summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llbutton.cpp14
-rw-r--r--indra/llui/llbutton.h3
-rw-r--r--indra/llui/llctrlselectioninterface.h3
-rw-r--r--indra/llui/llfloater.cpp180
-rw-r--r--indra/llui/llfloater.h10
-rw-r--r--indra/llui/llfocusmgr.cpp9
-rw-r--r--indra/llui/llfocusmgr.h1
-rw-r--r--indra/llui/llmenugl.cpp4
-rw-r--r--indra/llui/llpanel.cpp659
-rw-r--r--indra/llui/llpanel.h58
-rw-r--r--indra/llui/llradiogroup.cpp66
-rw-r--r--indra/llui/llradiogroup.h21
-rw-r--r--indra/llui/llresizebar.cpp86
-rw-r--r--indra/llui/llresizebar.h11
-rw-r--r--indra/llui/llscrollcontainer.cpp3
-rw-r--r--indra/llui/llscrolllistctrl.cpp55
-rw-r--r--indra/llui/llscrolllistctrl.h1
-rw-r--r--indra/llui/llslider.cpp158
-rw-r--r--indra/llui/llslider.h6
-rw-r--r--indra/llui/llsliderctrl.cpp10
-rw-r--r--indra/llui/llsliderctrl.h4
-rw-r--r--indra/llui/lltabcontainer.cpp114
-rw-r--r--indra/llui/lltabcontainer.h11
-rw-r--r--indra/llui/lltexteditor.cpp3
-rw-r--r--indra/llui/llui.cpp60
-rw-r--r--indra/llui/llui.h57
-rw-r--r--indra/llui/lluictrl.cpp2
-rw-r--r--indra/llui/lluictrlfactory.cpp36
-rw-r--r--indra/llui/lluictrlfactory.h8
-rw-r--r--indra/llui/lluistring.cpp3
-rw-r--r--indra/llui/lluistring.h2
-rw-r--r--indra/llui/llview.cpp125
-rw-r--r--indra/llui/llview.h2
33 files changed, 1398 insertions, 387 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index d93748d069..bdf1c12b79 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -197,6 +197,9 @@ void LLButton::init(void (*click_callback)(void*), void *callback_data, const LL
mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) );
mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) );
mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) );
+
+ mImageOverlayAlignment = LLFontGL::HCENTER;
+ mImageOverlayColor = LLColor4::white;
}
LLButton::~LLButton()
@@ -607,7 +610,7 @@ void LLButton::draw()
// draw overlay image
if (mImageOverlay.notNull())
{
- const S32 IMG_PAD = 4;
+ const S32 IMG_PAD = 5;
// get max width and height (discard level 0)
S32 overlay_width = mImageOverlay->getWidth(0);
S32 overlay_height = mImageOverlay->getHeight(0);
@@ -628,7 +631,7 @@ void LLButton::draw()
overlay_width,
overlay_height,
mImageOverlay,
- LLColor4::white);
+ mImageOverlayColor);
break;
case LLFontGL::HCENTER:
gl_draw_scaled_image(
@@ -637,7 +640,7 @@ void LLButton::draw()
overlay_width,
overlay_height,
mImageOverlay,
- LLColor4::white);
+ mImageOverlayColor);
break;
case LLFontGL::RIGHT:
gl_draw_scaled_image(
@@ -646,7 +649,7 @@ void LLButton::draw()
overlay_width,
overlay_height,
mImageOverlay,
- LLColor4::white);
+ mImageOverlayColor);
break;
default:
// draw nothing
@@ -866,7 +869,7 @@ void LLButton::setHoverImages( const LLString& image_name, const LLString& selec
setImageHoverSelected(selected_name);
}
-void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment)
+void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment, const LLColor4& color)
{
if (image_name.empty())
{
@@ -877,6 +880,7 @@ void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alig
LLUUID overlay_image_id = LLUI::findAssetUUIDByName(image_name);
mImageOverlay = LLUI::sImageProvider->getUIImageByID(overlay_image_id);
mImageOverlayAlignment = alignment;
+ mImageOverlayColor = color;
}
}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index ba77220a7b..a638b5be49 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -124,7 +124,7 @@ public:
void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; }
- void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER);
+ void setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
LLPointer<LLImageGL> getImageOverlay() { return mImageOverlay; }
@@ -190,6 +190,7 @@ protected:
LLPointer<LLImageGL> mImageOverlay;
LLFontGL::HAlign mImageOverlayAlignment;
+ LLColor4 mImageOverlayColor;
LLPointer<LLImageGL> mImageUnselected;
LLUIString mUnselectedLabel;
diff --git a/indra/llui/llctrlselectioninterface.h b/indra/llui/llctrlselectioninterface.h
index 698d609593..9df7475a6c 100644
--- a/indra/llui/llctrlselectioninterface.h
+++ b/indra/llui/llctrlselectioninterface.h
@@ -31,6 +31,8 @@ public:
virtual BOOL getCanSelect() const = 0;
+ virtual S32 getItemCount() const = 0;
+
virtual BOOL selectFirstItem() = 0;
virtual BOOL selectNthItem( S32 index ) = 0;
@@ -56,7 +58,6 @@ class LLCtrlListInterface : public LLCtrlSelectionInterface
public:
virtual ~LLCtrlListInterface();
- virtual S32 getItemCount() const = 0;
virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM) = 0;
virtual void clearColumns() = 0;
virtual void setColumnLabel(const LLString& column, const LLString& label) = 0;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 22acf46125..17b4dffa3f 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -292,28 +292,32 @@ void LLFloater::init(const LLString& title,
{
// Resize bars (sides)
const S32 RESIZE_BAR_THICKNESS = 3;
- mResizeBar[0] = new LLResizeBar(
+ mResizeBar[LLResizeBar::LEFT] = new LLResizeBar(
"resizebar_left",
+ this,
LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0),
- min_width, min_height, LLResizeBar::LEFT );
+ min_width, S32_MAX, LLResizeBar::LEFT );
addChild( mResizeBar[0] );
- mResizeBar[1] = new LLResizeBar(
+ mResizeBar[LLResizeBar::TOP] = new LLResizeBar(
"resizebar_top",
+ this,
LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS),
- min_width, min_height, LLResizeBar::TOP );
+ min_height, S32_MAX, LLResizeBar::TOP );
addChild( mResizeBar[1] );
- mResizeBar[2] = new LLResizeBar(
+ mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar(
"resizebar_right",
+ this,
LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
- min_width, min_height, LLResizeBar::RIGHT );
+ min_width, S32_MAX, LLResizeBar::RIGHT );
addChild( mResizeBar[2] );
- mResizeBar[3] = new LLResizeBar(
+ mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar(
"resizebar_bottom",
+ this,
LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0),
- min_width, min_height, LLResizeBar::BOTTOM );
+ min_height, S32_MAX, LLResizeBar::BOTTOM );
addChild( mResizeBar[3] );
@@ -601,7 +605,14 @@ void LLFloater::setResizeLimits( S32 min_width, S32 min_height )
{
if( mResizeBar[i] )
{
- mResizeBar[i]->setResizeLimits( min_width, min_height );
+ if (i == LLResizeBar::LEFT || i == LLResizeBar::RIGHT)
+ {
+ mResizeBar[i]->setResizeLimits( min_width, S32_MAX );
+ }
+ else
+ {
+ mResizeBar[i]->setResizeLimits( min_height, S32_MAX );
+ }
}
if( mResizeHandle[i] )
{
@@ -653,6 +664,25 @@ const LLString& LLFloater::getTitle() const
return mDragHandle ? mDragHandle->getTitle() : LLString::null;
}
+void LLFloater::setShortTitle( const LLString& short_title )
+{
+ mShortTitle = short_title;
+}
+
+LLString LLFloater::getShortTitle()
+{
+ if (mShortTitle.empty())
+ {
+ return mDragHandle ? mDragHandle->getTitle() : LLString::null;
+ }
+ else
+ {
+ return mShortTitle;
+ }
+}
+
+
+
BOOL LLFloater::canSnapTo(LLView* other_view)
{
if (NULL == other_view)
@@ -991,12 +1021,22 @@ void LLFloater::setHost(LLMultiFloater* host)
}
}
-void LLFloater::moveResizeHandleToFront()
+void LLFloater::moveResizeHandlesToFront()
{
- // 0 is the bottom right
- if( mResizeHandle[0] )
+ for( S32 i = 0; i < 4; i++ )
{
- sendChildToFront(mResizeHandle[0]);
+ if( mResizeBar[i] )
+ {
+ sendChildToFront(mResizeBar[i]);
+ }
+ }
+
+ for( S32 i = 0; i < 4; i++ )
+ {
+ if( mResizeHandle[i] )
+ {
+ sendChildToFront(mResizeHandle[i]);
+ }
}
}
@@ -1193,6 +1233,10 @@ BOOL LLFloater::getEditModeEnabled()
void LLFloater::show(LLFloater* floaterp)
{
if (floaterp) floaterp->open();
+ if (floaterp->getHost())
+ {
+ floaterp->getHost()->open();
+ }
}
//static
@@ -1206,7 +1250,7 @@ BOOL LLFloater::visible(LLFloater* floaterp)
{
if (floaterp)
{
- return floaterp->isInVisibleChain();
+ return !floaterp->isMinimized() && floaterp->isInVisibleChain();
}
return FALSE;
}
@@ -1233,12 +1277,15 @@ void LLFloater::onClickTearOff(void *userdata)
// reparent to floater view
gFloaterView->addChild(self);
- new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight());
-
self->open(); /* Flawfinder: ignore */
- self->setRect(new_rect);
+
+ // only force position for floaters that don't have that data saved
+ if (self->mRectControl.empty())
+ {
+ new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight());
+ self->setRect(new_rect);
+ }
gFloaterView->adjustToFitScreen(self, FALSE);
- self->setCanDrag(TRUE);
// give focus to new window to keep continuity for the user
self->setFocus(TRUE);
}
@@ -1248,6 +1295,8 @@ void LLFloater::onClickTearOff(void *userdata)
if (new_host)
{
new_host->showFloater(self);
+ // make sure host is visible
+ new_host->open();
}
}
}
@@ -1499,26 +1548,30 @@ void LLFloater::setCanResize(BOOL can_resize)
const S32 RESIZE_BAR_THICKNESS = 3;
mResizeBar[0] = new LLResizeBar(
"resizebar_left",
+ this,
LLRect( 0, mRect.getHeight(), RESIZE_BAR_THICKNESS, 0),
- mMinWidth, mMinHeight, LLResizeBar::LEFT );
+ mMinWidth, S32_MAX, LLResizeBar::LEFT );
addChild( mResizeBar[0] );
mResizeBar[1] = new LLResizeBar(
"resizebar_top",
+ this,
LLRect( 0, mRect.getHeight(), mRect.getWidth(), mRect.getHeight() - RESIZE_BAR_THICKNESS),
- mMinWidth, mMinHeight, LLResizeBar::TOP );
+ mMinHeight, S32_MAX, LLResizeBar::TOP );
addChild( mResizeBar[1] );
mResizeBar[2] = new LLResizeBar(
"resizebar_right",
+ this,
LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
- mMinWidth, mMinHeight, LLResizeBar::RIGHT );
+ mMinWidth, S32_MAX, LLResizeBar::RIGHT );
addChild( mResizeBar[2] );
mResizeBar[3] = new LLResizeBar(
"resizebar_bottom",
+ this,
LLRect( 0, RESIZE_BAR_THICKNESS, mRect.getWidth(), 0),
- mMinWidth, mMinHeight, LLResizeBar::BOTTOM );
+ mMinHeight, S32_MAX, LLResizeBar::BOTTOM );
addChild( mResizeBar[3] );
@@ -1855,7 +1908,7 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
sibling->getVisible() &&
expanded_base_rect.rectInRect(&sibling->getRect()))
{
- base_rect |= sibling->getRect();
+ base_rect.unionWith(sibling->getRect());
}
}
@@ -2550,18 +2603,22 @@ BOOL LLMultiFloater::closeAllFloaters()
return TRUE; //else all tabs were successfully closed...
}
-void LLMultiFloater::growToFit(LLFloater* floaterp, S32 width, S32 height)
+void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
{
- floater_data_map_t::iterator found_data_it;
- found_data_it = mFloaterDataMap.find(floaterp->getHandle());
- if (found_data_it != mFloaterDataMap.end())
+ S32 new_width = llmax(mRect.getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
+ S32 new_height = llmax(mRect.getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
+
+ if (isMinimized())
{
- // store new width and height with this floater so that it will keep its size when detached
- found_data_it->second.mWidth = width;
- found_data_it->second.mHeight = height;
+ mPreviousRect.setLeftTopAndSize(mPreviousRect.mLeft, mPreviousRect.mTop, new_width, new_height);
+ }
+ else
+ {
+ S32 old_height = mRect.getHeight();
+ reshape(new_width, new_height);
+ // keep top left corner in same position
+ translate(0, old_height - new_height);
}
-
- resizeToContents();
}
/**
@@ -2618,12 +2675,18 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
floaterp->setCanMinimize(FALSE);
floaterp->setCanResize(FALSE);
floaterp->setCanDrag(FALSE);
+ floaterp->storeRectControl();
+
+ if (mAutoResize)
+ {
+ growToFit(floater_data.mWidth, floater_data.mHeight);
+ }
//add the panel, add it to proper maps
- mTabContainer->addTabPanel(floaterp, floaterp->getTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
+ mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
mFloaterDataMap[floaterp->getHandle()] = floater_data;
- resizeToContents();
+ updateResizeLimits();
if ( select_added_floater )
{
@@ -2673,7 +2736,6 @@ void LLMultiFloater::showFloater(LLFloater* floaterp)
{
addFloater(floaterp, TRUE);
}
- setVisibleAndFrontmost();
}
void LLMultiFloater::removeFloater(LLFloater* floaterp)
@@ -2696,9 +2758,11 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp)
}
mTabContainer->removeTabPanel(floaterp);
floaterp->setBackgroundVisible(TRUE);
+ floaterp->setCanDrag(TRUE);
floaterp->setHost(NULL);
+ floaterp->applyRectControl();
- resizeToContents();
+ updateResizeLimits();
tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
}
@@ -2840,18 +2904,8 @@ BOOL LLMultiFloater::postBuild()
return FALSE;
}
-void LLMultiFloater::resizeToContents()
+void LLMultiFloater::updateResizeLimits()
{
- // we're already in the middle of a reshape, don't interrupt it
- floater_data_map_t::iterator floater_it;
- S32 new_width = 0;
- S32 new_height = 0;
- for (floater_it = mFloaterDataMap.begin(); floater_it != mFloaterDataMap.end(); ++floater_it)
- {
- new_width = llmax(new_width, floater_it->second.mWidth + LLPANEL_BORDER_WIDTH * 2);
- new_height = llmax(new_height, floater_it->second.mHeight + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
- }
-
S32 new_min_width = 0;
S32 new_min_height = 0;
S32 tab_idx;
@@ -2867,21 +2921,23 @@ void LLMultiFloater::resizeToContents()
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = mRect.getHeight();
+ S32 new_width = llmax(mRect.getWidth(), new_min_width);
+ S32 new_height = llmax(mRect.getHeight(), new_min_height);
- if (mAutoResize)
+ if (isMinimized())
{
- reshape(new_width, new_height);
+ mPreviousRect.setLeftTopAndSize(mPreviousRect.mLeft, mPreviousRect.mTop, llmax(mPreviousRect.getWidth(), new_width), llmax(mPreviousRect.getHeight(), new_height));
}
else
{
- reshape(llmax(new_min_width, mRect.getWidth()), llmax(new_min_height, mRect.getHeight()));
- }
+ reshape(new_width, new_height);
- // make sure upper left corner doesn't move
- translate(0, cur_height - mRect.getHeight());
+ // make sure upper left corner doesn't move
+ translate(0, cur_height - mRect.getHeight());
- // Try to keep whole view onscreen, don't allow partial offscreen.
- gFloaterView->adjustToFitScreen(this, FALSE);
+ // Try to keep whole view onscreen, don't allow partial offscreen.
+ gFloaterView->adjustToFitScreen(this, FALSE);
+ }
}
// virtual
@@ -2937,6 +2993,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
{
LLString name(getName());
LLString title(getTitle());
+ LLString short_title(getShortTitle());
LLString rect_control("");
BOOL resizable = isResizable();
S32 min_width = getMinWidth();
@@ -2948,6 +3005,7 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
node->getAttributeString("name", name);
node->getAttributeString("title", title);
+ node->getAttributeString("short_title", short_title);
node->getAttributeString("rect_control", rect_control);
node->getAttributeBOOL("can_resize", resizable);
node->getAttributeBOOL("can_minimize", minimizable);
@@ -2974,6 +3032,8 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
minimizable,
close_btn);
+ setShortTitle(short_title);
+
BOOL can_tear_off;
if (node->getAttributeBOOL("can_tear_off", can_tear_off))
{
@@ -2988,17 +3048,13 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
LLFloater::setFloaterHost((LLMultiFloater*) this);
}
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- factory->createWidget(this, child);
- }
+ initChildrenXML(node, factory);
+
if (node->hasName("multi_floater"))
{
LLFloater::setFloaterHost(last_host);
}
-
BOOL result = postBuild();
if (!result)
@@ -3011,4 +3067,6 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
{
this->open(); /* Flawfinder: ignore */
}
+
+ moveResizeHandlesToFront();
}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 1491f75683..942ae34d27 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -123,8 +123,10 @@ public:
void setTitle( const LLString& title );
const LLString& getTitle() const;
+ void setShortTitle( const LLString& short_title );
+ LLString getShortTitle();
virtual void setMinimized(BOOL b);
- void moveResizeHandleToFront();
+ void moveResizeHandlesToFront();
void addDependentFloater(LLFloater* dependent, BOOL reposition = TRUE);
void addDependentFloater(LLViewHandle dependent_handle, BOOL reposition = TRUE);
LLFloater* getDependee() { return (LLFloater*)LLFloater::getFloaterByHandle(mDependeeHandle); }
@@ -222,6 +224,7 @@ protected:
LLRect mPreviousRect;
BOOL mForeground;
LLViewHandle mDependeeHandle;
+ LLString mShortTitle;
BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible.
@@ -351,12 +354,11 @@ public:
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent);
-
/*virtual*/ EWidgetType getWidgetType() const;
/*virtual*/ LLString getWidgetTag() const;
virtual void setCanResize(BOOL can_resize);
- virtual void growToFit(LLFloater* floaterp, S32 width, S32 height);
+ virtual void growToFit(S32 content_width, S32 content_height);
virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainerCommon::eInsertionPoint insertion_point = LLTabContainerCommon::END);
virtual void showFloater(LLFloater* floaterp);
@@ -378,7 +380,7 @@ public:
void setTabContainer(LLTabContainerCommon* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
static void onTabSelected(void* userdata, bool);
- virtual void resizeToContents();
+ virtual void updateResizeLimits();
protected:
struct LLFloaterData
diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp
index da53e3d104..5c8eb8b4af 100644
--- a/indra/llui/llfocusmgr.cpp
+++ b/indra/llui/llfocusmgr.cpp
@@ -132,8 +132,7 @@ void LLFocusMgr::setKeyboardFocus(LLUICtrl* new_focus, FocusLostCallback on_focu
if (lock)
{
- mLockedView = mKeyboardFocus;
- mKeyboardLockedFocusLostCallback = on_focus_lost;
+ lockFocus();
}
}
@@ -292,6 +291,12 @@ void LLFocusMgr::removeTopCtrlWithoutCallback( LLUICtrl* top_view )
}
}
+void LLFocusMgr::lockFocus()
+{
+ mLockedView = mKeyboardFocus;
+ mKeyboardLockedFocusLostCallback = mKeyboardFocusLostCallback;
+}
+
void LLFocusMgr::unlockFocus()
{
mLockedView = NULL;
diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h
index dc8025d4c0..e764f5459c 100644
--- a/indra/llui/llfocusmgr.h
+++ b/indra/llui/llfocusmgr.h
@@ -61,6 +61,7 @@ public:
// All Three
void releaseFocusIfNeeded( LLView* top_view );
+ void lockFocus();
void unlockFocus();
BOOL focusLocked() { return mLockedView != NULL; }
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index d7ccfe1daa..52fdf3cd5a 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1391,9 +1391,9 @@ void LLMenuItemBranchGL::updateBranchParent(LLView* parentp)
}
}
-void LLMenuItemBranchGL::onVisibilityChange( BOOL curVisibilityIn )
+void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility )
{
- if (curVisibilityIn == FALSE && mBranch->getVisible() && !mBranch->getTornOff())
+ if (new_visibility == FALSE && !mBranch->getTornOff())
{
mBranch->setVisible(FALSE);
}
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 37feffd4b0..c130214b99 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -31,9 +31,18 @@
#include "llviewborder.h"
#include "llbutton.h"
+// LLLayoutStack
+#include "llgl.h"
+#include "llglheaders.h"
+#include "llresizebar.h"
+#include "llcriticaldamp.h"
+
LLPanel::panel_map_t LLPanel::sPanelMap;
LLPanel::alert_queue_t LLPanel::sAlertQueue;
+const S32 RESIZE_BAR_OVERLAP = 1;
+const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT;
+
void LLPanel::init()
{
// mRectControl
@@ -99,13 +108,16 @@ void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
addChild( mBorder );
}
+void LLPanel::removeBorder()
+{
+ delete mBorder;
+ mBorder = NULL;
+}
+
LLPanel::~LLPanel()
{
- if( !mRectControl.empty() )
- {
- LLUI::sConfigGroup->setRect( mRectControl, mRect );
- }
+ storeRectControl();
sPanelMap.erase(mViewHandle);
}
@@ -159,44 +171,41 @@ void LLPanel::setCtrlsEnabled( BOOL b )
void LLPanel::draw()
{
- if( getVisible() )
+ // draw background
+ if( mBgVisible )
{
- // draw background
- if( mBgVisible )
- {
- //RN: I don't see the point of this
- S32 left = 0;//LLPANEL_BORDER_WIDTH;
- S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
- S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
- S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
+ //RN: I don't see the point of this
+ S32 left = 0;//LLPANEL_BORDER_WIDTH;
+ S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
+ S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
+ S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
- if (mBgOpaque )
- {
- gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
- }
- else
- {
- gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
- }
+ if (mBgOpaque )
+ {
+ gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
}
-
- if( mDefaultBtn)
+ else
{
- if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
- {
- LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
- BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(focus_ctrl)->getCommitOnReturn();
- // only enable default button when current focus is not a return-capturing button
- mDefaultBtn->setBorderEnabled(!focus_is_child_button);
- }
- else
- {
- mDefaultBtn->setBorderEnabled(FALSE);
- }
+ gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
}
+ }
- LLView::draw();
+ if( mDefaultBtn)
+ {
+ if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
+ {
+ LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
+ BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(focus_ctrl)->getCommitOnReturn();
+ // only enable default button when current focus is not a return-capturing button
+ mDefaultBtn->setBorderEnabled(!focus_is_child_button);
+ }
+ else
+ {
+ mDefaultBtn->setBorderEnabled(FALSE);
+ }
}
+
+ LLView::draw();
}
void LLPanel::refresh()
@@ -552,7 +561,7 @@ LLXMLNodePtr LLPanel::getXML(bool save_children) const
return node;
}
-LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *factory)
+LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory)
{
LLString name("panel");
node->getAttributeString("name", name);
@@ -561,11 +570,21 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *fa
// Fall back on a default panel, if there was no special factory.
if (!panelp)
{
- panelp = new LLPanel("tab panel");
+ LLRect rect;
+ createRect(node, rect, parent, LLRect());
+ panelp = new LLPanel(name, rect);
+ panelp->initPanelXML(node, parent, factory);
+ // preserve panel's width and height, but override the location
+ const LLRect& panelrect = panelp->getRect();
+ S32 w = panelrect.getWidth();
+ S32 h = panelrect.getHeight();
+ rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
+ panelp->setRect(rect);
+ }
+ else
+ {
+ panelp->initPanelXML(node, parent, factory);
}
-
- panelp->initPanelXML(node, parentp, factory);
-
return panelp;
}
@@ -577,11 +596,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
setPanelParameters(node, parent);
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- factory->createWidget(this, child);
- }
+ initChildrenXML(node, factory);
LLString xml_filename;
node->getAttributeString("filename", xml_filename);
@@ -590,8 +605,16 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
if (!xml_filename.empty())
{
+ // Preserve postion of embedded panel but allow panel to dictate width/height
+ LLRect rect(getRect());
didPost = factory->buildPanel(this, xml_filename, NULL);
- } else {
+ S32 w = getRect().getWidth();
+ S32 h = getRect().getHeight();
+ rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
+ setRect(rect);
+ }
+ else
+ {
didPost = FALSE;
}
@@ -604,10 +627,32 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
return didPost;
}
-void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
+void LLPanel::initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory)
+{
+ LLXMLNodePtr child;
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ // look for string declarations for programmatic text
+ if (child->hasName("string"))
+ {
+ LLString string_name;
+ child->getAttributeString("name", string_name);
+ if (!string_name.empty())
+ {
+ mUIStrings[string_name] = LLUIString(child->getTextContents());
+ }
+ }
+ else
+ {
+ factory->createWidget(this, child);
+ }
+ }
+}
+
+void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
{
/////// Rect, follows, tool_tip, enabled, visible attributes ///////
- initFromXML(node, parentp);
+ initFromXML(node, parent);
/////// Border attributes ///////
BOOL border = FALSE;
@@ -632,6 +677,10 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
addBorder(bevel_style, border_style, border_thickness);
}
+ else
+ {
+ removeBorder();
+ }
/////// Background attributes ///////
BOOL background_visible = FALSE;
@@ -656,6 +705,30 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
setLabel(label);
}
+LLString LLPanel::getFormattedUIString(const LLString& name, const LLString::format_map_t& args) const
+{
+ ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
+ if (found_it != mUIStrings.end())
+ {
+ // make a copy as format works in place
+ LLUIString formatted_string = found_it->second;
+ formatted_string.setArgList(args);
+ return formatted_string.getString();
+ }
+ return LLString::null;
+}
+
+LLUIString LLPanel::getUIString(const LLString& name) const
+{
+ ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
+ if (found_it != mUIStrings.end())
+ {
+ return found_it->second;
+ }
+ return LLUIString(LLString::null);
+}
+
+
void LLPanel::childSetVisible(const LLString& id, bool visible)
{
LLView* child = getChildByName(id, true);
@@ -1045,3 +1118,493 @@ void LLPanel::childDisplayNotFound()
LLAlertDialog::showXml("FloaterNotFound", args);
}
+void LLPanel::storeRectControl()
+{
+ if( !mRectControl.empty() )
+ {
+ LLUI::sConfigGroup->setRect( mRectControl, mRect );
+ }
+}
+
+
+//
+// LLLayoutStack
+//
+struct LLLayoutStack::LLEmbeddedPanel
+{
+ LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize) :
+ mPanel(panelp),
+ mMinWidth(min_width),
+ mMinHeight(min_height),
+ mAutoResize(auto_resize),
+ mOrientation(orientation),
+ mVisibleAmt(1.f) // default to fully visible
+ {
+ LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
+ LLRect resize_bar_rect = panelp->getRect();
+
+ S32 min_dim;
+ if (orientation == HORIZONTAL)
+ {
+ min_dim = mMinHeight;
+ }
+ else
+ {
+ min_dim = mMinWidth;
+ }
+ mResizeBar = new LLResizeBar("resizer", mPanel, LLRect(), min_dim, S32_MAX, side);
+ mResizeBar->setEnableSnapping(FALSE);
+ // panels initialized as hidden should not start out partially visible
+ if (!mPanel->getVisible())
+ {
+ mVisibleAmt = 0.f;
+ }
+ }
+
+ LLPanel* mPanel;
+ S32 mMinWidth;
+ S32 mMinHeight;
+ BOOL mAutoResize;
+ LLResizeBar* mResizeBar;
+ eLayoutOrientation mOrientation;
+ F32 mVisibleAmt;
+};
+
+LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
+ mOrientation(orientation),
+ mMinWidth(0),
+ mMinHeight(0)
+{
+}
+
+LLLayoutStack::~LLLayoutStack()
+{
+}
+
+void LLLayoutStack::draw()
+{
+ updateLayout();
+ {
+ // clip if outside nominal bounds
+ LLLocalClipRect clip(getLocalRect(), mRect.getWidth() > mMinWidth || mRect.getHeight() > mMinHeight);
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLRect clip_rect = (*panel_it)->mPanel->getRect();
+ // scale clipping rectangle by visible amount
+ if (mOrientation == HORIZONTAL)
+ {
+ clip_rect.mRight = clip_rect.mLeft + llround(clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
+ }
+ else
+ {
+ clip_rect.mBottom = clip_rect.mTop - llround(clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
+ }
+ LLLocalClipRect clip(clip_rect, (*panel_it)->mVisibleAmt < 1.f);
+ // only force drawing invisible children if visible amount is non-zero
+ drawChild((*panel_it)->mPanel, 0, 0, (*panel_it)->mVisibleAmt > 0.f);
+ }
+ }
+}
+
+void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
+{
+ LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel((LLPanel*)ctrl);
+
+ if (embedded_panelp)
+ {
+ mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
+ delete embedded_panelp;
+ }
+
+ calcMinExtents();
+
+ LLView::removeCtrl(ctrl);
+}
+
+void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLView::reshape(width, height, called_from_parent);
+ //updateLayout();
+}
+
+LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
+{
+ LLXMLNodePtr node = LLView::getXML();
+ return node;
+}
+
+//static
+LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+{
+ LLString orientation_string("vertical");
+ node->getAttributeString("orientation", orientation_string);
+
+ eLayoutOrientation orientation = VERTICAL;
+
+ if (orientation_string == "horizontal")
+ {
+ orientation = HORIZONTAL;
+ }
+ else if (orientation_string == "vertical")
+ {
+ orientation = VERTICAL;
+ }
+ else
+ {
+ llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
+ }
+
+ LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
+
+ layout_stackp->initFromXML(node, parent);
+
+ LLXMLNodePtr child;
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ if (child->hasName("layout_panel"))
+ {
+ S32 min_width = 0;
+ S32 min_height = 0;
+ BOOL auto_resize = TRUE;
+
+ child->getAttributeS32("min_width", min_width);
+ child->getAttributeS32("min_height", min_height);
+ child->getAttributeBOOL("auto_resize", auto_resize);
+
+ LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
+ panelp->setFollowsNone();
+ if (panelp)
+ {
+ layout_stackp->addPanel(panelp, min_width, min_height, auto_resize);
+ }
+ }
+ }
+
+ return layout_stackp;
+}
+
+S32 LLLayoutStack::getMinWidth()
+{
+ return mMinWidth;
+}
+
+S32 LLLayoutStack::getMinHeight()
+{
+ return mMinHeight;
+}
+
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index)
+{
+ LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize);
+
+ mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
+ addChild(panel);
+ addChild(embedded_panel->mResizeBar);
+
+ // bring all resize bars to the front so that they are clickable even over the panels
+ // with a bit of overlap
+ for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ e_panel_list_t::iterator next_it = panel_it;
+ ++next_it;
+
+ LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
+ sendChildToFront(resize_barp);
+ // last resize bar is disabled, since its not between any two panels
+ if ( next_it == mPanels.end() )
+ {
+ resize_barp->setEnabled(FALSE);
+ }
+ else
+ {
+ resize_barp->setEnabled(TRUE);
+ }
+ }
+
+ //updateLayout();
+}
+
+void LLLayoutStack::removePanel(LLPanel* panel)
+{
+ removeChild(panel);
+ //updateLayout();
+}
+
+void LLLayoutStack::updateLayout(BOOL force_resize)
+{
+ calcMinExtents();
+
+ // calculate current extents
+ S32 cur_width = 0;
+ S32 cur_height = 0;
+
+ const F32 ANIM_OPEN_TIME = 0.02f;
+ const F32 ANIM_CLOSE_TIME = 0.02f;
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+ if (panelp->getVisible())
+ {
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
+ if ((*panel_it)->mVisibleAmt > 0.99f)
+ {
+ (*panel_it)->mVisibleAmt = 1.f;
+ }
+ }
+ else // not visible
+ {
+ (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ if ((*panel_it)->mVisibleAmt < 0.001f)
+ {
+ (*panel_it)->mVisibleAmt = 0.f;
+ }
+ }
+ if (mOrientation == HORIZONTAL)
+ {
+ // all panels get expanded to max of all the minimum dimensions
+ cur_height = llmax(mMinHeight, panelp->getRect().getHeight());
+ cur_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
+ if (panel_it != mPanels.end())
+ {
+ cur_width += PANEL_STACK_GAP;
+ }
+ }
+ else //VERTICAL
+ {
+ cur_width = llmax(mMinWidth, panelp->getRect().getWidth());
+ cur_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
+ if (panel_it != mPanels.end())
+ {
+ cur_height += PANEL_STACK_GAP;
+ }
+ }
+ }
+
+ S32 num_resizable_panels = 0;
+ S32 shrink_headroom_available = 0;
+ S32 shrink_headroom_total = 0;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ // panels that are not fully visible do not count towards shrink headroom
+ if ((*panel_it)->mVisibleAmt < 1.f)
+ continue;
+ // if currently resizing a panel or the panel is flagged as not automatically resizing
+ // only track total available headroom, but don't use it for automatic resize logic
+ if ((*panel_it)->mResizeBar->hasMouseCapture() || (!(*panel_it)->mAutoResize && !force_resize))
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ }
+ else //VERTICAL
+ {
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ }
+ }
+ else
+ {
+ num_resizable_panels++;
+ if (mOrientation == HORIZONTAL)
+ {
+ shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
+ }
+ else //VERTICAL
+ {
+ shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
+ }
+ }
+ }
+
+ // positive means panels need to grow, negative means shrink
+ S32 pixels_to_distribute;
+ if (mOrientation == HORIZONTAL)
+ {
+ pixels_to_distribute = mRect.getWidth() - cur_width;
+ }
+ else //VERTICAL
+ {
+ pixels_to_distribute = mRect.getHeight() - cur_height;
+ }
+
+ S32 cur_x = 0;
+ S32 cur_y = mRect.getHeight();
+
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ S32 cur_width = panelp->getRect().getWidth();
+ S32 cur_height = panelp->getRect().getHeight();
+ S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
+ S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
+
+ S32 delta_size = 0;
+
+ // if panel can automatically resize (not animating, and resize flag set)...
+ if ((*panel_it)->mVisibleAmt == 1.f && (force_resize || (*panel_it)->mAutoResize) && !(*panel_it)->mResizeBar->hasMouseCapture())
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ // if we're shrinking
+ if (pixels_to_distribute < 0)
+ {
+ // shrink proportionally to amount over minimum
+ delta_size = llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available);
+ }
+ else
+ {
+ // grow all elements equally
+ delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
+ }
+ new_width = llmax((*panel_it)->mMinWidth, panelp->getRect().getWidth() + delta_size);
+ }
+ else
+ {
+ new_width = llmax(mMinWidth, mRect.getWidth());
+ }
+
+ if (mOrientation == VERTICAL)
+ {
+ if (pixels_to_distribute < 0)
+ {
+ // shrink proportionally to amount over minimum
+ delta_size = llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available);
+ }
+ else
+ {
+ delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
+ }
+ new_height = llmax((*panel_it)->mMinHeight, panelp->getRect().getHeight() + delta_size);
+ }
+ else
+ {
+ new_height = llmax(mMinHeight, mRect.getHeight());
+ }
+ }
+ else // don't resize
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ new_height = llmax(mMinHeight, mRect.getHeight());
+ }
+ else // VERTICAL
+ {
+ new_width = llmax(mMinWidth, mRect.getWidth());
+ }
+ }
+
+ // adjust running headroom count based on new sizes
+ shrink_headroom_total += delta_size;
+
+ panelp->reshape(new_width, new_height);
+ panelp->setOrigin(cur_x, cur_y - new_height);
+
+ LLRect panel_rect = panelp->getRect();
+ LLRect resize_bar_rect = panel_rect;
+ if (mOrientation == HORIZONTAL)
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
+ resize_bar_rect.mRight = panel_rect.mRight + PANEL_STACK_GAP + RESIZE_BAR_OVERLAP;
+ }
+ else
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
+ resize_bar_rect.mBottom = panel_rect.mBottom - PANEL_STACK_GAP - RESIZE_BAR_OVERLAP;
+ }
+ (*panel_it)->mResizeBar->setRect(resize_bar_rect);
+
+ if (mOrientation == HORIZONTAL)
+ {
+ cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
+ }
+ else //VERTICAL
+ {
+ cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
+ }
+ }
+
+ // update resize bars with new limits
+ LLResizeBar* last_resize_bar = NULL;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ LLPanel* panelp = (*panel_it)->mPanel;
+
+ if (mOrientation == HORIZONTAL)
+ {
+ (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinWidth, (*panel_it)->mMinWidth + shrink_headroom_total);
+ }
+ else //VERTICAL
+ {
+ (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinHeight, (*panel_it)->mMinHeight + shrink_headroom_total);
+ }
+ // hide resize bars for invisible panels
+ (*panel_it)->mResizeBar->setVisible(panelp->getVisible());
+ if (panelp->getVisible())
+ {
+ last_resize_bar = (*panel_it)->mResizeBar;
+ }
+ }
+
+ // hide last resize bar as there is nothing past it
+ if (last_resize_bar)
+ {
+ last_resize_bar->setVisible(FALSE);
+ }
+
+ // not enough room to fit existing contents
+ if (!force_resize &&
+ ((cur_y != -PANEL_STACK_GAP) || (cur_x != mRect.getWidth() + PANEL_STACK_GAP)))
+ {
+ // do another layout pass with all stacked elements contributing
+ // even those that don't usually resize
+ llassert_always(force_resize == FALSE);
+ updateLayout(TRUE);
+ }
+}
+
+LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp)
+{
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ if ((*panel_it)->mPanel == panelp)
+ {
+ return *panel_it;
+ }
+ }
+ return NULL;
+}
+
+void LLLayoutStack::calcMinExtents()
+{
+ mMinWidth = 0;
+ mMinHeight = 0;
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ mMinHeight = llmax(mMinHeight, (*panel_it)->mMinHeight);
+ mMinWidth += (*panel_it)->mMinWidth;
+ if (panel_it != mPanels.begin())
+ {
+ mMinWidth += PANEL_STACK_GAP;
+ }
+ }
+ else //VERTICAL
+ {
+ mMinWidth = llmax(mMinWidth, (*panel_it)->mMinWidth);
+ mMinHeight += (*panel_it)->mMinHeight;
+ if (panel_it != mPanels.begin())
+ {
+ mMinHeight += PANEL_STACK_GAP;
+ }
+ }
+ }
+}
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index f06797a7f8..aa5f6e314f 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -15,6 +15,7 @@
#include "llcallbackmap.h"
#include "lluictrl.h"
#include "llviewborder.h"
+#include "lluistring.h"
#include "v4color.h"
#include <list>
#include <queue>
@@ -71,6 +72,8 @@ public:
LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE,
S32 border_thickness = LLPANEL_BORDER_WIDTH );
+ void removeBorder();
+
virtual ~LLPanel();
virtual void draw();
virtual void refresh(); // called in setFocus()
@@ -97,6 +100,7 @@ public:
LLString getLabel() const { return mLabel; }
void setRectControl(const LLString& rect_control) { mRectControl.assign(rect_control); }
+ void storeRectControl();
void setBorderVisible( BOOL b );
@@ -116,8 +120,12 @@ public:
virtual LLXMLNodePtr getXML(bool save_children = true) const;
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+ void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory);
void setPanelParameters(LLXMLNodePtr node, LLView *parentp);
+ LLString getFormattedUIString(const LLString& name, const LLString::format_map_t& args = LLUIString::sNullArgs) const;
+ LLUIString getUIString(const LLString& name) const;
+
// ** Wrappers for setting child properties by name ** -TomY
// Override to set not found list
@@ -196,6 +204,8 @@ public:
typedef std::queue<LLAlertInfo> alert_queue_t;
static alert_queue_t sAlertQueue;
+ typedef std::map<LLString, LLUIString> ui_string_map_t;
+
private:
// common constructor
void init();
@@ -221,6 +231,8 @@ protected:
LLString mLabel;
S32 mLastTabGroup;
+ ui_string_map_t mUIStrings;
+
typedef std::map<LLString, EWidgetType> requirements_map_t;
requirements_map_t mRequirements;
@@ -228,4 +240,50 @@ protected:
static panel_map_t sPanelMap;
};
+class LLLayoutStack : public LLView
+{
+public:
+ typedef enum e_layout_orientation
+ {
+ HORIZONTAL,
+ VERTICAL
+ } eLayoutOrientation;
+
+ LLLayoutStack(eLayoutOrientation orientation);
+ virtual ~LLLayoutStack();
+
+ /*virtual*/ void draw();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+ /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
+ /*virtual*/ void removeCtrl(LLUICtrl* ctrl);
+ virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_LAYOUT_STACK; }
+ virtual LLString getWidgetTag() const { return LL_LAYOUT_STACK_TAG; }
+
+ static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
+
+ S32 getMinWidth();
+ S32 getMinHeight();
+
+ void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index = S32_MAX);
+ void removePanel(LLPanel* panel);
+ void updateLayout(BOOL force_resize = FALSE);
+
+protected:
+ struct LLEmbeddedPanel;
+
+ LLEmbeddedPanel* findEmbeddedPanel(LLPanel* panelp);
+ void calcMinExtents();
+ S32 getMinStackSize();
+ S32 getCurStackSize();
+
+protected:
+ eLayoutOrientation mOrientation;
+
+ typedef std::vector<LLEmbeddedPanel*> e_panel_list_t;
+ e_panel_list_t mPanels;
+
+ S32 mMinWidth;
+ S32 mMinHeight;
+};
+
#endif
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 69c0da6933..b58ae09b5d 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -149,7 +149,7 @@ BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;
// do any of the tab buttons have keyboard focus?
- if (getEnabled() && !called_from_parent)
+ if (getEnabled() && !called_from_parent && mask == MASK_NONE)
{
switch(key)
{
@@ -421,6 +421,69 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
return radio_group;
}
+// LLCtrlSelectionInterface functions
+BOOL LLRadioGroup::setCurrentByID( const LLUUID& id )
+{
+ return FALSE;
+}
+
+LLUUID LLRadioGroup::getCurrentID()
+{
+ return LLUUID::null;
+}
+
+BOOL LLRadioGroup::setSelectedByValue(LLSD value, BOOL selected)
+{
+ S32 idx = 0;
+ std::string value_string = value.asString();
+ for (button_list_t::const_iterator iter = mRadioButtons.begin();
+ iter != mRadioButtons.end(); ++iter)
+ {
+ if((*iter)->getName() == value_string)
+ {
+ setSelectedIndex(idx);
+ return TRUE;
+ }
+ idx++;
+ }
+
+ return FALSE;
+}
+
+LLSD LLRadioGroup::getSimpleSelectedValue()
+{
+ return getValue();
+}
+
+BOOL LLRadioGroup::isSelected(LLSD value)
+{
+ S32 idx = 0;
+ std::string value_string = value.asString();
+ for (button_list_t::const_iterator iter = mRadioButtons.begin();
+ iter != mRadioButtons.end(); ++iter)
+ {
+ if((*iter)->getName() == value_string)
+ {
+ if (idx == mSelectedIndex)
+ {
+ return TRUE;
+ }
+ }
+ idx++;
+ }
+ return FALSE;
+}
+
+BOOL LLRadioGroup::operateOnSelection(EOperation op)
+{
+ return FALSE;
+}
+
+BOOL LLRadioGroup::operateOnAll(EOperation op)
+{
+ return FALSE;
+}
+
LLRadioCtrl::LLRadioCtrl(const LLString& name, const LLRect& rect, const LLString& label,
const LLFontGL* font, void (*commit_callback)(LLUICtrl*, void*), void* callback_userdata) :
@@ -438,3 +501,4 @@ void LLRadioCtrl::setValue(const LLSD& value)
LLCheckBoxCtrl::setValue(value);
mButton->setTabStop(value.asBoolean());
}
+
diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h
index 01b4a61b82..2a856ee6cf 100644
--- a/indra/llui/llradiogroup.h
+++ b/indra/llui/llradiogroup.h
@@ -15,6 +15,7 @@
#include "lluictrl.h"
#include "llcheckboxctrl.h"
+#include "llctrlselectioninterface.h"
class LLFontGL;
@@ -32,7 +33,7 @@ public:
};
class LLRadioGroup
-: public LLUICtrl
+: public LLUICtrl, public LLCtrlSelectionInterface
{
public:
// Build a radio group. The number (0...n-1) of the currently selected
@@ -63,7 +64,6 @@ public:
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
void setIndexEnabled(S32 index, BOOL enabled);
- S32 getItemCount() { return mRadioButtons.size(); }
// return the index value of the selected item
S32 getSelectedIndex() const;
@@ -87,6 +87,23 @@ public:
// button.
static void onClickButton(LLUICtrl* radio, void* userdata);
+ //========================================================================
+ LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; };
+
+ // LLCtrlSelectionInterface functions
+ /*virtual*/ S32 getItemCount() const { return mRadioButtons.size(); }
+ /*virtual*/ BOOL getCanSelect() const { return TRUE; }
+ /*virtual*/ BOOL selectFirstItem() { return setSelectedIndex(0); }
+ /*virtual*/ BOOL selectNthItem( S32 index ) { return setSelectedIndex(index); }
+ /*virtual*/ S32 getFirstSelectedIndex() { return getSelectedIndex(); }
+ /*virtual*/ BOOL setCurrentByID( const LLUUID& id );
+ /*virtual*/ LLUUID getCurrentID(); // LLUUID::null if no items in menu
+ /*virtual*/ BOOL setSelectedByValue(LLSD value, BOOL selected);
+ /*virtual*/ LLSD getSimpleSelectedValue();
+ /*virtual*/ BOOL isSelected(LLSD value);
+ /*virtual*/ BOOL operateOnSelection(EOperation op);
+ /*virtual*/ BOOL operateOnAll(EOperation op);
+
protected:
// protected function shared by the two constructors.
void init(BOOL border);
diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 0128b4ebbc..b3bce755b1 100644
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -18,16 +18,18 @@
#include "llfocusmgr.h"
#include "llwindow.h"
-LLResizeBar::LLResizeBar( const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side )
+LLResizeBar::LLResizeBar( const LLString& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side )
:
LLView( name, rect, TRUE ),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
mLastMouseScreenY( 0 ),
- mMinWidth( min_width ),
- mMinHeight( min_height ),
- mSide( side )
+ mMinSize( min_size ),
+ mMaxSize( max_size ),
+ mSide( side ),
+ mSnappingEnabled(TRUE),
+ mResizingView(resizing_view)
{
// set up some generically good follow code.
switch( side )
@@ -129,12 +131,11 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
// Make sure the mouse in still over the application. We don't want to make the parent
// so big that we can't see the resize handle any more.
LLRect valid_rect = getRootView()->getRect();
- LLView* resizing_view = getParent();
- if( valid_rect.localPointInRect( screen_x, screen_y ) && resizing_view )
+ if( valid_rect.localPointInRect( screen_x, screen_y ) && mResizingView )
{
// Resize the parent
- LLRect orig_rect = resizing_view->getRect();
+ LLRect orig_rect = mResizingView->getRect();
LLRect scaled_rect = orig_rect;
S32 new_width = orig_rect.getWidth();
@@ -143,76 +144,63 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
switch( mSide )
{
case LEFT:
- new_width = orig_rect.getWidth() - delta_x;
- if( new_width < mMinWidth )
- {
- new_width = mMinWidth;
- delta_x = orig_rect.getWidth() - mMinWidth;
- }
+ new_width = llclamp(orig_rect.getWidth() - delta_x, mMinSize, mMaxSize);
+ delta_x = orig_rect.getWidth() - new_width;
scaled_rect.translate(delta_x, 0);
break;
case TOP:
- new_height = orig_rect.getHeight() + delta_y;
- if( new_height < mMinHeight )
- {
- new_height = mMinHeight;
- delta_y = mMinHeight - orig_rect.getHeight();
- }
+ new_height = llclamp(orig_rect.getHeight() + delta_y, mMinSize, mMaxSize);
+ delta_y = new_height - orig_rect.getHeight();
break;
case RIGHT:
- new_width = orig_rect.getWidth() + delta_x;
- if( new_width < mMinWidth )
- {
- new_width = mMinWidth;
- delta_x = mMinWidth - orig_rect.getWidth();
- }
+ new_width = llclamp(orig_rect.getWidth() + delta_x, mMinSize, mMaxSize);
+ delta_x = new_width - orig_rect.getWidth();
break;
case BOTTOM:
- new_height = orig_rect.getHeight() - delta_y;
- if( new_height < mMinHeight )
- {
- new_height = mMinHeight;
- delta_y = orig_rect.getHeight() - mMinHeight;
- }
+ new_height = llclamp(orig_rect.getHeight() - delta_y, mMinSize, mMaxSize);
+ delta_y = orig_rect.getHeight() - new_height;
scaled_rect.translate(0, delta_y);
break;
}
scaled_rect.mTop = scaled_rect.mBottom + new_height;
scaled_rect.mRight = scaled_rect.mLeft + new_width;
- resizing_view->setRect(scaled_rect);
+ mResizingView->setRect(scaled_rect);
LLView* snap_view = NULL;
- switch( mSide )
+ if (mSnappingEnabled)
{
- case LEFT:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
- case TOP:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
- case RIGHT:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
- case BOTTOM:
- snap_view = resizing_view->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
- break;
+ switch( mSide )
+ {
+ case LEFT:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mLeft, mouse_dir, SNAP_LEFT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ case TOP:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mTop, mouse_dir, SNAP_TOP, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ case RIGHT:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mRight, mouse_dir, SNAP_RIGHT, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ case BOTTOM:
+ snap_view = mResizingView->findSnapEdge(scaled_rect.mBottom, mouse_dir, SNAP_BOTTOM, SNAP_PARENT_AND_SIBLINGS, LLUI::sConfigGroup->getS32("SnapMargin"));
+ break;
+ }
}
// register "snap" behavior with snapped view
- resizing_view->snappedTo(snap_view);
+ mResizingView->snappedTo(snap_view);
// restore original rectangle so the appropriate changes are detected
- resizing_view->setRect(orig_rect);
+ mResizingView->setRect(orig_rect);
// change view shape as user operation
- resizing_view->userSetShape(scaled_rect);
+ mResizingView->userSetShape(scaled_rect);
// update last valid mouse cursor position based on resized view's actual size
- LLRect new_rect = resizing_view->getRect();
+ LLRect new_rect = mResizingView->getRect();
switch(mSide)
{
case LEFT:
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index 7a77cce8a6..cf78879cba 100644
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -17,7 +17,7 @@ class LLResizeBar : public LLView
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM };
- LLResizeBar(const LLString& name, const LLRect& rect, S32 min_width, S32 min_height, Side side );
+ LLResizeBar(const LLString& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side );
virtual EWidgetType getWidgetType() const;
virtual LLString getWidgetTag() const;
@@ -27,7 +27,8 @@ public:
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
- void setResizeLimits( S32 min_width, S32 min_height ) { mMinWidth = min_width; mMinHeight = min_height; }
+ void setResizeLimits( S32 min_size, S32 max_size ) { mMinSize = min_size; mMaxSize = max_size; }
+ void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; }
protected:
S32 mDragLastScreenX;
@@ -35,9 +36,11 @@ protected:
S32 mLastMouseScreenX;
S32 mLastMouseScreenY;
LLCoordGL mLastMouseDir;
- S32 mMinWidth;
- S32 mMinHeight;
+ S32 mMinSize;
+ S32 mMaxSize;
Side mSide;
+ BOOL mSnappingEnabled;
+ LLView* mResizingView;
};
const S32 RESIZE_BAR_HEIGHT = 3;
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 0e3c73f633..589afb114a 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -485,8 +485,7 @@ void LLScrollableContainerView::draw()
BOOL show_h_scrollbar = FALSE;
calcVisibleSize( mScrolledView->getRect(), &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
- LLGLEnable scissor_test(GL_SCISSOR_TEST);
- LLUI::setScissorRegionLocal(LLRect(mInnerRect.mLeft,
+ LLLocalClipRect clip(LLRect(mInnerRect.mLeft,
mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0) + visible_height,
visible_width,
mInnerRect.mBottom + (show_h_scrollbar ? SCROLLBAR_SIZE : 0)
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 1d07d3f36b..e802b3426b 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -31,7 +31,7 @@
#include "llkeyboard.h"
#include "llresizebar.h"
-const S32 LIST_BORDER_PAD = 2; // white space inside the border and to the left of the scrollbar
+const S32 LIST_BORDER_PAD = 0; // white space inside the border and to the left of the scrollbar
const S32 MIN_COLUMN_WIDTH = 20;
const S32 LIST_SNAP_PADDING = 5;
@@ -397,6 +397,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mCommitOnKeyboardMovement(TRUE),
mCommitOnSelectionChange(FALSE),
mSelectionChanged(FALSE),
+ mNeedsScroll(FALSE),
mCanSelect(TRUE),
mDisplayColumnHeaders(FALSE),
mCollapseEmptyColumns(FALSE),
@@ -1419,14 +1420,16 @@ void LLScrollListCtrl::drawItems()
S32 x = mItemListRect.mLeft;
S32 y = mItemListRect.mTop - mLineHeight;
- S32 num_page_lines = mPageLines;
+ // allow for partial line at bottom
+ S32 num_page_lines = mPageLines + 1;
LLRect item_rect;
LLGLSUIDefault gls_ui;
{
-
+ LLLocalClipRect clip(mItemListRect);
+
S32 cur_x = x;
S32 cur_y = y;
@@ -1538,6 +1541,11 @@ void LLScrollListCtrl::draw()
{
if( getVisible() )
{
+ if (mNeedsScroll)
+ {
+ scrollToShowSelected();
+ mNeedsScroll = FALSE;
+ }
LLRect background(0, mRect.getHeight(), mRect.getWidth(), 0);
// Draw background
if (mBackgroundVisible)
@@ -1690,6 +1698,7 @@ BOOL LLScrollListCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
gFocusMgr.setMouseCapture(this);
selectItemAt(x, y, mask);
+ mNeedsScroll = TRUE;
}
return TRUE;
@@ -1699,17 +1708,16 @@ BOOL LLScrollListCtrl::handleMouseUp(S32 x, S32 y, MASK mask)
{
if (hasMouseCapture())
{
+ // release mouse capture immediately so
+ // scroll to show selected logic will work
+ gFocusMgr.setMouseCapture(NULL);
if(mask == MASK_NONE)
{
selectItemAt(x, y, mask);
+ mNeedsScroll = TRUE;
}
}
- if (hasMouseCapture())
- {
- gFocusMgr.setMouseCapture(NULL);
- }
-
// always commit when mouse operation is completed inside list
if (mItemListRect.pointInRect(x,y))
{
@@ -1750,7 +1758,8 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
mItemListRect.getWidth(),
mLineHeight );
- int num_page_lines = mPageLines;
+ // allow for partial line at bottom
+ S32 num_page_lines = mPageLines + 1;
S32 line = 0;
item_list::iterator iter;
@@ -1783,6 +1792,7 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
if(mask == MASK_NONE)
{
selectItemAt(x, y, mask);
+ mNeedsScroll = TRUE;
}
}
else if (mCanSelect)
@@ -1830,7 +1840,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
{
// commit implicit in call
selectPrevItem(FALSE);
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
handled = TRUE;
}
break;
@@ -1839,7 +1849,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
{
// commit implicit in call
selectNextItem(FALSE);
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
handled = TRUE;
}
break;
@@ -1847,7 +1857,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectNthItem(getFirstSelectedIndex() - (mScrollbar->getPageSize() - 1));
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1860,7 +1870,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectNthItem(getFirstSelectedIndex() + (mScrollbar->getPageSize() - 1));
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1873,7 +1883,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectFirstItem();
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1886,7 +1896,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
if (mAllowKeyboardMovement || hasFocus())
{
selectNthItem(getItemCount() - 1);
- scrollToShowSelected();
+ mNeedsScroll = TRUE;
if (mCommitOnKeyboardMovement
&& !mCommitOnSelectionChange)
{
@@ -1925,6 +1935,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask, BOOL called_from_parent
}
else if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString), FALSE))
{
+ mNeedsScroll = TRUE;
// update search string only on successful match
mSearchTimer.reset();
@@ -1964,6 +1975,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
if (selectSimpleItemByPrefix(wstring_to_utf8str(mSearchString + (llwchar)uni_char), FALSE))
{
// update search string only on successful match
+ mNeedsScroll = TRUE;
mSearchString += uni_char;
mSearchTimer.reset();
@@ -2009,6 +2021,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
{
selectItem(item);
+ mNeedsScroll = TRUE;
cellp->highlightText(0, 1);
mSearchTimer.reset();
@@ -2030,8 +2043,6 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_
}
}
- // make sure selected item is on screen
- scrollToShowSelected();
return TRUE;
}
@@ -2183,6 +2194,13 @@ void LLScrollListCtrl::setScrollPos( S32 pos )
void LLScrollListCtrl::scrollToShowSelected()
{
+ // don't scroll automatically when capturing mouse input
+ // as that will change what is currently under the mouse cursor
+ if (hasMouseCapture())
+ {
+ return;
+ }
+
S32 index = getFirstSelectedIndex();
if (index < 0)
{
@@ -3013,8 +3031,9 @@ LLColumnHeader::LLColumnHeader(const LLString& label, const LLRect &rect, LLScro
const S32 RESIZE_BAR_THICKNESS = 3;
mResizeBar = new LLResizeBar(
"resizebar",
+ this,
LLRect( mRect.getWidth() - RESIZE_BAR_THICKNESS, mRect.getHeight(), mRect.getWidth(), 0),
- MIN_COLUMN_WIDTH, mRect.getHeight(), LLResizeBar::RIGHT );
+ MIN_COLUMN_WIDTH, S32_MAX, LLResizeBar::RIGHT );
addChild(mResizeBar);
mResizeBar->setEnabled(FALSE);
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 793f97dc64..9604b0569c 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -585,6 +585,7 @@ protected:
BOOL mCommitOnKeyboardMovement;
BOOL mCommitOnSelectionChange;
BOOL mSelectionChanged;
+ BOOL mNeedsScroll;
BOOL mCanSelect;
BOOL mDisplayColumnHeaders;
BOOL mCollapseEmptyColumns;
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 3a01013943..06fd2830a3 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -30,6 +30,7 @@ LLSlider::LLSlider(
F32 min_value,
F32 max_value,
F32 increment,
+ BOOL volume,
const LLString& control_name)
:
LLUICtrl( name, rect, TRUE, on_commit_callback, callback_userdata,
@@ -39,6 +40,7 @@ LLSlider::LLSlider(
mMinValue( min_value ),
mMaxValue( max_value ),
mIncrement( increment ),
+ mVolumeSlider( volume ),
mMouseOffset( 0 ),
mDragStartThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
mThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
@@ -49,7 +51,7 @@ LLSlider::LLSlider(
mMouseDownCallback( NULL ),
mMouseUpCallback( NULL )
{
- // prperly handle setting the starting thumb rect
+ // properly handle setting the starting thumb rect
// do it this way to handle both the operating-on-settings
// and standalone ways of using this
setControlName(control_name, NULL);
@@ -74,13 +76,15 @@ void LLSlider::setValue(F32 value, BOOL from_event)
value -= mMinValue;
value += mIncrement/2.0001f;
value -= fmod(value, mIncrement);
- mValue = mMinValue + value;
+ value += mMinValue;
- if (!from_event)
+ if (!from_event && mValue != value)
{
- setControlValue(mValue);
+ setControlValue(value);
}
-
+
+ mValue = value;
+
F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
S32 left_edge = THUMB_WIDTH/2;
@@ -91,6 +95,18 @@ void LLSlider::setValue(F32 value, BOOL from_event)
mThumbRect.mRight = x + (THUMB_WIDTH/2);
}
+void LLSlider::setValueAndCommit(F32 value)
+{
+ F32 old_value = mValue;
+ setValue(value);
+
+ if (mValue != old_value)
+ {
+ onCommit();
+ }
+}
+
+
F32 LLSlider::getValueF32() const
{
return mValue;
@@ -107,8 +123,7 @@ BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
x = llclamp( x, left_edge, right_edge );
F32 t = F32(x - left_edge) / (right_edge - left_edge);
- setValue(t * (mMaxValue - mMinValue) + mMinValue );
- onCommit();
+ setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
getWindow()->setCursor(UI_CURSOR_ARROW);
lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
@@ -158,8 +173,7 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
if (MASK_CONTROL & mask) // if CTRL is modifying
{
- setValue(mInitialValue);
- onCommit();
+ setValueAndCommit(mInitialValue);
}
else
{
@@ -196,13 +210,11 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
handled = TRUE;
break;
case KEY_LEFT:
- setValue(getValueF32() - getIncrement());
- onCommit();
+ setValueAndCommit(getValueF32() - getIncrement());
handled = TRUE;
break;
case KEY_RIGHT:
- setValue(getValueF32() + getIncrement());
- onCommit();
+ setValueAndCommit(getValueF32() + getIncrement());
handled = TRUE;
break;
default:
@@ -224,33 +236,93 @@ void LLSlider::draw()
LLRect rect(mDragStartThumbRect);
F32 opacity = mEnabled ? 1.f : 0.3f;
+ LLColor4 center_color = (mThumbCenterColor % opacity);
+ LLColor4 outline_color = (mThumbOutlineColor % opacity);
+ LLColor4 track_color = (mTrackColor % opacity);
+ LLImageGL* thumb_imagep = NULL;
+
// Track
+ if (mVolumeSlider)
+ {
+ LLRect track(0, mRect.getHeight(), mRect.getWidth(), 0);
+
+ track.mBottom += 3;
+ track.mTop -= 1;
+ track.mRight -= 1;
+
+ gl_triangle_2d(track.mLeft, track.mBottom,
+ track.mRight, track.mBottom,
+ track.mRight, track.mTop,
+ center_color,
+ TRUE);
+ gl_triangle_2d(track.mLeft, track.mBottom,
+ track.mRight, track.mBottom,
+ track.mRight, track.mTop,
+ outline_color,
+ FALSE);
+ }
+ else
+ {
+ LLUUID thumb_image_id;
+ thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
+ thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
- LLUUID thumb_image_id;
- thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
- LLImageGL* thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
-
- S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2;
- LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset );
+ S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2;
+ LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset );
- track_rect.stretch(-1);
- gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
- thumb_imagep, mTrackColor % opacity);
- //gl_rect_2d( track_rect, mThumbOutlineColor % opacity );
+ track_rect.stretch(-1);
+ gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
+ thumb_imagep, track_color);
+ }
+ // Thumb
if (!thumb_imagep)
{
- gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
- if (hasMouseCapture())
+ if (mVolumeSlider)
+ {
+ if (hasMouseCapture())
+ {
+ LLRect rect(mDragStartThumbRect);
+ gl_rect_2d( rect, outline_color );
+ rect.stretch(-1);
+ gl_rect_2d( rect, mThumbCenterColor % 0.3f );
+
+ if (hasFocus())
+ {
+ LLRect thumb_rect = mThumbRect;
+ thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
+ gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
+ }
+ gl_rect_2d( mThumbRect, mThumbOutlineColor );
+ }
+ else
+ {
+ if (hasFocus())
+ {
+ LLRect thumb_rect = mThumbRect;
+ thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
+ gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
+ }
+ LLRect rect(mThumbRect);
+ gl_rect_2d(rect, outline_color);
+ rect.stretch(-1);
+ gl_rect_2d( rect, center_color);
+ }
+ }
+ else
{
- gl_rect_2d(mDragStartThumbRect, mThumbCenterColor % opacity, FALSE);
+ gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
+ if (hasMouseCapture())
+ {
+ gl_rect_2d(mDragStartThumbRect, center_color, FALSE);
+ }
}
}
else if( hasMouseCapture() )
{
gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(),
- thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
+ thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
if (hasFocus())
{
@@ -258,20 +330,12 @@ void LLSlider::draw()
LLRect highlight_rect = mThumbRect;
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
- thumb_imagep, gFocusMgr.getFocusColor());
+ thumb_imagep, gFocusMgr.getFocusColor());
}
-
gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
- thumb_imagep, mThumbOutlineColor, TRUE);
-
- //// Start Thumb
- //gl_rect_2d( mDragStartThumbRect, mThumbOutlineColor % 0.3f );
- //rect.stretch(-1);
- //gl_rect_2d( rect, mThumbCenterColor % 0.3f );
+ thumb_imagep, mThumbOutlineColor, TRUE);
- //// Thumb
- //gl_rect_2d( mThumbRect, mThumbOutlineColor );
}
else
{
@@ -281,22 +345,12 @@ void LLSlider::draw()
LLRect highlight_rect = mThumbRect;
highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
- thumb_imagep, gFocusMgr.getFocusColor());
+ thumb_imagep, gFocusMgr.getFocusColor());
}
gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(),
- thumb_imagep, mThumbCenterColor % opacity, TRUE);
- //rect = mThumbRect;
-
- //gl_rect_2d( mThumbRect, mThumbOutlineColor % opacity );
- //
- //rect.stretch(-1);
-
- //// Thumb
- //gl_rect_2d( rect, mThumbCenterColor % opacity );
-
+ thumb_imagep, center_color, TRUE);
}
-
LLUICtrl::draw();
}
}
@@ -310,6 +364,7 @@ LLXMLNodePtr LLSlider::getXML(bool save_children) const
node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
node->createChild("increment", TRUE)->setFloatValue(getIncrement());
+ node->createChild("volume", TRUE)->setBoolValue(getVolumeSlider());
return node;
}
@@ -336,6 +391,8 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
F32 increment = 0.1f;
node->getAttributeF32("increment", increment);
+ BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
+ node->getAttributeBOOL("volume", volume);
LLSlider* slider = new LLSlider(name,
rect,
@@ -344,7 +401,8 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
initial_value,
min_value,
max_value,
- increment);
+ increment,
+ volume);
slider->initFromXML(node, parent);
diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h
index d88da42064..d9cdf11d5d 100644
--- a/indra/llui/llslider.h
+++ b/indra/llui/llslider.h
@@ -26,6 +26,7 @@ public:
F32 min_value,
F32 max_value,
F32 increment,
+ BOOL volume,
const LLString& control_name = LLString::null );
virtual EWidgetType getWidgetType() const;
@@ -46,6 +47,7 @@ public:
F32 getMinValue() const { return mMinValue; }
F32 getMaxValue() const { return mMaxValue; }
F32 getIncrement() const { return mIncrement; }
+ BOOL getVolumeSlider() const { return mVolumeSlider; }
void setMinValue(F32 min_value) {mMinValue = min_value;}
void setMaxValue(F32 max_value) {mMaxValue = max_value;}
void setIncrement(F32 increment) {mIncrement = increment;}
@@ -59,12 +61,16 @@ public:
virtual void draw();
protected:
+ void setValueAndCommit(F32 value);
+
+protected:
F32 mValue;
F32 mInitialValue;
F32 mMinValue;
F32 mMaxValue;
F32 mIncrement;
+ BOOL mVolumeSlider;
S32 mMouseOffset;
LLRect mDragStartThumbRect;
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 8b5cd4690e..4ae8c5d222 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -37,6 +37,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
S32 text_left,
BOOL show_text,
BOOL can_edit_text,
+ BOOL volume,
void (*commit_callback)(LLUICtrl*, void*),
void* callback_user_data,
F32 initial_value, F32 min_value, F32 max_value, F32 increment,
@@ -45,6 +46,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
mFont(font),
mShowText( show_text ),
mCanEditText( can_edit_text ),
+ mVolumeSlider( volume ),
mPrecision( 3 ),
mLabelBox( NULL ),
mLabelWidth( label_width ),
@@ -84,7 +86,7 @@ LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect,
"slider",
slider_rect,
LLSliderCtrl::onSliderCommit, this,
- initial_value, min_value, max_value, increment,
+ initial_value, min_value, max_value, increment, volume,
control_which );
addChild( mSlider );
@@ -423,6 +425,8 @@ LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const
node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
+ node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider);
+
node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
if (mLabelBox)
@@ -474,6 +478,9 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
BOOL can_edit_text = FALSE;
node->getAttributeBOOL("can_edit_text", can_edit_text);
+ BOOL volume = FALSE;
+ node->getAttributeBOOL("volume", volume);
+
F32 initial_value = 0.f;
node->getAttributeF32("initial_val", initial_value);
@@ -521,6 +528,7 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
rect.getWidth() - text_left,
show_text,
can_edit_text,
+ volume,
callback,
NULL,
initial_value,
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 2185e42eb1..0780350462 100644
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -40,6 +40,7 @@ public:
S32 text_left,
BOOL show_text,
BOOL can_edit_text,
+ BOOL volume,
void (*commit_callback)(LLUICtrl*, void*),
void* callback_userdata,
F32 initial_value, F32 min_value, F32 max_value, F32 increment,
@@ -104,7 +105,8 @@ private:
const LLFontGL* mFont;
BOOL mShowText;
BOOL mCanEditText;
-
+ BOOL mVolumeSlider;
+
S32 mPrecision;
LLTextBox* mLabelBox;
S32 mLabelWidth;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index ef527b32c2..65551e5c48 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -50,6 +50,7 @@ LLTabContainerCommon::LLTabContainerCommon(
:
LLPanel(name, rect, bordered),
mCurrentTabIdx(-1),
+ mTabsHidden(FALSE),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
@@ -75,6 +76,7 @@ LLTabContainerCommon::LLTabContainerCommon(
:
LLPanel(name, rect_control, bordered),
mCurrentTabIdx(-1),
+ mTabsHidden(FALSE),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
@@ -127,11 +129,11 @@ void LLTabContainerCommon::addPlaceholder(LLPanel* child, const LLString& label)
addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
}
-void LLTabContainerCommon::lockTabs()
+void LLTabContainerCommon::lockTabs(S32 num_tabs)
{
- // count current tabs and ensure no new tabs get
+ // count current tabs or use supplied value and ensure no new tabs get
// inserted between them
- mLockedTabCount = getTabCount();
+ mLockedTabCount = num_tabs > 0 ? num_tabs : getTabCount();
}
void LLTabContainerCommon::removeTabPanel(LLPanel* child)
@@ -522,12 +524,12 @@ void LLTabContainerCommon::setTabPanelFlashing(LLPanel* child, BOOL state )
}
}
-void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name)
+void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name, const LLColor4& color)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(img_name, LLFontGL::RIGHT);
+ tuple->mButton->setImageOverlay(img_name, LLFontGL::RIGHT, color);
}
}
@@ -647,6 +649,8 @@ LLView* LLTabContainerCommon::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtr
}
}
+ node->getAttributeBOOL("hide_tabs", tab_container->mTabsHidden);
+
tab_container->setPanelParameters(node, parent);
if (LLFloater::getFloaterHost())
@@ -1016,10 +1020,11 @@ void LLTabContainer::setPanelTitle(S32 index, const LLString& title)
{
if (index >= 0 && index < (S32)mTabList.size())
{
- LLButton* tab_button = mTabList[index]->mButton;
+ LLTabTuple* tuple = mTabList[index];
+ LLButton* tab_button = tuple->mButton;
const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
mTotalTabWidth -= tab_button->getRect().getWidth();
- tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
+ tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
mTotalTabWidth += tab_button->getRect().getWidth();
tab_button->setLabelSelected(title);
tab_button->setLabelUnselected(title);
@@ -1225,63 +1230,60 @@ void LLTabContainer::draw()
LLPanel::draw();
- // Show all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ // if tabs are hidden, don't draw them and leave them in the invisible state
+ if (!mTabsHidden)
{
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
- }
-
- // Draw some of the buttons...
+ // Show all the buttons
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( TRUE );
+ }
- LLGLEnable scissor_test(has_scroll_arrows ? GL_SCISSOR_TEST : GL_FALSE);
- if( has_scroll_arrows )
- {
- // ...but clip them.
- S32 x1 = mLeftArrowBtn->getRect().mRight;
- S32 y1 = 0;
- S32 x2 = mRightArrowBtn->getRect().mLeft;
- S32 y2 = 1;
- if (mTabList.size() > 0)
+ // Draw some of the buttons...
+ LLRect clip_rect = getLocalRect();
+ if (has_scroll_arrows)
{
- y2 = mTabList[0]->mButton->getRect().mTop;
+ // ...but clip them.
+ clip_rect.mLeft = mLeftArrowBtn->getRect().mRight;
+ clip_rect.mRight = mRightArrowBtn->getRect().mLeft;
}
- LLUI::setScissorRegionLocal(LLRect(x1, y2, x2, y1));
- }
+ LLLocalClipRect clip(clip_rect);
- S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
- S32 idx = 0;
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
+ S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
+ S32 idx = 0;
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
- tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 );
- left += tuple->mButton->getRect().getWidth();
+ tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 );
+ left += tuple->mButton->getRect().getWidth();
- if( idx < mScrollPos )
- {
- if( tuple->mButton->getFlashing() )
+ if( idx < mScrollPos )
{
- mLeftArrowBtn->setFlashing( TRUE );
+ if( tuple->mButton->getFlashing() )
+ {
+ mLeftArrowBtn->setFlashing( TRUE );
+ }
}
- }
- else
- if( max_scroll_visible < idx )
- {
- if( tuple->mButton->getFlashing() )
+ else
+ if( max_scroll_visible < idx )
{
- mRightArrowBtn->setFlashing( TRUE );
+ if( tuple->mButton->getFlashing() )
+ {
+ mRightArrowBtn->setFlashing( TRUE );
+ }
}
- }
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
- tuple->mButton->draw();
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
+ tuple->mButton->draw();
+ }
+ LLUI::popMatrix();
+
+ idx++;
}
- LLUI::popMatrix();
-
- idx++;
}
mLeftArrowBtn->setFlashing(FALSE);
@@ -1608,12 +1610,12 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
}
-void LLTabContainer::setTabImage(LLPanel* child, std::string image_name)
+void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT);
+ tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
// remove current width from total tab strip width
@@ -1622,7 +1624,11 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name)
S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
tuple->mButton->getImageOverlay()->getWidth(0) :
0;
- tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + image_overlay_width, mMinTabWidth, mMaxTabWidth),
+
+ tuple->mPadding = image_overlay_width;
+
+ tuple->mButton->setRightHPad(tuple->mPadding + LLBUTTON_H_PAD);
+ tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
tuple->mButton->getRect().getHeight());
// add back in button width to total tab strip width
mTotalTabWidth += tuple->mButton->getRect().getWidth();
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index a395fd94af..4665983402 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -67,7 +67,7 @@ public:
BOOL placeholder = FALSE,
eInsertionPoint insertion_point = END) = 0;
virtual void addPlaceholder(LLPanel* child, const LLString& label);
- virtual void lockTabs();
+ virtual void lockTabs(S32 num_tabs = 0);
virtual void enableTabButton(S32 which, BOOL enable);
@@ -94,7 +94,7 @@ public:
BOOL getTabPanelFlashing(LLPanel* child);
void setTabPanelFlashing(LLPanel* child, BOOL state);
- virtual void setTabImage(LLPanel* child, std::string img_name);
+ virtual void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
void setTitle( const LLString& title );
const LLString getPanelTitle(S32 index);
@@ -135,7 +135,8 @@ protected:
mOnChangeCallback( cb ),
mUserData( userdata ),
mOldState(FALSE),
- mPlaceholderText(placeholder)
+ mPlaceholderText(placeholder),
+ mPadding(0)
{}
LLTabContainerCommon* mTabContainer;
@@ -145,11 +146,13 @@ protected:
void* mUserData;
BOOL mOldState;
LLTextBox* mPlaceholderText;
+ S32 mPadding;
};
typedef std::vector<LLTabTuple*> tuple_list_t;
tuple_list_t mTabList;
S32 mCurrentTabIdx;
+ BOOL mTabsHidden;
BOOL mScrolled;
LLFrameTimer mScrollTimer;
@@ -208,7 +211,7 @@ public:
/*virtual*/ void removeTabPanel( LLPanel* child );
/*virtual*/ void setPanelTitle(S32 index, const LLString& title);
- /*virtual*/ void setTabImage(LLPanel* child, std::string img_name);
+ /*virtual*/ void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
/*virtual*/ void setRightTabBtnOffset( S32 offset );
/*virtual*/ void setMinTabWidth(S32 width);
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index eb59765927..ea5897e28e 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2993,8 +2993,7 @@ void LLTextEditor::draw()
if( getVisible() )
{
{
- LLGLEnable scissor_test(GL_SCISSOR_TEST);
- LLUI::setScissorRegionLocal(LLRect(0, mRect.getHeight(), mRect.getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
+ LLLocalClipRect clip(LLRect(0, mRect.getHeight(), mRect.getWidth() - (mScrollbar->getVisible() ? SCROLLBAR_SIZE : 0), 0));
bindEmbeddedChars( mGLFont );
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index c65500b56c..696be050ce 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -57,6 +57,8 @@ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
LLWindow* LLUI::sWindow = NULL;
LLHtmlHelp* LLUI::sHtmlHelp = NULL;
BOOL LLUI::sShowXUINames = FALSE;
+std::stack<LLRect> LLUI::sClipRectStack;
+
//
// Functions
//
@@ -90,7 +92,7 @@ void make_ui_sound(const LLString& name)
{
llinfos << "ui sound name: " << name << llendl;
}
- LLUI::sAudioCallback(uuid, LLUI::sConfigGroup->getF32("AudioLevelUI"));
+ LLUI::sAudioCallback(uuid);
}
}
}
@@ -1791,3 +1793,59 @@ void LLUI::setHtmlHelp(LLHtmlHelp* html_help)
{
LLUI::sHtmlHelp = html_help;
}
+
+//static
+void LLUI::pushClipRect(const LLRect& rect)
+{
+ LLRect combined_clip_rect = rect;
+ if (!sClipRectStack.empty())
+ {
+ combined_clip_rect.intersectWith(sClipRectStack.top());
+ }
+ sClipRectStack.push(combined_clip_rect);
+ setScissorRegionScreen(combined_clip_rect);
+}
+
+//static
+void LLUI::popClipRect()
+{
+ sClipRectStack.pop();
+ if (!sClipRectStack.empty())
+ {
+ setScissorRegionScreen(sClipRectStack.top());
+ }
+}
+
+LLClipRect::LLClipRect(const LLRect& rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled)
+{
+ if (mEnabled)
+ {
+ LLUI::pushClipRect(rect);
+ }
+}
+
+LLClipRect::~LLClipRect()
+{
+ if (mEnabled)
+ {
+ LLUI::popClipRect();
+ }
+}
+
+LLLocalClipRect::LLLocalClipRect(const LLRect &rect, BOOL enabled) : mScissorState(GL_SCISSOR_TEST, enabled), mEnabled(enabled)
+{
+ if (mEnabled)
+ {
+ LLRect scissor_rect = rect;
+ scissor_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY);
+ LLUI::pushClipRect(scissor_rect);
+ }
+}
+
+LLLocalClipRect::~LLLocalClipRect()
+{
+ if (mEnabled)
+ {
+ LLUI::popClipRect();
+ }
+}
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index dbe79338e5..fefe75f43e 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -16,6 +16,8 @@
#include "llrect.h"
#include "llcoord.h"
#include "llhtmlhelp.h"
+#include "llgl.h"
+#include <stack>
class LLColor4;
class LLVector3;
@@ -123,7 +125,7 @@ extern BOOL gShowTextEditCursor;
extern LLString gLanguage;
class LLImageProviderInterface;
-typedef void (*LLUIAudioCallback)(const LLUUID& uuid, F32 volume);
+typedef void (*LLUIAudioCallback)(const LLUUID& uuid);
class LLUI
{
@@ -144,8 +146,8 @@ public:
//helper functions (should probably move free standing rendering helper functions here)
static LLString locateSkin(const LLString& filename);
- static void setScissorRegionScreen(const LLRect& rect);
- static void setScissorRegionLocal(const LLRect& rect); // works assuming LLUI::translate has been called
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
static void setCursorPositionScreen(S32 x, S32 y);
static void setCursorPositionLocal(LLView* viewp, S32 x, S32 y);
static void setScaleFactor(const LLVector2& scale_factor);
@@ -153,6 +155,11 @@ public:
static LLUUID findAssetUUIDByName(const LLString& name);
static LLVector2 getWindowSize();
static void setHtmlHelp(LLHtmlHelp* html_help);
+
+private:
+ static void setScissorRegionScreen(const LLRect& rect);
+ static void setScissorRegionLocal(const LLRect& rect); // works assuming LLUI::translate has been called
+
public:
static LLControlGroup* sConfigGroup;
static LLControlGroup* sColorsGroup;
@@ -163,6 +170,8 @@ public:
static LLWindow* sWindow;
static BOOL sShowXUINames;
static LLHtmlHelp* sHtmlHelp;
+ static std::stack<LLRect> sClipRectStack;
+
};
// UI widgets
@@ -251,6 +260,7 @@ typedef enum e_widget_type
WIDGET_TYPE_TEXTURE_VIEW,
WIDGET_TYPE_MEMORY_VIEW,
WIDGET_TYPE_FRAME_STAT_VIEW,
+ WIDGET_TYPE_LAYOUT_STACK,
WIDGET_TYPE_DONTCARE,
WIDGET_TYPE_COUNT
} EWidgetType;
@@ -272,38 +282,38 @@ public:
}
// default show and hide methods
- static T* showInstance(const LLSD& seed)
+ static T* showInstance(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::getInstance(seed);
INSTANCE_ADAPTOR::show(instance);
return instance;
}
- static void hideInstance(const LLSD& seed)
+ static void hideInstance(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::getInstance(seed);
INSTANCE_ADAPTOR::hide(instance);
}
- static void toggleInstance(const LLSD& seed)
+ static void toggleInstance(const LLSD& seed = LLSD())
{
- if (!INSTANCE_ADAPTOR::instanceVisible(seed))
+ if (INSTANCE_ADAPTOR::instanceVisible(seed))
{
- INSTANCE_ADAPTOR::showInstance(seed);
+ INSTANCE_ADAPTOR::hideInstance(seed);
}
else
{
- INSTANCE_ADAPTOR::hideInstance(seed);
+ INSTANCE_ADAPTOR::showInstance(seed);
}
}
- static BOOL instanceVisible(const LLSD& seed)
+ static BOOL instanceVisible(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::findInstance(seed);
return instance != NULL && INSTANCE_ADAPTOR::visible(instance);
}
- static T* getInstance(const LLSD& seed)
+ static T* getInstance(const LLSD& seed = LLSD())
{
T* instance = INSTANCE_ADAPTOR::findInstance(seed);
if (instance == NULL)
@@ -312,6 +322,7 @@ public:
}
return instance;
}
+
};
// Creates a UI singleton by ignoring the identifying parameter
@@ -326,12 +337,12 @@ public:
LLUISingleton() : LLUIInstanceMgr<T, INSTANCE_ADAPTOR>() { sInstance = (T*)this; }
~LLUISingleton() { sInstance = NULL; }
- static T* findInstance(const LLSD& seed)
+ static T* findInstance(const LLSD& seed = LLSD())
{
return sInstance;
}
- static T* createInstance(const LLSD& seed)
+ static T* createInstance(const LLSD& seed = LLSD())
{
if (sInstance == NULL)
{
@@ -346,4 +357,24 @@ protected:
template <class T, class U> T* LLUISingleton<T,U>::sInstance = NULL;
+class LLClipRect
+{
+public:
+ LLClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLClipRect();
+protected:
+ LLGLState mScissorState;
+ BOOL mEnabled;
+};
+
+class LLLocalClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLLocalClipRect();
+protected:
+ LLGLState mScissorState;
+ BOOL mEnabled;
+};
+
#endif
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index abf796fde0..46bb977f7e 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -236,7 +236,7 @@ public:
/*virtual*/ void operator() (LLView * parent, viewList_t &children) const
{
children.sort(CompareByDefaultTabGroup(parent->getCtrlOrder(), parent->getDefaultTabGroup()));
- }
+ }
};
BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields)
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 1d149b63e2..b4551c1852 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -69,7 +69,7 @@ const LLString LLUICtrlFactory::sUICtrlNames[WIDGET_TYPE_COUNT] =
LLString("web_browser"), //WIDGET_TYPE_WEBBROWSER
LLString("slider"), //WIDGET_TYPE_SLIDER, actually LLSliderCtrl
LLString("slider_bar"), //WIDGET_TYPE_SLIDER_BAR, actually LLSlider
- LLString("volume_slider"), //WIDGET_TYPE_VOLUME_SLIDER, actually LLVolumeSliderCtrl
+ LLString("volume_slider"), //WIDGET_TYPE_VOLUME_SLIDER, actually LLSlider + "volume" param
LLString("spinner"), //WIDGET_TYPE_SPINNER, actually LLSpinCtrl
LLString("text_editor"), //WIDGET_TYPE_TEXT_EDITOR
LLString("texture_picker"),//WIDGET_TYPE_TEXTURE_PICKER
@@ -135,6 +135,7 @@ const LLString LLUICtrlFactory::sUICtrlNames[WIDGET_TYPE_COUNT] =
LLString("texture_view"), //WIDGET_TYPE_TEXTURE_VIEW
LLString("memory_view"), //WIDGET_TYPE_MEMORY_VIEW
LLString("frame_stat_view"), //WIDGET_TYPE_FRAME_STAT_VIEW
+ LLString("layout_stack"), //WIDGET_TYPE_LAYOUT_STACK
LLString("DONT_CARE"), //WIDGET_TYPE_DONTCARE
};
@@ -177,6 +178,7 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator<LLScrollListCtrl>::registerCreator(LL_SCROLL_LIST_CTRL_TAG, this);
LLUICtrlCreator<LLSliderCtrl>::registerCreator(LL_SLIDER_CTRL_TAG, this);
LLUICtrlCreator<LLSlider>::registerCreator(LL_SLIDER_TAG, this);
+ LLUICtrlCreator<LLSlider>::registerCreator(LL_VOLUME_SLIDER_CTRL_TAG, this);
LLUICtrlCreator<LLSpinCtrl>::registerCreator(LL_SPIN_CTRL_TAG, this);
LLUICtrlCreator<LLTextBox>::registerCreator(LL_TEXT_BOX_TAG, this);
LLUICtrlCreator<LLRadioGroup>::registerCreator(LL_RADIO_GROUP_TAG, this);
@@ -190,6 +192,7 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlCreator<LLMenuGL>::registerCreator(LL_MENU_GL_TAG, this);
LLUICtrlCreator<LLMenuBarGL>::registerCreator(LL_MENU_BAR_GL_TAG, this);
LLUICtrlCreator<LLScrollingPanelList>::registerCreator(LL_SCROLLING_PANEL_LIST_TAG, this);
+ LLUICtrlCreator<LLLayoutStack>::registerCreator(LL_LAYOUT_STACK_TAG, this);
setupPaths();
@@ -745,6 +748,37 @@ LLScrollingPanelList* LLUICtrlFactory::getScrollingPanelList(LLPanel* panelp, co
return (LLScrollingPanelList*)panelp->getCtrlByNameAndType(name, WIDGET_TYPE_SCROLLING_PANEL_LIST);
}
+
+LLCtrlListInterface* LLUICtrlFactory::getListInterfaceByName(LLPanel* panelp, const LLString& name)
+{
+ LLView* viewp = panelp->getCtrlByNameAndType(name, WIDGET_TYPE_DONTCARE);
+ if (viewp && viewp->isCtrl())
+ {
+ return ((LLUICtrl*)viewp)->getListInterface();
+ }
+ return NULL;
+}
+
+LLCtrlSelectionInterface* LLUICtrlFactory::getSelectionInterfaceByName(LLPanel* panelp, const LLString& name)
+{
+ LLView* viewp = panelp->getCtrlByNameAndType(name, WIDGET_TYPE_DONTCARE);
+ if (viewp && viewp->isCtrl())
+ {
+ return ((LLUICtrl*)viewp)->getSelectionInterface();
+ }
+ return NULL;
+}
+
+LLCtrlScrollInterface* LLUICtrlFactory::getScrollInterfaceByName(LLPanel* panelp, const LLString& name)
+{
+ LLView* viewp = panelp->getCtrlByNameAndType(name, WIDGET_TYPE_DONTCARE);
+ if (viewp && viewp->isCtrl())
+ {
+ return ((LLUICtrl*)viewp)->getScrollInterface();
+ }
+ return NULL;
+}
+
void LLUICtrlFactory::registerCreator(LLString ctrlname, creator_function_t function)
{
LLString::toLower(ctrlname);
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index c7280aa4a2..04a8a83cfa 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -45,6 +45,9 @@ class LLWebBrowserCtrl;
class LLViewBorder;
class LLColorSwatchCtrl;
class LLScrollingPanelList;
+class LLCtrlListInterface;
+class LLCtrlSelectionInterface;
+class LLCtrlScrollInterface;
// Widget
@@ -103,6 +106,11 @@ public:
static LLMenuItemCallGL* getMenuItemCallByName(LLPanel* panelp, const LLString& name);
static LLScrollingPanelList* getScrollingPanelList(LLPanel* panelp, const LLString& name);
+ // interface getters
+ static LLCtrlListInterface* getListInterfaceByName(LLPanel* panelp, const LLString& name);
+ static LLCtrlSelectionInterface* getSelectionInterfaceByName(LLPanel* panelp, const LLString& name);
+ static LLCtrlScrollInterface* getScrollInterfaceByName(LLPanel* panelp, const LLString& name);
+
LLPanel* createFactoryPanel(LLString name);
virtual LLView* createCtrlWidget(LLPanel *parent, LLXMLNodePtr node);
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 8c5b587158..900a867164 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -10,6 +10,9 @@
#include "lluistring.h"
+const LLString::format_map_t LLUIString::sNullArgs;
+
+
// public
LLUIString::LLUIString(const LLString& instring, const LLString::format_map_t& args)
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index 8c2e3c481c..c3113cbe74 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -75,6 +75,8 @@ public:
void insert(S32 charidx, const LLWString& wchars);
void replace(S32 charidx, llwchar wc);
+ static const LLString::format_map_t sNullArgs;
+
private:
void format();
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index dbc635830b..b87d82653a 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -305,6 +305,10 @@ void LLView::moveChildToFrontOfTabGroup(LLUICtrl* child)
void LLView::addChild(LLView* child, S32 tab_group)
{
+ if (mParentView == child)
+ {
+ llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
+ }
// remove from current parent
if (child->mParentView)
{
@@ -328,6 +332,10 @@ void LLView::addChild(LLView* child, S32 tab_group)
void LLView::addChildAtEnd(LLView* child, S32 tab_group)
{
+ if (mParentView == child)
+ {
+ llerrs << "Adding view " << child->getName() << " as child of itself" << llendl;
+ }
// remove from current parent
if (child->mParentView)
{
@@ -732,18 +740,22 @@ void LLView::setEnabled(BOOL enabled)
// virtual
void LLView::setVisible(BOOL visible)
{
- if( !visible && (gFocusMgr.getTopCtrl() == this) )
- {
- gFocusMgr.setTopCtrl( NULL );
- }
-
if ( mVisible != visible )
{
- // tell all children of this view that the visibility may have changed
- onVisibilityChange ( visible );
- }
+ if( !visible && (gFocusMgr.getTopCtrl() == this) )
+ {
+ gFocusMgr.setTopCtrl( NULL );
+ }
- mVisible = visible;
+ mVisible = visible;
+
+ // notify children of visibility change if root, or part of visible hierarchy
+ if (!getParent() || getParent()->isInVisibleChain())
+ {
+ // tell all children of this view that the visibility may have changed
+ onVisibilityChange( visible );
+ }
+ }
}
// virtual
@@ -758,7 +770,7 @@ BOOL LLView::setLabelArg(const LLString& key, const LLString& text)
return FALSE;
}
-void LLView::onVisibilityChange ( BOOL curVisibilityIn )
+void LLView::onVisibilityChange ( BOOL new_visibility )
{
for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
@@ -766,7 +778,7 @@ void LLView::onVisibilityChange ( BOOL curVisibilityIn )
// only views that are themselves visible will have their overall visibility affected by their ancestors
if (viewp->getVisible())
{
- viewp->onVisibilityChange ( curVisibilityIn );
+ viewp->onVisibilityChange ( new_visibility );
}
}
}
@@ -1370,64 +1382,61 @@ LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
void LLView::draw()
{
- if (getVisible())
+ if (sDebugRects)
{
- if (sDebugRects)
- {
- drawDebugRect();
+ drawDebugRect();
- // Check for bogus rectangle
- if (mRect.mRight <= mRect.mLeft
- || mRect.mTop <= mRect.mBottom)
- {
- llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
- }
+ // Check for bogus rectangle
+ if (mRect.mRight <= mRect.mLeft
+ || mRect.mTop <= mRect.mBottom)
+ {
+ llwarns << "Bogus rectangle for " << getName() << " with " << mRect << llendl;
}
+ }
- LLRect rootRect = getRootView()->getRect();
- LLRect screenRect;
+ LLRect rootRect = getRootView()->getRect();
+ LLRect screenRect;
- // draw focused control on top of everything else
- LLView* focus_view = gFocusMgr.getKeyboardFocus();
- if (focus_view && focus_view->getParent() != this)
- {
- focus_view = NULL;
- }
+ // draw focused control on top of everything else
+ LLView* focus_view = gFocusMgr.getKeyboardFocus();
+ if (focus_view && focus_view->getParent() != this)
+ {
+ focus_view = NULL;
+ }
- for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
- {
- LLView *viewp = *child_iter;
- ++sDepth;
+ for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter)
+ {
+ LLView *viewp = *child_iter;
+ ++sDepth;
- if (viewp->getVisible() && viewp != focus_view)
+ if (viewp->getVisible() && viewp != focus_view)
+ {
+ // Only draw views that are within the root view
+ localRectToScreen(viewp->getRect(),&screenRect);
+ if ( rootRect.rectInRect(&screenRect) )
{
- // Only draw views that are within the root view
- localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect.rectInRect(&screenRect) )
+ glMatrixMode(GL_MODELVIEW);
+ LLUI::pushMatrix();
{
- glMatrixMode(GL_MODELVIEW);
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
- viewp->draw();
- }
- LLUI::popMatrix();
+ LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f);
+ viewp->draw();
}
+ LLUI::popMatrix();
}
-
- --sDepth;
}
- if (focus_view && focus_view->getVisible())
- {
- drawChild(focus_view);
- }
+ --sDepth;
+ }
- // HACK
- if (sEditingUI && this == sEditingUIView)
- {
- drawDebugRect();
- }
+ if (focus_view && focus_view->getVisible())
+ {
+ drawChild(focus_view);
+ }
+
+ // HACK
+ if (sEditingUI && this == sEditingUIView)
+ {
+ drawDebugRect();
}
}
@@ -1480,13 +1489,13 @@ void LLView::drawDebugRect()
}
}
-void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset)
+void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_draw)
{
if (childp && childp->getParent() == this)
{
++sDepth;
- if (childp->getVisible())
+ if (childp->getVisible() || force_draw)
{
glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
@@ -1616,7 +1625,7 @@ void LLView::updateRect()
LLView* viewp = *child_it;
if (viewp->getVisible())
{
- child_spanning_rect |= viewp->mRect;
+ child_spanning_rect.unionWith(viewp->mRect);
}
}
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index f9875e8cca..18f453f621 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -359,7 +359,7 @@ public:
virtual void draw();
void drawDebugRect();
- void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0);
+ void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);
virtual const LLString& getName() const;