summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrl.cpp36
-rw-r--r--indra/llui/llaccordionctrl.h3
-rw-r--r--indra/llui/llaccordionctrltab.cpp39
-rw-r--r--indra/llui/llaccordionctrltab.h1
-rw-r--r--indra/llui/llbutton.cpp12
-rw-r--r--indra/llui/llbutton.h1
-rw-r--r--indra/llui/llcallbackmap.h3
-rw-r--r--indra/llui/llcheckboxctrl.cpp30
-rw-r--r--indra/llui/lldockablefloater.cpp17
-rw-r--r--indra/llui/lldockablefloater.h7
-rw-r--r--indra/llui/llflatlistview.cpp21
-rw-r--r--indra/llui/llfloater.cpp8
-rw-r--r--indra/llui/llfloater.h2
-rw-r--r--indra/llui/lllocalcliprect.cpp48
-rw-r--r--indra/llui/lllocalcliprect.h26
-rw-r--r--indra/llui/llmenugl.cpp15
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llui/llpanel.cpp66
-rw-r--r--indra/llui/llpanel.h4
-rw-r--r--indra/llui/llresmgr.cpp4
-rw-r--r--indra/llui/llscrolllistctrl.cpp23
-rw-r--r--indra/llui/llsdparam.cpp116
-rw-r--r--indra/llui/llsdparam.h12
-rw-r--r--indra/llui/lltextbase.cpp83
-rw-r--r--indra/llui/lltextbase.h21
-rw-r--r--indra/llui/lltexteditor.cpp7
-rw-r--r--indra/llui/llui.cpp400
-rw-r--r--indra/llui/llui.h2
-rw-r--r--indra/llui/lluictrl.h4
-rw-r--r--indra/llui/lluictrlfactory.cpp7
-rw-r--r--indra/llui/lluistring.cpp19
-rw-r--r--indra/llui/lluistring.h9
-rw-r--r--indra/llui/llurlentry.cpp19
-rw-r--r--indra/llui/llurlentry.h5
-rw-r--r--indra/llui/llurlmatch.cpp6
-rw-r--r--indra/llui/llurlmatch.h6
-rw-r--r--indra/llui/llurlregistry.cpp6
-rw-r--r--indra/llui/llview.cpp62
-rw-r--r--indra/llui/llview.h7
39 files changed, 714 insertions, 445 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index 673631f99a..c3ef734823 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -765,6 +765,17 @@ S32 LLAccordionCtrl::notifyParent(const LLSD& info)
}
return 0;
}
+ else if(str_action == "deselect_current")
+ {
+ // Reset selection to the currently selected tab.
+ if (mSelectedTab)
+ {
+ mSelectedTab->setSelected(false);
+ mSelectedTab = NULL;
+ return 1;
+ }
+ return 0;
+ }
}
else if (info.has("scrollToShowRect"))
{
@@ -811,6 +822,31 @@ void LLAccordionCtrl::reset ()
mScrollbar->setDocPos(0);
}
+void LLAccordionCtrl::expandDefaultTab()
+{
+ if (mAccordionTabs.size() > 0)
+ {
+ LLAccordionCtrlTab* tab = mAccordionTabs.front();
+
+ if (!tab->getDisplayChildren())
+ {
+ tab->setDisplayChildren(true);
+ }
+
+ for (size_t i = 1; i < mAccordionTabs.size(); ++i)
+ {
+ tab = mAccordionTabs[i];
+
+ if (tab->getDisplayChildren())
+ {
+ tab->setDisplayChildren(false);
+ }
+ }
+
+ arrange();
+ }
+}
+
void LLAccordionCtrl::sort()
{
if (!mTabComparator)
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
index b5fdf796cd..f26a380e5f 100644
--- a/indra/llui/llaccordionctrl.h
+++ b/indra/llui/llaccordionctrl.h
@@ -122,6 +122,7 @@ public:
S32 notifyParent(const LLSD& info);
void reset ();
+ void expandDefaultTab();
void setComparator(const LLTabComparator* comp) { mTabComparator = comp; }
void sort();
@@ -140,6 +141,8 @@ public:
const LLAccordionCtrlTab* getSelectedTab() const { return mSelectedTab; }
+ bool getFitParent() const {return mFitParent;}
+
private:
void initNoTabsWidget(const LLTextBox::Params& tb_params);
void updateNoTabsHelpTextVisibility();
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 0cccd4e6de..84716394e6 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -33,6 +33,7 @@
#include "linden_common.h"
#include "llaccordionctrltab.h"
+#include "llaccordionctrl.h"
#include "lllocalcliprect.h"
#include "llscrollbar.h"
@@ -372,9 +373,11 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p)
mHeader = LLUICtrlFactory::create<LLAccordionCtrlTabHeader>(headerParams);
addChild(mHeader, 1);
- if (mSelectionEnabled)
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
+
+ if (!p.selection_enabled)
{
- LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLAccordionCtrlTab::selectOnFocusReceived, this));
+ LLFocusableElement::setFocusLostCallback(boost::bind(&LLAccordionCtrlTab::deselectOnFocusLost, this));
}
reshape(100, 200,FALSE);
@@ -599,6 +602,15 @@ void LLAccordionCtrlTab::selectOnFocusReceived()
getParent()->notifyParent(LLSD().with("action", "select_current"));
}
+void LLAccordionCtrlTab::deselectOnFocusLost()
+{
+ if(getParent()) // A parent may not be set if tabs are added dynamically.
+ {
+ getParent()->notifyParent(LLSD().with("action", "deselect_current"));
+ }
+
+}
+
S32 LLAccordionCtrlTab::getHeaderHeight()
{
return mHeaderVisible?HEADER_HEIGHT:0;
@@ -699,7 +711,7 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
setRect(panel_rect);
}
- //LLAccordionCtrl should rearrange accodion tab if one of accordion change its size
+ //LLAccordionCtrl should rearrange accordion tab if one of accordion change its size
if (getParent()) // A parent may not be set if tabs are added dynamically.
getParent()->notifyParent(info);
return 1;
@@ -710,6 +722,27 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
return 1;
}
}
+ else if (info.has("scrollToShowRect"))
+ {
+ LLAccordionCtrl* parent = dynamic_cast<LLAccordionCtrl*>(getParent());
+ if (parent && parent->getFitParent())
+ {
+ // EXT-8285 ('No attachments worn' text appears at the bottom of blank 'Attachments' accordion)
+ // The problem was in passing message "scrollToShowRect" IN LLAccordionCtrlTab::notifyParent
+ // FROM child LLScrollContainer TO parent LLAccordionCtrl with "it_parent" set to true.
+
+ // It is wrong notification for parent accordion which leads to recursive call of adjustContainerPanel
+ // As the result of recursive call of adjustContainerPanel we got LLAccordionCtrlTab
+ // that reshaped and re-sized with different rectangles.
+
+ // LLAccordionCtrl has own scrollContainer and LLAccordionCtrlTab has own scrollContainer
+ // both should handle own scroll container's event.
+ // So, if parent accordion "fit_parent" accordion tab should handle its scroll container events itself.
+
+ return 1;
+ }
+ }
+
return LLUICtrl::notifyParent(info);
}
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index 1344ce0a30..00fb276f19 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -220,6 +220,7 @@ protected:
LLView* findContainerView ();
void selectOnFocusReceived();
+ void deselectOnFocusLost();
private:
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index aeedf62379..5a4f0515fc 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -120,6 +120,7 @@ LLButton::LLButton(const LLButton::Params& p)
mFlashing( FALSE ),
mCurGlowStrength(0.f),
mNeedsHighlight(FALSE),
+ mMouseOver(false),
mUnselectedLabel(p.label()),
mSelectedLabel(p.label_selected()),
mGLFont(p.font),
@@ -504,7 +505,11 @@ void LLButton::onMouseEnter(S32 x, S32 y, MASK mask)
LLUICtrl::onMouseEnter(x, y, mask);
if (isInEnabledChain())
+ {
mNeedsHighlight = TRUE;
+ }
+
+ mMouseOver = true;
}
void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
@@ -512,6 +517,7 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
LLUICtrl::onMouseLeave(x, y, mask);
mNeedsHighlight = FALSE;
+ mMouseOver = true;
}
void LLButton::setHighlight(bool b)
@@ -565,14 +571,10 @@ void LLButton::draw()
}
// Unselected image assignments
- S32 local_mouse_x;
- S32 local_mouse_y;
- LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y);
-
bool enabled = isInEnabledChain();
bool pressed = pressed_by_keyboard
- || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
+ || (hasMouseCapture() && mMouseOver)
|| mForcePressedState;
bool selected = getToggleState();
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index f4af19b696..5f25084b35 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -356,6 +356,7 @@ private:
BOOL mCommitOnReturn;
BOOL mFadeWhenDisabled;
bool mForcePressedState;
+ bool mMouseOver;
LLFrameTimer mFlashingTimer;
};
diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h
index 97b1e2fc50..60c4fc6b6d 100644
--- a/indra/llui/llcallbackmap.h
+++ b/indra/llui/llcallbackmap.h
@@ -35,12 +35,13 @@
#include <map>
#include <string>
+#include <boost/function.hpp>
class LLCallbackMap
{
public:
// callback definition.
- typedef void* (*callback_t)(void* data);
+ typedef boost::function<void* (void* data)> callback_t;
typedef std::map<std::string, LLCallbackMap> map_t;
typedef map_t::iterator map_iter_t;
diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp
index 3d32157406..0c524cd470 100644
--- a/indra/llui/llcheckboxctrl.cpp
+++ b/indra/llui/llcheckboxctrl.cpp
@@ -81,17 +81,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
// must be big enough to hold all children
setUseBoundingRect(TRUE);
- // Label (add a little space to make sure text actually renders)
- const S32 FUDGE = 10;
- S32 text_width = mFont->getWidth( p.label ) + FUDGE;
- S32 text_height = llround(mFont->getLineHeight());
- LLRect label_rect;
- label_rect.setOriginAndSize(
- llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
- llcheckboxctrl_vpad + 1, // padding to get better alignment
- text_width + llcheckboxctrl_hpad,
- text_height );
-
// *HACK Get rid of this with SL-55508...
// this allows blank check boxes and radio boxes for now
std::string local_label = p.label;
@@ -101,7 +90,6 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
}
LLTextBox::Params tbparams = p.label_text;
- tbparams.rect(label_rect);
tbparams.initial_value(local_label);
if (p.font.isProvided())
{
@@ -111,6 +99,17 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
mLabel = LLUICtrlFactory::create<LLTextBox> (tbparams);
addChild(mLabel);
+ S32 text_width = mLabel->getTextBoundingRect().getWidth();
+ S32 text_height = llround(mFont->getLineHeight());
+ LLRect label_rect;
+ label_rect.setOriginAndSize(
+ llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing,
+ llcheckboxctrl_vpad + 1, // padding to get better alignment
+ text_width + llcheckboxctrl_hpad,
+ text_height );
+ mLabel->setShape(label_rect);
+
+
// Button
// Note: button cover the label by extending all the way to the right.
LLRect btn_rect;
@@ -190,8 +189,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
static LLUICachedControl<S32> llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0);
static LLUICachedControl<S32> llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0);
- const S32 FUDGE = 10;
- S32 text_width = mFont->getWidth( mLabel->getText() ) + FUDGE;
+ S32 text_width = mLabel->getTextBoundingRect().getWidth();
S32 text_height = llround(mFont->getLineHeight());
LLRect label_rect;
label_rect.setOriginAndSize(
@@ -199,7 +197,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llcheckboxctrl_vpad,
text_width,
text_height );
- mLabel->setRect(label_rect);
+ mLabel->setShape(label_rect);
LLRect btn_rect;
btn_rect.setOriginAndSize(
@@ -207,7 +205,7 @@ void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
llcheckboxctrl_vpad,
llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width,
llmax( text_height, llcheckboxctrl_btn_size() ) );
- mButton->setRect( btn_rect );
+ mButton->setShape( btn_rect );
LLUICtrl::reshape(width, height, called_from_parent);
}
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 3d8670fef2..f9983278d1 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -49,12 +49,13 @@ void LLDockableFloater::init(LLDockableFloater* thiz)
thiz->setCanClose(TRUE);
thiz->setCanDock(true);
thiz->setCanMinimize(TRUE);
+ thiz->setOverlapsScreenChannel(false);
+ thiz->mForceDocking = false;
}
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl), mUniqueDocking(true)
- , mOverlapsScreenChannel(false)
{
init(this);
mUseTongue = true;
@@ -81,6 +82,12 @@ LLDockableFloater::~LLDockableFloater()
BOOL LLDockableFloater::postBuild()
{
+ // Remember we should force docking when the floater is opened for the first time
+ if (mIsDockedStateForcedCallback != NULL && mIsDockedStateForcedCallback())
+ {
+ mForceDocking = true;
+ }
+
mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
LLFloater::setDocked(true);
return LLView::postBuild();
@@ -134,6 +141,14 @@ void LLDockableFloater::resetInstance()
void LLDockableFloater::setVisible(BOOL visible)
{
+ // Force docking if requested
+ if (visible && mForceDocking)
+ {
+ setCanDock(true);
+ setDocked(true);
+ mForceDocking = false;
+ }
+
if(visible && isDocked())
{
resetInstance();
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 2b1ce99ae2..054d59b984 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -130,6 +130,10 @@ protected:
void setDockControl(LLDockControl* dockControl);
const LLUIImagePtr& getDockTongue();
+ // Checks if docking should be forced.
+ // It may be useful e.g. if floater created in mouselook mode (see EXT-5609)
+ boost::function<BOOL ()> mIsDockedStateForcedCallback;
+
private:
std::auto_ptr<LLDockControl> mDockControl;
LLUIImagePtr mDockTongue;
@@ -143,6 +147,9 @@ private:
bool mUseTongue;
bool mOverlapsScreenChannel;
+
+ // Force docking when the floater is being shown for the first time.
+ bool mForceDocking;
};
#endif /* LL_DOCKABLEFLOATER_H */
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 90c6f15d23..70558f8eb8 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -615,7 +615,7 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
//only CTRL usage allows to deselect an item, usual clicking on an item cannot deselect it
if (mask & MASK_CONTROL)
- selectItemPair(item_pair, select_item);
+ selectItemPair(item_pair, select_item);
else
selectItemPair(item_pair, true);
}
@@ -1078,25 +1078,6 @@ void LLFlatListView::setNoItemsCommentVisible(bool visible) const
{
if (mNoItemsCommentTextbox)
{
- if (visible)
- {
-/*
-// *NOTE: MA 2010-02-04
-// Deprecated after params of the comment text box were moved into widget (flat_list_view.xml)
-// can be removed later if nothing happened.
- // We have to update child rect here because of issues with rect after reshaping while creating LLTextbox
- // It is possible to have invalid LLRect if Flat List is in LLAccordionTab
- LLRect comment_rect = getLocalRect();
-
- // To see comment correctly (EXT - 3244) in mNoItemsCommentTextbox we must get border width
- // of LLFlatListView (@see getBorderWidth()) and stretch mNoItemsCommentTextbox to this width
- // But getBorderWidth() returns 0 if LLFlatListView not visible. So we have to get border width
- // from 'scroll_border'
- LLViewBorder* scroll_border = getChild<LLViewBorder>("scroll border");
- comment_rect.stretch(-scroll_border->getBorderWidth());
- mNoItemsCommentTextbox->setRect(comment_rect);
-*/
- }
mSelectedItemsBorder->setVisible(!visible);
mNoItemsCommentTextbox->setVisible(visible);
}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 39a6855273..22d6f6ca52 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -451,6 +451,14 @@ void LLFloater::enableResizeCtrls(bool enable)
}
}
+void LLFloater::destroy()
+{
+ // LLFloaterReg should be synchronized with "dead" floater to avoid returning dead instance before
+ // it was deleted via LLMortician::updateClass(). See EXT-8458.
+ LLFloaterReg::removeInstance(mInstanceName, mKey);
+ die();
+}
+
// virtual
LLFloater::~LLFloater()
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 3ea035777c..42f422f91c 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -308,7 +308,7 @@ protected:
BOOL getAutoFocus() const { return mAutoFocus; }
LLDragHandle* getDragHandle() const { return mDragHandle; }
- void destroy() { die(); } // Don't call this directly. You probably want to call closeFloater()
+ void destroy(); // Don't call this directly. You probably want to call closeFloater()
virtual void onClickCloseBtn();
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
index 43c21e250c..805d5879f7 100644
--- a/indra/llui/lllocalcliprect.cpp
+++ b/indra/llui/lllocalcliprect.cpp
@@ -33,33 +33,8 @@
#include "lllocalcliprect.h"
#include "llfontgl.h"
-#include "llgl.h"
#include "llui.h"
-#include <stack>
-
-//---------------------------------------------------------------------------
-// LLScreenClipRect
-// implementation class in screen space
-//---------------------------------------------------------------------------
-class LLScreenClipRect
-{
-public:
- LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
- virtual ~LLScreenClipRect();
-
-private:
- static void pushClipRect(const LLRect& rect);
- static void popClipRect();
- static void updateScissorRegion();
-
-private:
- LLGLState mScissorState;
- BOOL mEnabled;
-
- static std::stack<LLRect> sClipRectStack;
-};
-
/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
@@ -70,9 +45,9 @@ LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled)
if (mEnabled)
{
pushClipRect(rect);
+ mScissorState.setEnabled(!sClipRectStack.empty());
+ updateScissorRegion();
}
- mScissorState.setEnabled(!sClipRectStack.empty());
- updateScissorRegion();
}
LLScreenClipRect::~LLScreenClipRect()
@@ -80,8 +55,8 @@ LLScreenClipRect::~LLScreenClipRect()
if (mEnabled)
{
popClipRect();
+ updateScissorRegion();
}
- updateScissorRegion();
}
//static
@@ -131,16 +106,11 @@ void LLScreenClipRect::updateScissorRegion()
// LLLocalClipRect
//---------------------------------------------------------------------------
LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
-{
- LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX,
- rect.mTop + LLFontGL::sCurOrigin.mY,
- rect.mRight + LLFontGL::sCurOrigin.mX,
- rect.mBottom + LLFontGL::sCurOrigin.mY);
- mScreenClipRect = new LLScreenClipRect(screen, enabled);
-}
+: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
+{}
LLLocalClipRect::~LLLocalClipRect()
-{
- delete mScreenClipRect;
- mScreenClipRect = NULL;
-}
+{}
diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h
index cd0c55ca72..36413f1496 100644
--- a/indra/llui/lllocalcliprect.h
+++ b/indra/llui/lllocalcliprect.h
@@ -31,7 +31,9 @@
#ifndef LLLOCALCLIPRECT_H
#define LLLOCALCLIPRECT_H
+#include "llgl.h"
#include "llrect.h" // can't forward declare, it's templated
+#include <stack>
// Clip rendering to a specific rectangle using GL scissor
// Just create one of these on the stack:
@@ -39,15 +41,29 @@
// LLLocalClipRect(rect);
// draw();
// }
-class LLLocalClipRect
+class LLScreenClipRect
{
public:
- LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
- ~LLLocalClipRect();
+ LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLScreenClipRect();
+
+private:
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
+ static void updateScissorRegion();
private:
- // implementation class
- class LLScreenClipRect* mScreenClipRect;
+ LLGLState mScissorState;
+ BOOL mEnabled;
+
+ static std::stack<LLRect> sClipRectStack;
+};
+
+class LLLocalClipRect : public LLScreenClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ ~LLLocalClipRect();
};
#endif
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index b4a1bcb7c5..12007f7b52 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -218,6 +218,12 @@ void LLMenuItemGL::setValue(const LLSD& value)
}
//virtual
+LLSD LLMenuItemGL::getValue() const
+{
+ return getLabel();
+}
+
+//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
if( getEnabled() && (!gKeyboard->getKeyRepeated(key) || mAllowKeyRepeat) && (key == mAcceleratorKey) && (mask == (mAcceleratorMask & MASK_NORMALKEYS)) )
@@ -922,6 +928,15 @@ void LLMenuItemCheckGL::setValue(const LLSD& value)
}
}
+//virtual
+LLSD LLMenuItemCheckGL::getValue() const
+{
+ // Get our boolean value from the view model.
+ // If we don't override this method then the implementation from
+ // LLMenuItemGL will return a string. (EXT-8501)
+ return LLUICtrl::getValue();
+}
+
// called to rebuild the draw label
void LLMenuItemCheckGL::buildDrawLabel( void )
{
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 7668f301ea..bf40163dac 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -95,6 +95,7 @@ public:
// LLUICtrl overrides
/*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ LLSD getValue() const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
@@ -321,6 +322,7 @@ public:
virtual void onCommit( void );
virtual void setValue(const LLSD& value);
+ virtual LLSD getValue() const;
// called to rebuild the draw label
virtual void buildDrawLabel( void );
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 9ebdcb87c6..0f769bd6dc 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -661,7 +661,7 @@ void LLPanel::childSetEnabled(const std::string& id, bool enabled)
void LLPanel::childSetTentative(const std::string& id, bool tentative)
{
- LLView* child = findChild<LLView>(id);
+ LLUICtrl* child = findChild<LLUICtrl>(id);
if (child)
{
child->setTentative(tentative);
@@ -860,13 +860,16 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
return NULL;
}
-static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
+LLPanel* LLPanel::childGetVisibleTabWithHelp()
{
LLView *child;
- // look through immediate children first for an active tab with help
- for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
+ bfs_tree_iterator_t it = beginTreeBFS();
+ // skip ourselves
+ ++it;
+ for (; it != endTreeBFS(); ++it)
{
+ child = *it;
LLPanel *curTabPanel = NULL;
// do we have a tab container?
@@ -890,36 +893,21 @@ static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
}
}
- // then try a bit harder and recurse through all children
- for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
- {
- if (child->getVisible())
- {
- LLPanel* tab = ::childGetVisibleTabWithHelp(child);
- if (tab)
- {
- return tab;
- }
- }
- }
-
// couldn't find any active tabs with a help topic string
return NULL;
}
-LLPanel *LLPanel::childGetVisibleTabWithHelp()
-{
- // find a visible tab with a help topic (to determine help context)
- return ::childGetVisibleTabWithHelp(this);
-}
-static LLPanel *childGetVisiblePanelWithHelp(LLView *parent)
+LLPanel *LLPanel::childGetVisiblePanelWithHelp()
{
LLView *child;
- // look through immediate children first for an active panel with help
- for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
+ bfs_tree_iterator_t it = beginTreeBFS();
+ // skip ourselves
+ ++it;
+ for (; it != endTreeBFS(); ++it)
{
+ child = *it;
// do we have a panel with a help topic?
LLPanel *panel = dynamic_cast<LLPanel *>(child);
if (panel && panel->getVisible() && !panel->getHelpTopic().empty())
@@ -928,39 +916,19 @@ static LLPanel *childGetVisiblePanelWithHelp(LLView *parent)
}
}
- // then try a bit harder and recurse through all children
- for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
- {
- if (child->getVisible())
- {
- LLPanel* panel = ::childGetVisiblePanelWithHelp(child);
- if (panel)
- {
- return panel;
- }
- }
- }
-
// couldn't find any active panels with a help topic string
return NULL;
}
-LLPanel *LLPanel::childGetVisiblePanelWithHelp()
+void LLPanel::childSetAction(const std::string& id, const commit_signal_t::slot_type& function)
{
- // find a visible tab with a help topic (to determine help context)
- return ::childGetVisiblePanelWithHelp(this);
-}
-
-void LLPanel::childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) )
-{
- LLLineEditor* child = findChild<LLLineEditor>(id);
- if (child)
+ LLButton* button = findChild<LLButton>(id);
+ if (button)
{
- child->setPrevalidate(func);
+ button->setClickedCallback(function);
}
}
-
void LLPanel::childSetAction(const std::string& id, boost::function<void(void*)> function, void* value)
{
LLButton* button = findChild<LLButton>(id);
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 03e3dc0c0e..784054cd86 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -170,6 +170,7 @@ public:
std::string getString(const std::string& name) const;
// ** Wrappers for setting child properties by name ** -TomY
+ // WARNING: These are deprecated, please use getChild<T>("name")->doStuff() idiom instead
// LLView
void childSetVisible(const std::string& name, bool visible);
@@ -233,7 +234,8 @@ public:
void childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) );
// LLButton
- void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value = NULL);
+ void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value);
+ void childSetAction(const std::string& id, const commit_signal_t::slot_type& function);
// LLTextBox
void childSetActionTextbox(const std::string& id, boost::function<void(void*)> function, void* value = NULL);
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index ed870d46d5..9158bc70f5 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -298,11 +298,11 @@ void LLResMgr::getIntegerString( std::string& output, S32 input ) const
{
if (fraction == remaining_count)
{
- fraction_string = llformat("%d%c", fraction, getThousandsSeparator());
+ fraction_string = llformat_to_utf8("%d%c", fraction, getThousandsSeparator());
}
else
{
- fraction_string = llformat("%3.3d%c", fraction, getThousandsSeparator());
+ fraction_string = llformat_to_utf8("%3.3d%c", fraction, getThousandsSeparator());
}
output = fraction_string + output;
}
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index d4d161f2c9..9ab2cfef4b 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -541,23 +541,7 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
setNeedsSort();
break;
- case ADD_SORTED:
- {
- // sort by column 0, in ascending order
- std::vector<sort_column_t> single_sort_column;
- single_sort_column.push_back(std::make_pair(0, TRUE));
-
- mItemList.push_back(item);
- std::stable_sort(
- mItemList.begin(),
- mItemList.end(),
- SortScrollListItem(single_sort_column,mSortCallback));
-
- // ADD_SORTED just sorts by first column...
- // this might not match user sort criteria, so flag list as being in unsorted state
- setNeedsSort();
- break;
- }
+ case ADD_DEFAULT:
case ADD_BOTTOM:
mItemList.push_back(item);
setNeedsSort();
@@ -2762,9 +2746,10 @@ LLScrollListColumn* LLScrollListCtrl::getColumn(const std::string& name)
return NULL;
}
-
+LLFastTimer::DeclareTimer FTM_ADD_SCROLLLIST_ELEMENT("Add Scroll List Item");
LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
{
+ LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
LLScrollListItem::Params item_params;
LLParamSDParser::instance().readSD(element, item_params);
item_params.userdata = userdata;
@@ -2773,12 +2758,14 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition
LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)
{
+ LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
LLScrollListItem *new_item = new LLScrollListItem(item_p);
return addRow(new_item, item_p, pos);
}
LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos)
{
+ LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
if (!item_p.validateBlock() || !new_item) return NULL;
new_item->setNumColumns(mColumns.size());
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 4bb45a3065..7d37127584 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -43,33 +43,16 @@ LLParamSDParser::LLParamSDParser()
{
using boost::bind;
- registerParserFuncs<S32>(bind(&LLParamSDParser::readTypedValue<S32>, this, _1, &LLSD::asInteger),
- bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
- registerParserFuncs<U32>(bind(&LLParamSDParser::readTypedValue<U32>, this, _1, &LLSD::asInteger),
- bind(&LLParamSDParser::writeU32Param, this, _1, _2));
- registerParserFuncs<F32>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asReal),
- bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
- registerParserFuncs<F64>(bind(&LLParamSDParser::readTypedValue<F64>, this, _1, &LLSD::asReal),
- bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
- registerParserFuncs<bool>(bind(&LLParamSDParser::readTypedValue<F32>, this, _1, &LLSD::asBoolean),
- bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
- registerParserFuncs<std::string>(bind(&LLParamSDParser::readTypedValue<std::string>, this, _1, &LLSD::asString),
- bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
- registerParserFuncs<LLUUID>(bind(&LLParamSDParser::readTypedValue<LLUUID>, this, _1, &LLSD::asUUID),
- bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
- registerParserFuncs<LLDate>(bind(&LLParamSDParser::readTypedValue<LLDate>, this, _1, &LLSD::asDate),
- bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
- registerParserFuncs<LLURI>(bind(&LLParamSDParser::readTypedValue<LLURI>, this, _1, &LLSD::asURI),
- bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
- registerParserFuncs<LLSD>(bind(&LLParamSDParser::readSDParam, this, _1),
- bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
-}
-
-bool LLParamSDParser::readSDParam(void* value_ptr)
-{
- if (!mCurReadSD) return false;
- *((LLSD*)value_ptr) = *mCurReadSD;
- return true;
+ registerParserFuncs<S32>(readS32, bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
+ registerParserFuncs<U32>(readU32, bind(&LLParamSDParser::writeU32Param, this, _1, _2));
+ registerParserFuncs<F32>(readF32, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+ registerParserFuncs<F64>(readF64, bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
+ registerParserFuncs<bool>(readBool, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+ registerParserFuncs<std::string>(readString, bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
+ registerParserFuncs<LLUUID>(readUUID, bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
+ registerParserFuncs<LLDate>(readDate, bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
+ registerParserFuncs<LLURI>(readURI, bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
+ registerParserFuncs<LLSD>(readSD, bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
}
// special case handling of U32 due to ambiguous LLSD::assign overload
@@ -148,3 +131,82 @@ LLSD* LLParamSDParser::getSDWriteNode(const parser_t::name_stack_t& name_stack)
return mWriteSD;
}
+bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((S32*)val_ptr) = self.mCurReadSD->asInteger();
+ return true;
+}
+
+bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((U32*)val_ptr) = self.mCurReadSD->asInteger();
+ return true;
+}
+
+bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((F32*)val_ptr) = self.mCurReadSD->asReal();
+ return true;
+}
+
+bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((F64*)val_ptr) = self.mCurReadSD->asReal();
+ return true;
+}
+
+bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((bool*)val_ptr) = self.mCurReadSD->asBoolean();
+ return true;
+}
+
+bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((std::string*)val_ptr) = self.mCurReadSD->asString();
+ return true;
+}
+
+bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
+ return true;
+}
+
+bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLDate*)val_ptr) = self.mCurReadSD->asDate();
+ return true;
+}
+
+bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLURI*)val_ptr) = self.mCurReadSD->asURI();
+ return true;
+}
+
+bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
+{
+ LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
+
+ *((LLSD*)val_ptr) = *self.mCurReadSD;
+ return true;
+}
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index 12f28f876f..71b0a45630 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -79,9 +79,19 @@ private:
LLSD* getSDWriteNode(const parser_t::name_stack_t& name_stack);
- bool readSDParam(void* value_ptr);
bool writeU32Param(const void* value_ptr, const parser_t::name_stack_t& name_stack);
+ static bool readS32(Parser& parser, void* val_ptr);
+ static bool readU32(Parser& parser, void* val_ptr);
+ static bool readF32(Parser& parser, void* val_ptr);
+ static bool readF64(Parser& parser, void* val_ptr);
+ static bool readBool(Parser& parser, void* val_ptr);
+ static bool readString(Parser& parser, void* val_ptr);
+ static bool readUUID(Parser& parser, void* val_ptr);
+ static bool readDate(Parser& parser, void* val_ptr);
+ static bool readURI(Parser& parser, void* val_ptr);
+ static bool readSD(Parser& parser, void* val_ptr);
+
Parser::name_stack_t mNameStack;
const LLSD* mCurReadSD;
LLSD* mWriteSD;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 617c496d6a..cde08c7b19 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1012,21 +1012,26 @@ void LLTextBase::draw()
if (mBGVisible)
{
// clip background rect against extents, if we support scrolling
- LLLocalClipRect clip(doc_rect, mScroller != NULL);
-
+ LLRect bg_rect = mVisibleTextRect;
+ if (mScroller)
+ {
+ bg_rect.intersectWith(doc_rect);
+ }
LLColor4 bg_color = mReadOnly
? mReadOnlyBgColor.get()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(mVisibleTextRect, bg_color, TRUE);
+ gl_rect_2d(doc_rect, bg_color, TRUE);
}
// draw document view
LLUICtrl::draw();
{
- // only clip if we support scrolling (mScroller != NULL)
+ // only clip if we support scrolling...
+ // since convention is that text boxes never vertically truncate their contents
+ // regardless of rect bounds
LLLocalClipRect clip(doc_rect, mScroller != NULL);
drawSelectionBackground();
drawText();
@@ -1490,23 +1495,32 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg
LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
{
+ static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
+
if (index > getLength()) { return mSegments.end(); }
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
- segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ //FIXME: avoid operator new somehow (without running into refcount problems)
+ index_segment->setStart(index);
+ index_segment->setEnd(index);
+ segment_set_t::iterator it = mSegments.upper_bound(index_segment);
return it;
}
LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 index) const
{
+ static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment();
+
if (index > getLength()) { return mSegments.end(); }
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
- LLTextBase::segment_set_t::const_iterator it = mSegments.upper_bound(new LLIndexSegment(index));
+ index_segment->setStart(index);
+ index_segment->setEnd(index);
+ LLTextBase::segment_set_t::const_iterator it = mSegments.upper_bound(index_segment);
return it;
}
@@ -1642,7 +1656,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
}
else
{
- appendAndHighlightText(match.getLabel(), part, link_params);
+ appendAndHighlightText(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
// set the tooltip for the Url label
if (! match.getTooltip().empty())
@@ -1725,7 +1739,7 @@ void LLTextBase::appendWidget(const LLInlineViewSegment::Params& params, const s
insertStringNoUndo(getLength(), widget_wide_text, &segments);
}
-void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params)
+void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
{
// Save old state
S32 selection_start = mSelectionStart;
@@ -1756,7 +1770,17 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
S32 cur_length = getLength();
LLStyleConstSP sp(new LLStyle(highlight_params));
- LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
+ LLTextSegmentPtr segmentp;
+ if(underline_on_hover_only)
+ {
+ highlight_params.font.style("NORMAL");
+ LLStyleConstSP normal_sp(new LLStyle(highlight_params));
+ segmentp = new LLOnHoverChangeableTextSegment(sp, normal_sp, cur_length, cur_length + wide_text.size(), *this);
+ }
+ else
+ {
+ segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
+ }
segment_vec_t segments;
segments.push_back(segmentp);
insertStringNoUndo(cur_length, wide_text, &segments);
@@ -1771,7 +1795,17 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
S32 segment_start = old_length;
S32 segment_end = old_length + wide_text.size();
LLStyleConstSP sp(new LLStyle(style_params));
+ if (underline_on_hover_only)
+ {
+ LLStyle::Params normal_style_params(style_params);
+ normal_style_params.font.style("NORMAL");
+ LLStyleConstSP normal_sp(new LLStyle(normal_style_params));
+ segments.push_back(new LLOnHoverChangeableTextSegment(sp, normal_sp, segment_start, segment_end, *this ));
+ }
+ else
+ {
segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this ));
+ }
insertStringNoUndo(getLength(), wide_text, &segments);
}
@@ -1795,7 +1829,7 @@ void LLTextBase::appendAndHighlightTextImpl(const std::string &new_text, S32 hig
}
}
-void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params)
+void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only)
{
if (new_text.empty()) return;
@@ -1807,7 +1841,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
if(pos!=start)
{
std::string str = std::string(new_text,start,pos-start);
- appendAndHighlightTextImpl(str,highlight_part, style_params);
+ appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);
}
appendLineBreakSegment(style_params);
start = pos+1;
@@ -1815,7 +1849,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
}
std::string str = std::string(new_text,start,new_text.length()-start);
- appendAndHighlightTextImpl(str,highlight_part, style_params);
+ appendAndHighlightTextImpl(str,highlight_part, style_params, underline_on_hover_only);
}
@@ -2269,6 +2303,7 @@ void LLTextBase::updateRects()
// allow horizontal scrolling?
// if so, use entire width of text contents
// otherwise, stop at width of mVisibleTextRect
+ //FIXME: consider use of getWordWrap() instead
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();
@@ -2675,6 +2710,30 @@ void LLNormalTextSegment::dump() const
llendl;
}
+//
+// LLOnHoverChangeableTextSegment
+//
+
+LLOnHoverChangeableTextSegment::LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor ):
+ LLNormalTextSegment(normal_style, start, end, editor),
+ mHoveredStyle(style),
+ mNormalStyle(normal_style){}
+
+/*virtual*/
+F32 LLOnHoverChangeableTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
+{
+ F32 result = LLNormalTextSegment::draw(start, end, selection_start, selection_end, draw_rect);
+ mStyle = mNormalStyle;
+ return result;
+}
+
+/*virtual*/
+BOOL LLOnHoverChangeableTextSegment::handleHover(S32 x, S32 y, MASK mask)
+{
+ mStyle = mHoveredStyle;
+ return LLNormalTextSegment::handleHover(x, y, mask);
+}
+
//
// LLInlineViewSegment
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 86f0e55a1d..db010d1cf6 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -145,10 +145,25 @@ protected:
boost::signals2::connection mImageLoadedConnection;
};
+// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment)
+class LLOnHoverChangeableTextSegment : public LLNormalTextSegment
+{
+public:
+ LLOnHoverChangeableTextSegment( LLStyleConstSP style, LLStyleConstSP normal_style, S32 start, S32 end, LLTextBase& editor );
+ /*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
+protected:
+ // Style used for text when mouse pointer is over segment
+ LLStyleConstSP mHoveredStyle;
+ // Style used for text when mouse pointer is outside segment
+ LLStyleConstSP mNormalStyle;
+
+};
+
class LLIndexSegment : public LLTextSegment
{
public:
- LLIndexSegment(S32 pos) : LLTextSegment(pos, pos) {}
+ LLIndexSegment() : LLTextSegment(0, 0) {}
};
class LLInlineViewSegment : public LLTextSegment
@@ -443,7 +458,7 @@ protected:
S32 insertStringNoUndo(S32 pos, const LLWString &wstr, segment_vec_t* segments = NULL); // returns num of chars actually inserted
S32 removeStringNoUndo(S32 pos, S32 length);
S32 overwriteCharNoUndo(S32 pos, llwchar wc);
- void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep);
+ void appendAndHighlightText(const std::string &new_text, S32 highlight_part, const LLStyle::Params& stylep, bool underline_on_hover_only = false);
// manage segments
@@ -486,7 +501,7 @@ protected:
void replaceUrlLabel(const std::string &url, const std::string &label);
void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
- void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params);
+ void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
protected:
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 6781c23416..482a53e4af 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -461,8 +461,13 @@ S32 LLTextEditor::nextWordPos(S32 cursorPos) const
const LLTextSegmentPtr LLTextEditor::getPreviousSegment() const
{
+ static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment;
+
+ index_segment->setStart(mCursorPos);
+ index_segment->setEnd(mCursorPos);
+
// find segment index at character to left of cursor (or rightmost edge of selection)
- segment_set_t::const_iterator it = mSegments.lower_bound(new LLIndexSegment(mCursorPos));
+ segment_set_t::const_iterator it = mSegments.lower_bound(index_segment);
if (it != mSegments.end())
{
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 7f9dca08d2..5d8b628776 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -466,7 +466,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
}
-void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect)
+void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect)
{
stop_glerror();
@@ -476,36 +476,53 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
return;
}
+ // add in offset of current image to current ui translation
+ const LLVector3 ui_scale = gGL.getUIScale();
+ const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
+
+ F32 uv_width = uv_outer_rect.getWidth();
+ F32 uv_height = uv_outer_rect.getHeight();
+
// shrink scaling region to be proportional to clipped image region
- LLRectf scale_rect_uv(
- uv_rect.mLeft + (scale_rect.mLeft * uv_rect.getWidth()),
- uv_rect.mBottom + (scale_rect.mTop * uv_rect.getHeight()),
- uv_rect.mLeft + (scale_rect.mRight * uv_rect.getWidth()),
- uv_rect.mBottom + (scale_rect.mBottom * uv_rect.getHeight()));
-
- S32 image_natural_width = llround((F32)image->getWidth(0) * uv_rect.getWidth());
- S32 image_natural_height = llround((F32)image->getHeight(0) * uv_rect.getHeight());
-
- LLRect draw_rect(0, height, width, 0);
- LLRect draw_scale_rect(llround(scale_rect_uv.mLeft * (F32)image->getWidth(0)),
- llround(scale_rect_uv.mTop * (F32)image->getHeight(0)),
- llround(scale_rect_uv.mRight * (F32)image->getWidth(0)),
- llround(scale_rect_uv.mBottom * (F32)image->getHeight(0)));
- // scale fixed region of image to drawn region
- draw_scale_rect.mRight += width - image_natural_width;
- draw_scale_rect.mTop += height - image_natural_height;
-
- S32 border_shrink_width = llmax(0, draw_scale_rect.mLeft - draw_scale_rect.mRight);
- S32 border_shrink_height = llmax(0, draw_scale_rect.mBottom - draw_scale_rect.mTop);
-
- F32 shrink_width_ratio = scale_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - scale_rect.getWidth()));
- F32 shrink_height_ratio = scale_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - scale_rect.getHeight()));
-
- F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
- draw_scale_rect.mLeft = llround((F32)draw_scale_rect.mLeft * shrink_scale);
- draw_scale_rect.mTop = llround(lerp((F32)height, (F32)draw_scale_rect.mTop, shrink_scale));
- draw_scale_rect.mRight = llround(lerp((F32)width, (F32)draw_scale_rect.mRight, shrink_scale));
- draw_scale_rect.mBottom = llround((F32)draw_scale_rect.mBottom * shrink_scale);
+ LLRectf uv_center_rect(
+ uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
+ uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
+
+ F32 image_width = image->getWidth(0);
+ F32 image_height = image->getHeight(0);
+
+ S32 image_natural_width = llround(image_width * uv_width);
+ S32 image_natural_height = llround(image_height * uv_height);
+
+ LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
+ uv_center_rect.mTop * image_height,
+ uv_center_rect.mRight * image_width,
+ uv_center_rect.mBottom * image_height);
+
+ { // scale fixed region of image to drawn region
+ draw_center_rect.mRight += width - image_natural_width;
+ draw_center_rect.mTop += height - image_natural_height;
+
+ F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
+ F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
+
+ F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
+ F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
+
+ F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
+
+ draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]);
+ draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]);
+ draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]);
+ draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]);
+ }
+
+ LLRectf draw_outer_rect(ui_translation.mV[VX],
+ ui_translation.mV[VY] + height * ui_scale.mV[VY],
+ ui_translation.mV[VX] + width * ui_scale.mV[VX],
+ ui_translation.mV[VY]);
LLGLSUIDefault gls_ui;
@@ -515,136 +532,174 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
}
- gGL.pushUIMatrix();
- {
- gGL.translateUI((F32)x, (F32)y, 0.f);
+ gGL.getTexUnit(0)->bind(image);
- gGL.getTexUnit(0)->bind(image);
+ gGL.color4fv(color.mV);
+
+ const S32 NUM_VERTICES = 9 * 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
- gGL.color4fv(color.mV);
-
- gGL.begin(LLRender::QUADS);
- {
- // draw bottom left
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2i(0, 0);
+ S32 index = 0;
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, 0);
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(0, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- // draw bottom middle
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, 0);
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, 0);
+ // draw bottom middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- // draw bottom right
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, 0);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2i(width, 0);
+ // draw bottom right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(width, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- // draw left
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(0, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ // draw left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(0, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- // draw middle
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ // draw middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- // draw right
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(width, draw_scale_rect.mBottom);
+ // draw right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(width, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- // draw top left
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(0, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ // draw top left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, height);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2i(0, height);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
- // draw top middle
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ // draw top middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, height);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, height);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
- // draw top right
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(width, draw_scale_rect.mTop);
+ // draw top right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2i(width, height);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, height);
- }
- gGL.end();
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
}
- gGL.popUIMatrix();
+ gGL.end();
if (solid_color)
{
@@ -674,25 +729,40 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
if (degrees == 0.f)
{
- gGL.pushUIMatrix();
- gGL.translateUI((F32)x, (F32)y, 0.f);
-
+ const S32 NUM_VERTICES = 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
gGL.begin(LLRender::QUADS);
{
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2i(width, height );
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2i(0, height );
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2i(0, 0);
-
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2i(width, 0);
+ LLVector3 ui_scale = gGL.getUIScale();
+ LLVector3 ui_translation = gGL.getUITranslation();
+ ui_translation.mV[VX] += x;
+ ui_translation.mV[VY] += y;
+ ui_translation.scaleVec(ui_scale);
+ S32 index = 0;
+ S32 scaled_width = llround(width * ui_scale.mV[VX]);
+ S32 scaled_height = llround(height * ui_scale.mV[VY]);
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
}
gGL.end();
- gGL.popUIMatrix();
}
else
{
@@ -761,25 +831,6 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL
LLUI::setLineWidth(1.f);
}
-
-void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom)
-{
- gGL.color4fv( LLColor4::white.mV );
- glLogicOp( GL_XOR );
- stop_glerror();
-
- gGL.begin(LLRender::QUADS);
- gGL.vertex2i(left, top);
- gGL.vertex2i(left, bottom);
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(right, top);
- gGL.end();
-
- glLogicOp( GL_COPY );
- stop_glerror();
-}
-
-
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
{
if (end_angle < start_angle)
@@ -1013,42 +1064,6 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians,
gGL.end();
}
-// Draws spokes around a circle.
-void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color)
-{
- const F32 DELTA = F_TWO_PI / count;
- const F32 HALF_DELTA = DELTA * 0.5f;
- const F32 SIN_DELTA = sin( DELTA );
- const F32 COS_DELTA = cos( DELTA );
-
- F32 x1 = outer_radius * cos( HALF_DELTA );
- F32 y1 = outer_radius * sin( HALF_DELTA );
- F32 x2 = inner_radius * cos( HALF_DELTA );
- F32 y2 = inner_radius * sin( HALF_DELTA );
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.begin( LLRender::LINES );
- {
- while( count-- )
- {
- gGL.color4fv(outer_color.mV);
- gGL.vertex2f( x1, y1 );
- gGL.color4fv(inner_color.mV);
- gGL.vertex2f( x2, y2 );
-
- F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
- y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
- x1 = x1_new;
-
- F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
- y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
- x2 = x2_new;
- }
- }
- gGL.end();
-}
-
void gl_rect_2d_simple_tex( S32 width, S32 height )
{
gGL.begin( LLRender::QUADS );
@@ -1236,6 +1251,7 @@ void gl_segmented_rect_2d_tex(const S32 left,
gGL.popUIMatrix();
}
+//FIXME: rewrite to use scissor?
void gl_segmented_rect_2d_fragment_tex(const S32 left,
const S32 top,
const S32 right,
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index c18262ef76..745d0ff662 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -96,7 +96,6 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
-void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
@@ -105,7 +104,6 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
-void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom);
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
void gl_rect_2d_simple_tex( S32 width, S32 height );
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 1f9d2c9049..259104f72c 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -147,8 +147,6 @@ public:
// LLView interface
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
/*virtual*/ BOOL isCtrl() const;
- /*virtual*/ void setTentative(BOOL b);
- /*virtual*/ BOOL getTentative() const;
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL canFocusChildren() const;
@@ -180,6 +178,8 @@ public:
void setMakeVisibleControlVariable(LLControlVariable* control);
void setMakeInvisibleControlVariable(LLControlVariable* control);
+ virtual void setTentative(BOOL b);
+ virtual BOOL getTentative() const;
virtual void setValue(const LLSD& value);
virtual LLSD getValue() const;
/// When two widgets are displaying the same data (e.g. during a skin
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index a46d961709..c5bd6c7fce 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -99,10 +99,11 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml";
LLXMLNodePtr root_node;
- if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
+ std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), filename);
+ if (!full_filename.empty())
{
- LLUICtrlFactory::instance().pushFileName(filename);
- LLXUIParser::instance().readXUI(root_node, block, filename);
+ LLUICtrlFactory::instance().pushFileName(full_filename);
+ LLSimpleXUIParser::instance().readXUI(full_filename, block);
LLUICtrlFactory::instance().popFileName();
}
}
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index ac9e71665f..e343df0063 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -40,7 +40,7 @@ LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
: mOrig(instring),
- mArgs(args)
+ mArgs(new LLStringUtil::format_map_t(args))
{
dirty();
}
@@ -54,7 +54,7 @@ void LLUIString::assign(const std::string& s)
void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
{
- mArgs = args;
+ getArgs() = args;
dirty();
}
@@ -74,7 +74,7 @@ void LLUIString::setArgs(const LLSD& sd)
void LLUIString::setArg(const std::string& key, const std::string& replacement)
{
- mArgs[key] = replacement;
+ getArgs()[key] = replacement;
dirty();
}
@@ -135,14 +135,14 @@ void LLUIString::updateResult() const
mResult = mOrig;
// get the defailt args + local args
- if (mArgs.empty())
+ if (!mArgs || mArgs->empty())
{
LLStringUtil::format(mResult, LLTrans::getDefaultArgs());
}
else
{
LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();
- combined_args.insert(mArgs.begin(), mArgs.end());
+ combined_args.insert(mArgs->begin(), mArgs->end());
LLStringUtil::format(mResult, combined_args);
}
}
@@ -153,3 +153,12 @@ void LLUIString::updateWResult() const
mWResult = utf8str_to_wstring(getUpdatedResult());
}
+
+LLStringUtil::format_map_t& LLUIString::getArgs()
+{
+ if (!mArgs)
+ {
+ mArgs = new LLStringUtil::format_map_t;
+ }
+ return *mArgs;
+}
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index 32cfc0d9cd..3f91856e26 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -64,9 +64,9 @@ class LLUIString
public:
// These methods all perform appropriate argument substitution
// and modify mOrig where appropriate
- LLUIString() : mNeedsResult(false), mNeedsWResult(false) {}
+ LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {}
LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args);
- LLUIString(const std::string& instring) { assign(instring); }
+ LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); }
void assign(const std::string& instring);
LLUIString& operator=(const std::string& s) { assign(s); return *this; }
@@ -86,7 +86,7 @@ public:
S32 length() const { return getUpdatedWResult().size(); }
void clear();
- void clearArgs() { mArgs.clear(); }
+ void clearArgs() { if (mArgs) mArgs->clear(); }
// These utility functions are included for text editing.
// They do not affect mOrig and do not perform argument substitution
@@ -105,11 +105,12 @@ private:
// do actual work of updating strings (non-inlined)
void updateResult() const;
void updateWResult() const;
+ LLStringUtil::format_map_t& getArgs();
std::string mOrig;
mutable std::string mResult;
mutable LLWString mWResult; // for displaying
- LLStringUtil::format_map_t mArgs;
+ LLStringUtil::format_map_t* mArgs;
// controls lazy evaluation
mutable bool mNeedsResult;
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e075699a6e..17d211fb36 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -363,6 +363,12 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
return LLTrans::getString("TooltipAgentUrl");
}
+bool LLUrlEntryAgent::underlineOnHoverOnly(const std::string &string) const
+{
+ std::string url = getUrl(string);
+ return LLStringUtil::endsWith(url, "/about");
+}
+
std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
if (!gCacheName)
@@ -730,6 +736,19 @@ std::string LLUrlEntrySLLabel::getTooltip(const std::string &string) const
return LLUrlEntryBase::getTooltip(string);
}
+bool LLUrlEntrySLLabel::underlineOnHoverOnly(const std::string &string) const
+{
+ std::string url = getUrl(string);
+ LLUrlMatch match;
+ if (LLUrlRegistry::instance().findUrl(url, match))
+ {
+ return match.underlineOnHoverOnly();
+ }
+
+ // unrecognized URL? should not happen
+ return LLUrlEntryBase::underlineOnHoverOnly(string);
+}
+
//
// LLUrlEntryWorldMap Describes secondlife:///<location> URLs
//
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 7d718b67a9..f8588dd760 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -94,6 +94,9 @@ public:
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
+ /// Should this link text be underlined only when mouse is hovered over it?
+ virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
+
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
protected:
@@ -173,6 +176,7 @@ public:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getTooltip(const std::string &string) const;
/*virtual*/ LLUUID getID(const std::string &string) const;
+ /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
private:
void onAgentNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, BOOL is_group);
@@ -275,6 +279,7 @@ public:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getTooltip(const std::string &string) const;
+ /*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
};
///
diff --git a/indra/llui/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index 7c96665ce4..a6d3dcb40f 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -43,7 +43,8 @@ LLUrlMatch::LLUrlMatch() :
mIcon(""),
mMenuName(""),
mLocation(""),
- mDisabledLink(false)
+ mDisabledLink(false),
+ mUnderlineOnHoverOnly(false)
{
}
@@ -51,7 +52,7 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, const LLUIColor& color,
const std::string &menu, const std::string &location,
- bool disabled_link, const LLUUID& id)
+ bool disabled_link, const LLUUID& id, bool underline_on_hover_only)
{
mStart = start;
mEnd = end;
@@ -64,4 +65,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLocation = location;
mDisabledLink = disabled_link;
mID = id;
+ mUnderlineOnHoverOnly = underline_on_hover_only;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index 78dd2c528f..7090dd3f93 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -86,12 +86,15 @@ public:
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
+ /// Should this link text be underlined only when mouse is hovered over it?
+ bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
+
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
const LLUIColor& color, const std::string &menu,
const std::string &location, bool disabled_link
- , const LLUUID& id );
+ , const LLUUID& id, bool underline_on_hover_only = false );
const LLUUID& getID() const { return mID;}
@@ -108,6 +111,7 @@ private:
LLUUID mID;
LLUIColor mColor;
bool mDisabledLink;
+ bool mUnderlineOnHoverOnly;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 1f86f72faa..b37a52cad2 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -184,7 +184,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->isLinkDisabled(),
- match_entry->getID(url));
+ match_entry->getID(url),
+ match_entry->underlineOnHoverOnly(url));
return true;
}
@@ -219,7 +220,8 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getMenuName(),
match.getLocation(),
match.isLinkDisabled(),
- match.getID());
+ match.getID(),
+ match.underlineOnHoverOnly());
return true;
}
return false;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 394ec957d5..4d3708302b 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -403,28 +403,40 @@ bool LLCompareByTabOrder::operator() (const LLView* const a, const LLView* const
return (a_score == b_score) ? a < b : a_score < b_score;
}
-bool LLView::trueToRoot(const boost::function<bool (const LLView*)>& predicate) const
+BOOL LLView::isInVisibleChain() const
{
- const LLView* cur_view = this;
- while(cur_view)
+ BOOL visible = TRUE;
+
+ const LLView* viewp = this;
+ while(viewp)
{
- if(!predicate(cur_view))
+ if (!viewp->getVisible())
{
- return false;
+ visible = FALSE;
+ break;
}
- cur_view = cur_view->getParent();
+ viewp = viewp->getParent();
}
- return true;
-}
-
-BOOL LLView::isInVisibleChain() const
-{
- return trueToRoot(&LLView::getVisible);
+
+ return visible;
}
BOOL LLView::isInEnabledChain() const
{
- return trueToRoot(&LLView::getEnabled);
+ BOOL enabled = TRUE;
+
+ const LLView* viewp = this;
+ while(viewp)
+ {
+ if (!viewp->getEnabled())
+ {
+ enabled = FALSE;
+ break;
+ }
+ viewp = viewp->getParent();
+ }
+
+ return enabled;
}
// virtual
@@ -434,17 +446,6 @@ BOOL LLView::canFocusChildren() const
}
//virtual
-void LLView::setTentative(BOOL b)
-{
-}
-
-//virtual
-BOOL LLView::getTentative() const
-{
- return FALSE;
-}
-
-//virtual
void LLView::setEnabled(BOOL enabled)
{
mEnabled = enabled;
@@ -2784,6 +2785,19 @@ LLView::tree_post_iterator_t LLView::endTreeDFSPost()
return tree_post_iterator_t();
}
+LLView::bfs_tree_iterator_t LLView::beginTreeBFS()
+{
+ return bfs_tree_iterator_t(this,
+ boost::bind(boost::mem_fn(&LLView::beginChild), _1),
+ boost::bind(boost::mem_fn(&LLView::endChild), _1));
+}
+
+LLView::bfs_tree_iterator_t LLView::endTreeBFS()
+{
+ // an empty iterator is an "end" iterator
+ return bfs_tree_iterator_t();
+}
+
LLView::root_to_view_iterator_t LLView::beginRootToView()
{
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 8e705ed701..37f5232f91 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -273,7 +273,6 @@ public:
S32 getDefaultTabGroup() const { return mDefaultTabGroup; }
S32 getLastTabGroup() { return mLastTabGroup; }
- bool trueToRoot(const boost::function<bool (const LLView*)>& predicate) const;
BOOL isInVisibleChain() const;
BOOL isInEnabledChain() const;
@@ -289,8 +288,6 @@ public:
// children, etc.
virtual void deleteAllChildren();
- virtual void setTentative(BOOL b);
- virtual BOOL getTentative() const;
void setAllChildrenEnabled(BOOL b);
virtual void setVisible(BOOL visible);
@@ -357,6 +354,10 @@ public:
tree_post_iterator_t beginTreeDFSPost();
tree_post_iterator_t endTreeDFSPost();
+ typedef LLTreeBFSIter<LLView, child_list_const_iter_t> bfs_tree_iterator_t;
+ bfs_tree_iterator_t beginTreeBFS();
+ bfs_tree_iterator_t endTreeBFS();
+
typedef LLTreeDownIter<LLView> root_to_view_iterator_t;
root_to_view_iterator_t beginRootToView();