summaryrefslogtreecommitdiff
path: root/indra/llui/lltabcontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lltabcontainer.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llui/lltabcontainer.cpp715
1 files changed, 474 insertions, 241 deletions
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 3ca05ff0ff..6f858cdeb3 100644..100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -2,40 +2,33 @@
* @file lltabcontainer.cpp
* @brief LLTabContainer class
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltabcontainer.h"
-
+#include "llviewereventrecorder.h"
#include "llfocusmgr.h"
-#include "llbutton.h"
#include "lllocalcliprect.h"
#include "llrect.h"
#include "llresizehandle.h"
@@ -44,6 +37,7 @@
#include "lluictrlfactory.h"
#include "llrender.h"
#include "llfloater.h"
+#include "lltrans.h"
//----------------------------------------------------------------------------
@@ -95,6 +89,96 @@ public:
//----------------------------------------------------------------------------
+//============================================================================
+/*
+ * @file lltabcontainer.cpp
+ * @brief class implements LLButton with LLIconCtrl on it
+ */
+class LLCustomButtonIconCtrl : public LLButton
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLButton::Params>
+ {
+ // LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value
+ Optional<S32> icon_ctrl_pad;
+
+ Params()
+ : icon_ctrl_pad("icon_ctrl_pad", 1)
+ {}
+ };
+
+protected:
+ friend class LLUICtrlFactory;
+
+ LLCustomButtonIconCtrl(const Params& p)
+ : LLButton(p),
+ mIcon(NULL),
+ mIconAlignment(LLFontGL::HCENTER),
+ mIconCtrlPad(p.icon_ctrl_pad)
+ {}
+
+public:
+
+ void updateLayout()
+ {
+ LLRect button_rect = getRect();
+ LLRect icon_rect = mIcon->getRect();
+
+ S32 icon_size = button_rect.getHeight() - 2*mIconCtrlPad;
+
+ switch(mIconAlignment)
+ {
+ case LLFontGL::LEFT:
+ icon_rect.setLeftTopAndSize(button_rect.mLeft + mIconCtrlPad, button_rect.mTop - mIconCtrlPad,
+ icon_size, icon_size);
+ setLeftHPad(icon_size + mIconCtrlPad * 2);
+ break;
+ case LLFontGL::HCENTER:
+ icon_rect.setLeftTopAndSize(button_rect.mRight - (button_rect.getWidth() + mIconCtrlPad - icon_size)/2, button_rect.mTop - mIconCtrlPad,
+ icon_size, icon_size);
+ setRightHPad(icon_size + mIconCtrlPad * 2);
+ break;
+ case LLFontGL::RIGHT:
+ icon_rect.setLeftTopAndSize(button_rect.mRight - mIconCtrlPad - icon_size, button_rect.mTop - mIconCtrlPad,
+ icon_size, icon_size);
+ setRightHPad(icon_size + mIconCtrlPad * 2);
+ break;
+ default:
+ break;
+ }
+ mIcon->setRect(icon_rect);
+ }
+
+ void setIcon(LLIconCtrl* icon, LLFontGL::HAlign alignment = LLFontGL::LEFT)
+ {
+ if(icon)
+ {
+ if(mIcon)
+ {
+ removeChild(mIcon);
+ mIcon->die();
+ }
+ mIcon = icon;
+ mIconAlignment = alignment;
+
+ addChild(mIcon);
+ updateLayout();
+ }
+ }
+
+ LLIconCtrl* getIconCtrl() const
+ {
+ return mIcon;
+ }
+
+private:
+ LLIconCtrl* mIcon;
+ LLFontGL::HAlign mIconAlignment;
+ S32 mIconCtrlPad;
+};
+//============================================================================
+
struct LLPlaceHolderPanel : public LLPanel
{
// create dummy param block to register with "placeholder" nane
@@ -105,24 +189,37 @@ struct LLPlaceHolderPanel : public LLPanel
static LLDefaultChildRegistry::Register<LLPlaceHolderPanel> r1("placeholder");
static LLDefaultChildRegistry::Register<LLTabContainer> r2("tab_container");
+LLTabContainer::TabParams::TabParams()
+: tab_top_image_unselected("tab_top_image_unselected"),
+ tab_top_image_selected("tab_top_image_selected"),
+ tab_top_image_flash("tab_top_image_flash"),
+ tab_bottom_image_unselected("tab_bottom_image_unselected"),
+ tab_bottom_image_selected("tab_bottom_image_selected"),
+ tab_bottom_image_flash("tab_bottom_image_flash"),
+ tab_left_image_unselected("tab_left_image_unselected"),
+ tab_left_image_selected("tab_left_image_selected"),
+ tab_left_image_flash("tab_left_image_flash")
+{}
+
LLTabContainer::Params::Params()
: tab_width("tab_width"),
tab_min_width("tab_min_width"),
tab_max_width("tab_max_width"),
tab_height("tab_height"),
+ label_pad_bottom("label_pad_bottom"),
+ label_pad_left("label_pad_left"),
tab_position("tab_position"),
hide_tabs("hide_tabs", false),
tab_padding_right("tab_padding_right"),
- tab_top_image_unselected("tab_top_image_unselected"),
- tab_top_image_selected("tab_top_image_selected"),
- tab_bottom_image_unselected("tab_bottom_image_unselected"),
- tab_bottom_image_selected("tab_bottom_image_selected"),
- tab_left_image_unselected("tab_left_image_unselected"),
- tab_left_image_selected("tab_left_image_selected")
-{
- name(std::string("tab_container"));
- mouse_opaque = false;
-}
+ first_tab("first_tab"),
+ middle_tab("middle_tab"),
+ last_tab("last_tab"),
+ use_custom_icon_ctrl("use_custom_icon_ctrl", false),
+ open_tabs_on_drag_and_drop("open_tabs_on_drag_and_drop", false),
+ tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
+ use_ellipses("use_ellipses"),
+ font_halign("halign")
+{}
LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
: LLPanel(p),
@@ -138,6 +235,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mMinTabWidth(0),
mMaxTabWidth(p.tab_max_width),
mTabHeight(p.tab_height),
+ mLabelPadBottom(p.label_pad_bottom),
+ mLabelPadLeft(p.label_pad_left),
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical( p.tab_position == LEFT ),
@@ -147,12 +246,15 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mRightTabBtnOffset(p.tab_padding_right),
mTotalTabWidth(0),
mTabPosition(p.tab_position),
- mImageTopUnselected(p.tab_top_image_unselected),
- mImageTopSelected(p.tab_top_image_selected),
- mImageBottomUnselected(p.tab_bottom_image_unselected),
- mImageBottomSelected(p.tab_bottom_image_selected),
- mImageLeftUnselected(p.tab_left_image_unselected),
- mImageLeftSelected(p.tab_left_image_selected)
+ mFontHalign(p.font_halign),
+ mFont(p.font),
+ mFirstTabParams(p.first_tab),
+ mMiddleTabParams(p.middle_tab),
+ mLastTabParams(p.last_tab),
+ mCustomIconCtrlUsed(p.use_custom_icon_ctrl),
+ mOpenTabsOnDragAndDrop(p.open_tabs_on_drag_and_drop),
+ mTabIconCtrlPad(p.tab_icon_ctrl_pad),
+ mUseTabEllipses(p.use_ellipses)
{
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
@@ -179,6 +281,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
LLTabContainer::~LLTabContainer()
{
std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
+ mTabList.clear();
}
//virtual
@@ -256,8 +359,6 @@ bool LLTabContainer::addChild(LLView* view, S32 tab_group)
if (panelp)
{
- panelp->setSaveToXML(TRUE);
-
addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast<LLPlaceHolderPanel*>(view) != NULL));
return true;
}
@@ -306,7 +407,7 @@ void LLTabContainer::draw()
}
}
- setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)));
+ setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLSmoothInterpolation::getInterpolant(0.08f)));
BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0));
if (!mIsVertical)
@@ -340,7 +441,13 @@ void LLTabContainer::draw()
}
}
- LLPanel::draw();
+ {
+ LLRect clip_rect = getLocalRect();
+ clip_rect.mLeft+=(LLPANEL_BORDER_WIDTH + 2);
+ clip_rect.mRight-=(LLPANEL_BORDER_WIDTH + 2);
+ LLLocalClipRect clip(clip_rect);
+ LLPanel::draw();
+ }
// if tabs are hidden, don't draw them and leave them in the invisible state
if (!getTabsHidden())
@@ -352,24 +459,6 @@ void LLTabContainer::draw()
tuple->mButton->setVisible( TRUE );
}
- // Draw some of the buttons...
- LLRect clip_rect = getLocalRect();
- if (has_scroll_arrows)
- {
- // ...but clip them.
- if (mIsVertical)
- {
- clip_rect.mBottom = mNextArrowBtn->getRect().mTop + 3*tabcntrv_pad;
- clip_rect.mTop = mPrevArrowBtn->getRect().mBottom - 3*tabcntrv_pad;
- }
- else
- {
- clip_rect.mLeft = mPrevArrowBtn->getRect().mRight;
- clip_rect.mRight = mNextArrowBtn->getRect().mLeft;
- }
- }
- LLLocalClipRect clip(clip_rect);
-
S32 max_scroll_visible = getTabCount() - getMaxScrollPos() + getScrollPos();
S32 idx = 0;
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
@@ -398,12 +487,6 @@ void LLTabContainer::draw()
}
}
}
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
- tuple->mButton->draw();
- }
- LLUI::popMatrix();
idx++;
}
@@ -412,20 +495,20 @@ void LLTabContainer::draw()
if( mIsVertical && has_scroll_arrows )
{
// Redraw the arrows so that they appears on top.
- gGL.pushMatrix();
- gGL.translatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
mPrevArrowBtn->draw();
- gGL.popMatrix();
+ gGL.popUIMatrix();
- gGL.pushMatrix();
- gGL.translatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
mNextArrowBtn->draw();
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
}
- mPrevArrowBtn->setFlashing(FALSE);
- mNextArrowBtn->setFlashing(FALSE);
+ mPrevArrowBtn->setFlashing(false);
+ mNextArrowBtn->setFlashing(false);
}
@@ -469,23 +552,23 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
}
S32 tab_count = getTabCount();
- if (tab_count > 0)
+ if (tab_count > 0 && !getTabsHidden())
{
LLTabTuple* firsttuple = getTab(0);
LLRect tab_rect;
if (mIsVertical)
{
tab_rect = LLRect(firsttuple->mButton->getRect().mLeft,
- has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - tabcntrv_pad : mPrevArrowBtn->getRect().mTop,
- firsttuple->mButton->getRect().mRight,
- has_scroll_arrows ? mNextArrowBtn->getRect().mTop + tabcntrv_pad : mNextArrowBtn->getRect().mBottom );
+ has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - tabcntrv_pad : mPrevArrowBtn->getRect().mTop,
+ firsttuple->mButton->getRect().mRight,
+ has_scroll_arrows ? mNextArrowBtn->getRect().mTop + tabcntrv_pad : mNextArrowBtn->getRect().mBottom );
}
else
{
tab_rect = LLRect(has_scroll_arrows ? mPrevArrowBtn->getRect().mRight : mJumpPrevArrowBtn->getRect().mLeft,
- firsttuple->mButton->getRect().mTop,
- has_scroll_arrows ? mNextArrowBtn->getRect().mLeft : mJumpNextArrowBtn->getRect().mRight,
- firsttuple->mButton->getRect().mBottom );
+ firsttuple->mButton->getRect().mTop,
+ has_scroll_arrows ? mNextArrowBtn->getRect().mLeft : mJumpNextArrowBtn->getRect().mRight,
+ firsttuple->mButton->getRect().mBottom );
}
if( tab_rect.pointInRect( x, y ) )
{
@@ -496,6 +579,11 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
tab_button->setFocus(TRUE);
}
}
+ if (handled) {
+ // Note: May need to also capture local coords right here ?
+ LLViewerEventRecorder::instance().update_xui(getPathname( ));
+ }
+
return handled;
}
@@ -547,30 +635,33 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
BOOL handled = FALSE;
BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
+ S32 local_x = x - getRect().mLeft;
+ S32 local_y = y - getRect().mBottom;
+
if (has_scroll_arrows)
{
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
+ local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
+ local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
handled = mJumpPrevArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
+ local_x = x - mJumpNextArrowBtn->getRect().mLeft;
+ local_y = y - mJumpNextArrowBtn->getRect().mBottom;
handled = mJumpNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
+ local_x = x - mPrevArrowBtn->getRect().mLeft;
+ local_y = y - mPrevArrowBtn->getRect().mBottom;
handled = mPrevArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y))
{
- S32 local_x = x - mNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mNextArrowBtn->getRect().mBottom;
+ local_x = x - mNextArrowBtn->getRect().mLeft;
+ local_y = y - mNextArrowBtn->getRect().mBottom;
handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
}
@@ -594,6 +685,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
}
gFocusMgr.setMouseCapture(NULL);
}
+ if (handled) {
+ // Note: may need to capture local coords here
+ LLViewerEventRecorder::instance().update_xui(getPathname( ));
+ }
return handled;
}
@@ -602,7 +697,7 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
{
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
BOOL handled = LLPanel::handleToolTip( x, y, mask);
- if (!handled && getTabCount() > 0)
+ if (!handled && getTabCount() > 0 && !getTabsHidden())
{
LLTabTuple* firsttuple = getTab(0);
@@ -638,12 +733,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
}
}
}
-
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
- }
}
return handled;
}
@@ -739,48 +828,62 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
{
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
- if( mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
+ if(mOpenTabsOnDragAndDrop && !getTabsHidden())
{
- if (has_scroll_arrows)
+ // In that case, we'll open the hovered tab while dragging and dropping items.
+ // This allows for drilling through tabs.
+ if (mDragAndDropDelayTimer.getStarted())
{
- if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
+ if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME)
{
- S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
- mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
- mJumpNextArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mPrevArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
- S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
- mPrevArrowBtn->handleHover(local_x, local_y, mask);
- }
- else if (mNextArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mNextArrowBtn->getRect().mLeft;
- S32 local_y = y - mNextArrowBtn->getRect().mBottom;
- mNextArrowBtn->handleHover(local_x, local_y, mask);
- }
- }
+ if (has_scroll_arrows)
+ {
+ if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
+ S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
+ mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
+ S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
+ mJumpNextArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ if (mPrevArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
+ S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
+ mPrevArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ else if (mNextArrowBtn->getRect().pointInRect(x, y))
+ {
+ S32 local_x = x - mNextArrowBtn->getRect().mLeft;
+ S32 local_y = y - mNextArrowBtn->getRect().mBottom;
+ mNextArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ }
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
- S32 local_x = x - tuple->mButton->getRect().mLeft;
- S32 local_y = y - tuple->mButton->getRect().mBottom;
- if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
- {
- tuple->mButton->onCommit();
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( TRUE );
+ S32 local_x = x - tuple->mButton->getRect().mLeft;
+ S32 local_y = y - tuple->mButton->getRect().mBottom;
+ if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
+ {
+ tuple->mButton->onCommit();
+ }
+ }
+ // Stop the timer whether successful or not. Don't let it run forever.
mDragAndDropDelayTimer.stop();
}
}
+ else
+ {
+ // Start a timer so we don't open tabs as soon as we hover on them
+ mDragAndDropDelayTimer.start();
+ }
}
return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
@@ -791,9 +894,39 @@ void LLTabContainer::addTabPanel(LLPanel* panelp)
addTabPanel(TabPanelParams().panel(panelp));
}
+// function to update images
+void LLTabContainer::update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos)
+{
+ if (tuple && tuple->mButton)
+ {
+ if (pos == LLTabContainer::TOP)
+ {
+ tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_top_image_unselected));
+ tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_top_image_selected));
+ tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_top_image_flash));
+ }
+ else if (pos == LLTabContainer::BOTTOM)
+ {
+ tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_bottom_image_unselected));
+ tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_bottom_image_selected));
+ tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_bottom_image_flash));
+ }
+ else if (pos == LLTabContainer::LEFT)
+ {
+ tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_left_image_unselected));
+ tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_left_image_selected));
+ tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_left_image_flash));
+ }
+ }
+}
+
void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
LLPanel* child = panel.panel();
+
+ llassert(child);
+ if (!child) return;
+
const std::string& label = panel.label.isProvided()
? panel.label()
: panel.panel()->getLabel();
@@ -810,8 +943,6 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
// already a child of mine
return;
}
- const LLFontGL* font =
- (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall());
// Store the original label for possible xml export.
child->setLabel(label);
@@ -821,7 +952,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
S32 button_width = mMinTabWidth;
if (!mIsVertical)
{
- button_width = llclamp(font->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
+ button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
}
// Tab panel
@@ -851,7 +982,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLRect tab_panel_rect;
if (!getTabsHidden() && mIsVertical)
{
- tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + tabcntrv_pad,
+ tab_panel_rect = LLRect(mMinTabWidth + mRightTabBtnOffset + (LLPANEL_BORDER_WIDTH * 2) + tabcntrv_pad,
getRect().getHeight() - LLPANEL_BORDER_WIDTH,
getRect().getWidth() - LLPANEL_BORDER_WIDTH,
LLPANEL_BORDER_WIDTH);
@@ -888,94 +1019,83 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
else if( getTabPosition() == LLTabContainer::TOP )
{
btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, mTabHeight);
- tab_img = mImageTopUnselected.get();
- tab_selected_img = mImageTopSelected.get();
+ tab_img = mMiddleTabParams.tab_top_image_unselected;
+ tab_selected_img = mMiddleTabParams.tab_top_image_selected;
}
else
{
btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, mTabHeight);
- tab_img = mImageBottomUnselected.get();
- tab_selected_img = mImageBottomSelected.get();
+ tab_img = mMiddleTabParams.tab_bottom_image_unselected;
+ tab_selected_img = mMiddleTabParams.tab_bottom_image_selected;
}
LLTextBox* textbox = NULL;
LLButton* btn = NULL;
+ LLCustomButtonIconCtrl::Params custom_btn_params;
+ {
+ custom_btn_params.icon_ctrl_pad(mTabIconCtrlPad);
+ }
+ LLButton::Params normal_btn_params;
if (placeholder)
{
- btn_rect.translate(0, -LLBUTTON_V_PAD-2);
+ btn_rect.translate(0, -6); // *TODO: make configurable
LLTextBox::Params params;
params.name(trimmed_label);
params.rect(btn_rect);
params.initial_value(trimmed_label);
- params.font(font);
+ params.font(mFont);
textbox = LLUICtrlFactory::create<LLTextBox> (params);
LLButton::Params p;
- p.name("");
+ p.name("placeholder");
btn = LLUICtrlFactory::create<LLButton>(p);
}
else
{
+ LLButton::Params& p = (mCustomIconCtrlUsed ? custom_btn_params : normal_btn_params);
+
+ p.rect(btn_rect);
+ p.font(mFont);
+ p.font_halign = mFontHalign;
+ p.label(trimmed_label);
+ p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
+ if (indent)
+ {
+ p.pad_left(indent);
+ }
+ p.pad_bottom( mLabelPadBottom );
+ p.scale_image(true);
+ p.tab_stop(false);
+ p.label_shadow(false);
+ p.follows.flags = FOLLOWS_LEFT;
+
if (mIsVertical)
{
- LLButton::Params p;
- p.name(std::string("vert tab button"));
- p.rect(btn_rect);
- p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
- p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(font);
- p.label(trimmed_label);
- p.image_unselected(mImageLeftUnselected);
- p.image_selected(mImageLeftSelected);
- p.scale_image(true);
- p.font_halign = LLFontGL::LEFT;
- p.tab_stop(false);
- if (indent)
- {
- p.pad_left(indent);
- }
- btn = LLUICtrlFactory::create<LLButton>(p);
+ p.name("vtab_"+std::string(child->getName()));
+ p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
+ p.image_selected(mMiddleTabParams.tab_left_image_selected);
+ p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
+ }
+ else
+ {
+ p.name("htab_"+std::string(child->getName()));
+ p.visible(false);
+ p.image_unselected(tab_img);
+ p.image_selected(tab_selected_img);
+ p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM);
+ // Try to squeeze in a bit more text
+ p.pad_left( mLabelPadLeft );
+ p.pad_right(2);
+ }
+
+ // *TODO : It seems wrong not to use p in both cases considering the way p is initialized
+ if (mCustomIconCtrlUsed)
+ {
+ btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
}
else
{
- std::string tooltip = trimmed_label;
- tooltip += "\nAlt-Left arrow for previous tab";
- tooltip += "\nAlt-Right arrow for next tab";
-
- LLButton::Params p;
- p.name(std::string(child->getName()) + " tab");
- p.rect(btn_rect);
- p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(font);
- p.label(trimmed_label);
- p.visible(false);
- p.tool_tip(tooltip);
- p.scale_image(true);
- p.image_unselected(tab_img);
- p.image_selected(tab_selected_img);
- p.tab_stop(false);
- // Try to squeeze in a bit more text
- p.pad_left(4);
- p.pad_right(2);
- p.font_halign = LLFontGL::LEFT;
- p.follows.flags = FOLLOWS_LEFT;
- p.follows.flags = FOLLOWS_LEFT;
-
- if (indent)
- {
- p.pad_left(indent);
- }
-
- if( getTabPosition() == TOP )
- {
- p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
- }
- else
- {
- p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
- }
-
btn = LLUICtrlFactory::create<LLButton>(p);
}
}
@@ -983,25 +1103,64 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox );
insertTuple( tuple, insertion_point );
+ // if new tab was added as a first or last tab, update button image
+ // and update button image of any tab it may have affected
+ if (tuple == mTabList.front())
+ {
+ update_images(tuple, mFirstTabParams, getTabPosition());
+
+ if (mTabList.size() == 2)
+ {
+ update_images(mTabList[1], mLastTabParams, getTabPosition());
+ }
+ else if (mTabList.size() > 2)
+ {
+ update_images(mTabList[1], mMiddleTabParams, getTabPosition());
+ }
+ }
+ else if (tuple == mTabList.back())
+ {
+ update_images(tuple, mLastTabParams, getTabPosition());
+
+ if (mTabList.size() > 2)
+ {
+ update_images(mTabList[mTabList.size()-2], mMiddleTabParams, getTabPosition());
+ }
+ }
+
//Don't add button and textbox if tab buttons are invisible(EXT - 576)
if (!getTabsHidden())
{
if (textbox)
{
- textbox->setSaveToXML(false);
addChild( textbox, 0 );
}
if (btn)
{
- btn->setSaveToXML(false);
addChild( btn, 0 );
}
}
+ else
+ {
+ if (textbox)
+ {
+ LLUICtrl::addChild(textbox, 0);
+ }
+ if (btn)
+ {
+ LLUICtrl::addChild(btn, 0);
+ }
+ }
if (child)
{
LLUICtrl::addChild(child, 1);
}
+
+ sendChildToFront(mPrevArrowBtn);
+ sendChildToFront(mNextArrowBtn);
+ sendChildToFront(mJumpPrevArrowBtn);
+ sendChildToFront(mJumpNextArrowBtn);
if( select )
{
@@ -1064,11 +1223,27 @@ void LLTabContainer::removeTabPanel(LLPanel* child)
LLTabTuple* tuple = *iter;
if( tuple->mTabPanel == child )
{
- removeChild( tuple->mButton );
+ // update tab button images if removing the first or last tab
+ if ((tuple == mTabList.front()) && (mTabList.size() > 1))
+ {
+ update_images(mTabList[1], mFirstTabParams, getTabPosition());
+ }
+ else if ((tuple == mTabList.back()) && (mTabList.size() > 2))
+ {
+ update_images(mTabList[mTabList.size()-2], mLastTabParams, getTabPosition());
+ }
+
+ if (!getTabsHidden())
+ {
+ // We need to remove tab buttons only if the tabs are not hidden.
+ removeChild( tuple->mButton );
+ }
delete tuple->mButton;
+ tuple->mButton = NULL;
removeChild( tuple->mTabPanel );
// delete tuple->mTabPanel;
+ tuple->mTabPanel = NULL;
mTabList.erase( iter );
delete tuple;
@@ -1115,6 +1290,10 @@ void LLTabContainer::enableTabButton(S32 which, BOOL enable)
{
mTabList[which]->mButton->setEnabled(enable);
}
+ // Stop the DaD timer as it might run forever
+ // enableTabButton() is typically called on refresh and draw when anything changed
+ // in the tab container so it's a good time to reset that.
+ mDragAndDropDelayTimer.stop();
}
void LLTabContainer::deleteAllTabs()
@@ -1126,9 +1305,11 @@ void LLTabContainer::deleteAllTabs()
removeChild( tuple->mButton );
delete tuple->mButton;
+ tuple->mButton = NULL;
removeChild( tuple->mTabPanel );
// delete tuple->mTabPanel;
+ tuple->mTabPanel = NULL;
}
// Actually delete the tuples themselves
@@ -1299,12 +1480,12 @@ BOOL LLTabContainer::selectTab(S32 which)
cbdata = selected_tuple->mTabPanel->getName();
BOOL res = FALSE;
- if( mValidateSignal( this, cbdata ) )
+ if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) )
{
res = setTab(which);
- if (res)
+ if (res && mCommitSignal)
{
- mCommitSignal(this, cbdata);
+ (*mCommitSignal)(this, cbdata);
}
}
@@ -1331,11 +1512,20 @@ BOOL LLTabContainer::setTab(S32 which)
{
LLTabTuple* tuple = *iter;
BOOL is_selected = ( tuple == selected_tuple );
- tuple->mTabPanel->setVisible( is_selected );
-// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
- tuple->mButton->setToggleState( is_selected );
- // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
- tuple->mButton->setTabStop( is_selected );
+ // Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list
+ if (tuple && tuple->mButton)
+ {
+ tuple->mButton->setUseEllipses(mUseTabEllipses);
+ tuple->mButton->setHAlign(mFontHalign);
+ tuple->mButton->setToggleState( is_selected );
+ // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
+ tuple->mButton->setTabStop( is_selected );
+ }
+ if (tuple && tuple->mTabPanel)
+ {
+ tuple->mTabPanel->setVisible( is_selected );
+ //tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
+ }
if (is_selected)
{
@@ -1362,7 +1552,7 @@ BOOL LLTabContainer::setTab(S32 which)
else
{
S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
- S32 running_tab_width = tuple->mButton->getRect().getWidth();
+ S32 running_tab_width = (tuple && tuple->mButton ? tuple->mButton->getRect().getWidth() : 0);
S32 j = i - 1;
S32 min_scroll_pos = i;
if (running_tab_width < available_width_with_arrows)
@@ -1370,7 +1560,7 @@ BOOL LLTabContainer::setTab(S32 which)
while (j >= 0)
{
LLTabTuple* other_tuple = getTab(j);
- running_tab_width += other_tuple->mButton->getRect().getWidth();
+ running_tab_width += (other_tuple && other_tuple->mButton ? other_tuple->mButton->getRect().getWidth() : 0);
if (running_tab_width > available_width_with_arrows)
{
break;
@@ -1406,8 +1596,7 @@ BOOL LLTabContainer::selectTabByName(const std::string& name)
LLPanel* panel = getPanelByName(name);
if (!panel)
{
- llwarns << "LLTabContainer::selectTabByName("
- << name << ") failed" << llendl;
+ LL_WARNS() << "LLTabContainer::selectTabByName(" << name << ") failed" << LL_ENDL;
return FALSE;
}
@@ -1436,33 +1625,81 @@ void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state )
void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
- static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
+ tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color);
+ reshapeTuple(tuple);
+ }
+}
- if (!mIsVertical)
+void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
+{
+ LLTabTuple* tuple = getTabByPanel(child);
+ if( tuple )
+ {
+ tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color);
+ reshapeTuple(tuple);
+ }
+}
+
+void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
+{
+ LLTabTuple* tuple = getTabByPanel(child);
+ LLCustomButtonIconCtrl* button;
+ bool hasButton = false;
+
+ if(tuple)
+ {
+ button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
+ if(button)
{
- const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
- // remove current width from total tab strip width
- mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+ hasButton = true;
+ button->setIcon(icon);
+ reshapeTuple(tuple);
+ }
+ }
- S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
- tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
- 0;
+ if (!hasButton && (icon != NULL))
+ {
+ // It was assumed that the tab's button would take ownership of the icon pointer.
+ // But since the tab did not have a button, kill the icon to prevent the memory
+ // leak.
+ icon->die();
+ }
+}
- tuple->mPadding = image_overlay_width;
+void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
+{
+ static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
- tuple->mButton->setRightHPad(6);
- 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();
+ if (!mIsVertical)
+ {
+ S32 image_overlay_width = 0;
- // tabs have changed size, might need to scroll to see current tab
- updateMaxScrollPos();
+ if(mCustomIconCtrlUsed)
+ {
+ LLCustomButtonIconCtrl* button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
+ LLIconCtrl* icon_ctrl = button ? button->getIconCtrl() : NULL;
+ image_overlay_width = icon_ctrl ? icon_ctrl->getRect().getWidth() : 0;
}
+ else
+ {
+ image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
+ tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
+ }
+ // remove current width from total tab strip width
+ mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+
+ tuple->mPadding = image_overlay_width;
+
+ tuple->mButton->reshape(llclamp(mFont->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();
+
+ // tabs have changed size, might need to scroll to see current tab
+ updateMaxScrollPos();
}
}
@@ -1525,7 +1762,10 @@ void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel )
LLTabTuple* tuple = getTabByPanel(panel);
selectTabPanel( panel );
- tuple->mTabPanel->setFocus(TRUE);
+ if (tuple)
+ {
+ tuple->mTabPanel->setFocus(TRUE);
+ }
}
void LLTabContainer::onNextBtn( const LLSD& data )
@@ -1626,23 +1866,23 @@ void LLTabContainer::initButtons()
S32 btn_top = (getTabPosition() == TOP ) ? getRect().getHeight() - getTopBorderHeight() : tabcntr_arrow_btn_size + 1;
LLRect left_arrow_btn_rect;
- left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+tabcntr_arrow_btn_size, btn_top + arrow_fudge, tabcntr_arrow_btn_size, tabcntr_arrow_btn_size );
+ left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+tabcntr_arrow_btn_size, btn_top + arrow_fudge, tabcntr_arrow_btn_size, mTabHeight );
LLRect jump_left_arrow_btn_rect;
- jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, tabcntr_arrow_btn_size, tabcntr_arrow_btn_size );
+ jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, tabcntr_arrow_btn_size, mTabHeight );
S32 right_pad = tabcntr_arrow_btn_size + LLPANEL_BORDER_WIDTH + 1;
LLRect right_arrow_btn_rect;
right_arrow_btn_rect.setLeftTopAndSize( getRect().getWidth() - mRightTabBtnOffset - right_pad - tabcntr_arrow_btn_size,
btn_top + arrow_fudge,
- tabcntr_arrow_btn_size, tabcntr_arrow_btn_size );
+ tabcntr_arrow_btn_size, mTabHeight );
LLRect jump_right_arrow_btn_rect;
jump_right_arrow_btn_rect.setLeftTopAndSize( getRect().getWidth() - mRightTabBtnOffset - right_pad,
btn_top + arrow_fudge,
- tabcntr_arrow_btn_size, tabcntr_arrow_btn_size );
+ tabcntr_arrow_btn_size, mTabHeight );
LLButton::Params p;
p.name(std::string("Jump Left Arrow"));
@@ -1702,24 +1942,20 @@ void LLTabContainer::initButtons()
}
}
- mPrevArrowBtn->setSaveToXML(false);
mPrevArrowBtn->setTabStop(FALSE);
addChild(mPrevArrowBtn);
- mNextArrowBtn->setSaveToXML(false);
mNextArrowBtn->setTabStop(FALSE);
addChild(mNextArrowBtn);
if (mJumpPrevArrowBtn)
{
- mJumpPrevArrowBtn->setSaveToXML(false);
mJumpPrevArrowBtn->setTabStop(FALSE);
addChild(mJumpPrevArrowBtn);
}
if (mJumpNextArrowBtn)
{
- mJumpNextArrowBtn->setSaveToXML(false);
mJumpNextArrowBtn->setTabStop(FALSE);
addChild(mJumpNextArrowBtn);
}
@@ -1858,6 +2094,3 @@ void LLTabContainer::commitHoveredButton(S32 x, S32 y)
}
}
}
-
-
-