summaryrefslogtreecommitdiff
path: root/indra/llui/lltabcontainer.cpp
diff options
context:
space:
mode:
authorSteven Bennetts <steve@lindenlab.com>2008-02-19 21:42:32 +0000
committerSteven Bennetts <steve@lindenlab.com>2008-02-19 21:42:32 +0000
commit2e32d44e7165775936beae5d9ef636ff9d3f2bd2 (patch)
tree8153bc399994aabf6e1c41c2d8332e4e8c4ddb78 /indra/llui/lltabcontainer.cpp
parentdb0f5847ea8b96b3c1ac08e7aeb43d83daacb8e4 (diff)
merge svn+ssh://svn.lindenlab.com/svn/linden/qa/combo-merge-ui-2008-02-13 -r 79986 : 80178 -> release.
QAR-290 = QAR-271 + QAR-191
Diffstat (limited to 'indra/llui/lltabcontainer.cpp')
-rw-r--r--indra/llui/lltabcontainer.cpp2393
1 files changed, 1264 insertions, 1129 deletions
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 148060359f..4568ebac29 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1,6 +1,6 @@
/**
* @file lltabcontainer.cpp
- * @brief LLTabContainerCommon base class
+ * @brief LLTabContainer class
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
@@ -30,33 +30,23 @@
*/
#include "linden_common.h"
-
#include "lltabcontainer.h"
-
#include "llfocusmgr.h"
-#include "llfontgl.h"
-#include "llgl.h"
-
#include "llbutton.h"
#include "llrect.h"
-#include "llpanel.h"
#include "llresmgr.h"
-#include "llkeyboard.h"
#include "llresizehandle.h"
-#include "llui.h"
#include "lltextbox.h"
-#include "llcontrol.h"
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
-
#include "lltabcontainervertical.h"
-#include "llglheaders.h"
const F32 SCROLL_STEP_TIME = 0.4f;
const F32 SCROLL_DELAY_TIME = 0.5f;
const S32 TAB_PADDING = 15;
const S32 TABCNTR_TAB_MIN_WIDTH = 60;
+const S32 TABCNTR_VERT_TAB_MIN_WIDTH = 100;
const S32 TABCNTR_TAB_MAX_WIDTH = 150;
const S32 TABCNTR_TAB_PARTIAL_WIDTH = 12; // When tabs are parially obscured, how much can you still see.
const S32 TABCNTR_TAB_HEIGHT = 16;
@@ -64,12 +54,19 @@ const S32 TABCNTR_ARROW_BTN_SIZE = 16;
const S32 TABCNTR_BUTTON_PANEL_OVERLAP = 1; // how many pixels the tab buttons and tab panels overlap.
const S32 TABCNTR_TAB_H_PAD = 4;
+const S32 TABCNTR_CLOSE_BTN_SIZE = 16;
+const S32 TABCNTR_HEADER_HEIGHT = LLPANEL_BORDER_WIDTH + TABCNTR_CLOSE_BTN_SIZE;
+
+const S32 TABCNTRV_CLOSE_BTN_SIZE = 16;
+const S32 TABCNTRV_HEADER_HEIGHT = LLPANEL_BORDER_WIDTH + TABCNTRV_CLOSE_BTN_SIZE;
+//const S32 TABCNTRV_TAB_WIDTH = 100;
+const S32 TABCNTRV_ARROW_BTN_SIZE = 16;
+const S32 TABCNTRV_PAD = 0;
+
-LLTabContainerCommon::LLTabContainerCommon(
- const LLString& name, const LLRect& rect,
- TabPosition pos,
- void(*close_callback)(void*), void* callback_userdata,
- BOOL bordered )
+
+LLTabContainer::LLTabContainer(const LLString& name, const LLRect& rect, TabPosition pos,
+ BOOL bordered, BOOL is_vertical )
:
LLPanel(name, rect, bordered),
mCurrentTabIdx(-1),
@@ -78,50 +75,65 @@ LLTabContainerCommon::LLTabContainerCommon(
mScrollPos(0),
mScrollPosPixels(0),
mMaxScrollPos(0),
- mCloseCallback( close_callback ),
- mCallbackUserdata( callback_userdata ),
+ mCloseCallback( NULL ),
+ mCallbackUserdata( NULL ),
mTitleBox(NULL),
mTopBorderHeight(LLPANEL_BORDER_WIDTH),
mTabPosition(pos),
- mLockedTabCount(0)
+ mLockedTabCount(0),
+ mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
+ mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
+ mPrevArrowBtn(NULL),
+ mNextArrowBtn(NULL),
+ mIsVertical(is_vertical),
+ // Horizontal Specific
+ mJumpPrevArrowBtn(NULL),
+ mJumpNextArrowBtn(NULL),
+ mRightTabBtnOffset(0),
+ mTotalTabWidth(0)
{
+ //RN: HACK to support default min width for legacy vertical tab containers
+ if (mIsVertical)
+ {
+ mMinTabWidth = TABCNTR_VERT_TAB_MIN_WIDTH;
+ }
setMouseOpaque(FALSE);
+ initButtons( );
mDragAndDropDelayTimer.stop();
}
+LLTabContainer::~LLTabContainer()
+{
+ std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
+}
-LLTabContainerCommon::LLTabContainerCommon(
- const LLString& name,
- const LLString& rect_control,
- TabPosition pos,
- void(*close_callback)(void*), void* callback_userdata,
- BOOL bordered )
- :
- LLPanel(name, rect_control, bordered),
- mCurrentTabIdx(-1),
- mTabsHidden(FALSE),
- mScrolled(FALSE),
- mScrollPos(0),
- mScrollPosPixels(0),
- mMaxScrollPos(0),
- mCloseCallback( close_callback ),
- mCallbackUserdata( callback_userdata ),
- mTitleBox(NULL),
- mTopBorderHeight(LLPANEL_BORDER_WIDTH),
- mTabPosition(pos),
- mLockedTabCount(0)
+//virtual
+void LLTabContainer::setValue(const LLSD& value)
{
- setMouseOpaque(FALSE);
- mDragAndDropDelayTimer.stop();
+ selectTab((S32) value.asInteger());
}
+//virtual
+EWidgetType LLTabContainer::getWidgetType() const
+{
+ return WIDGET_TYPE_TAB_CONTAINER;
+}
-LLTabContainerCommon::~LLTabContainerCommon()
+//virtual
+LLString LLTabContainer::getWidgetTag() const
{
- std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
+ return LL_TAB_CONTAINER_COMMON_TAG;
}
-LLView* LLTabContainerCommon::getChildByName(const LLString& name, BOOL recurse) const
+//virtual
+void LLTabContainer::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLPanel::reshape( width, height, called_from_parent );
+ updateMaxScrollPos();
+}
+
+//virtual
+LLView* LLTabContainer::getChildByName(const LLString& name, BOOL recurse) const
{
tuple_list_t::const_iterator itor;
for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
@@ -137,7 +149,7 @@ LLView* LLTabContainerCommon::getChildByName(const LLString& name, BOOL recurse)
for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
{
LLPanel *panel = (*itor)->mTabPanel;
- LLView *child = panel->getChildByName(name, recurse);
+ LLView *child = panel->getChild<LLView>(name, recurse);
if (child)
{
return child;
@@ -147,25 +159,750 @@ LLView* LLTabContainerCommon::getChildByName(const LLString& name, BOOL recurse)
return LLView::getChildByName(name, recurse);
}
-void LLTabContainerCommon::addPlaceholder(LLPanel* child, const LLString& label)
+// virtual
+void LLTabContainer::draw()
{
- addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
+ S32 target_pixel_scroll = 0;
+ S32 cur_scroll_pos = mIsVertical ? 0 : getScrollPos();
+ if (cur_scroll_pos > 0)
+ {
+ S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ if (cur_scroll_pos == 0)
+ {
+ break;
+ }
+ target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
+ cur_scroll_pos--;
+ }
+
+ // Show part of the tab to the left of what is fully visible
+ target_pixel_scroll -= TABCNTR_TAB_PARTIAL_WIDTH;
+ // clamp so that rightmost tab never leaves right side of screen
+ target_pixel_scroll = llmin(mTotalTabWidth - available_width_with_arrows, target_pixel_scroll);
+ }
+
+ setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)));
+ if( getVisible() )
+ {
+ BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
+ if (!mIsVertical)
+ {
+ mJumpPrevArrowBtn->setVisible( has_scroll_arrows );
+ mJumpNextArrowBtn->setVisible( has_scroll_arrows );
+ }
+ mPrevArrowBtn->setVisible( has_scroll_arrows );
+ mNextArrowBtn->setVisible( has_scroll_arrows );
+
+ S32 left = 0, top = 0;
+ if (mIsVertical)
+ {
+ top = getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1 - (has_scroll_arrows ? TABCNTRV_ARROW_BTN_SIZE : 0);
+ top += getScrollPosPixels();
+ }
+ else
+ {
+ // Set the leftmost position of the tab buttons.
+ left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD);
+ left -= getScrollPosPixels();
+ }
+
+ // Hide all the buttons
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( FALSE );
+ }
+
+ LLPanel::draw();
+
+ // if tabs are hidden, don't draw them and leave them in the invisible state
+ if (!getTabsHidden())
+ {
+ // Show all the buttons
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ 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)
+ {
+ LLTabTuple* tuple = *iter;
+
+ tuple->mButton->translate( left ? left - tuple->mButton->getRect().mLeft : 0,
+ top ? top - tuple->mButton->getRect().mTop : 0 );
+ if (top) top -= BTN_HEIGHT + TABCNTRV_PAD;
+ if (left) left += tuple->mButton->getRect().getWidth();
+
+ if (!mIsVertical)
+ {
+ if( idx < getScrollPos() )
+ {
+ if( tuple->mButton->getFlashing() )
+ {
+ mPrevArrowBtn->setFlashing( TRUE );
+ }
+ }
+ else if( max_scroll_visible < idx )
+ {
+ if( tuple->mButton->getFlashing() )
+ {
+ mNextArrowBtn->setFlashing( TRUE );
+ }
+ }
+ }
+ LLUI::pushMatrix();
+ {
+ LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
+ tuple->mButton->draw();
+ }
+ LLUI::popMatrix();
+
+ idx++;
+ }
+
+
+ if( mIsVertical && has_scroll_arrows )
+ {
+ // Redraw the arrows so that they appears on top.
+ glPushMatrix();
+ glTranslatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
+ mPrevArrowBtn->draw();
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
+ mNextArrowBtn->draw();
+ glPopMatrix();
+ }
+ }
+
+ mPrevArrowBtn->setFlashing(FALSE);
+ mNextArrowBtn->setFlashing(FALSE);
+ }
}
-void LLTabContainerCommon::lockTabs(S32 num_tabs)
+
+// virtual
+BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
{
- // count current tabs or use supplied value and ensure no new tabs get
- // inserted between them
- mLockedTabCount = num_tabs > 0 ? llmin(getTabCount(), num_tabs) : getTabCount();
+ BOOL handled = FALSE;
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+
+ 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;
+ handled = mJumpPrevArrowBtn->handleMouseDown(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;
+ handled = mJumpNextArrowBtn->handleMouseDown(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;
+ handled = mPrevArrowBtn->handleMouseDown(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;
+ handled = mNextArrowBtn->handleMouseDown(local_x, local_y, mask);
+ }
+ }
+ if (!handled)
+ {
+ handled = LLPanel::handleMouseDown( x, y, mask );
+ }
+
+ if (getTabCount() > 0)
+ {
+ 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 );
+ }
+ 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 );
+ }
+ if( tab_rect.pointInRect( x, y ) )
+ {
+ LLButton* tab_button = getTab(getCurrentPanelIndex())->mButton;
+ gFocusMgr.setMouseCapture(this);
+ gFocusMgr.setKeyboardFocus(tab_button);
+ }
+ }
+ return handled;
+}
+
+// virtual
+BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
+{
+ BOOL handled = FALSE;
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+
+ 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;
+ handled = mJumpPrevArrowBtn->handleHover(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;
+ handled = mJumpNextArrowBtn->handleHover(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;
+ handled = mPrevArrowBtn->handleHover(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;
+ handled = mNextArrowBtn->handleHover(local_x, local_y, mask);
+ }
+ }
+ if (!handled)
+ {
+ handled = LLPanel::handleHover(x, y, mask);
+ }
+
+ commitHoveredButton(x, y);
+ return handled;
}
-void LLTabContainerCommon::unlockTabs()
+// virtual
+BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
{
- mLockedTabCount = 0;
+ BOOL handled = FALSE;
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+
+ 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;
+ 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;
+ 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;
+ 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;
+ handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);
+ }
+ }
+ if (!handled)
+ {
+ handled = LLPanel::handleMouseUp( x, y, mask );
+ }
+
+ commitHoveredButton(x, y);
+ LLPanel* cur_panel = getCurrentPanel();
+ if (hasMouseCapture())
+ {
+ if (cur_panel)
+ {
+ if (!cur_panel->focusFirstItem(FALSE))
+ {
+ // if nothing in the panel gets focus, make sure the new tab does
+ // otherwise the last tab might keep focus
+ getTab(getCurrentPanelIndex())->mButton->setFocus(TRUE);
+ }
+ }
+ gFocusMgr.setMouseCapture(NULL);
+ }
+ return handled;
+}
+
+// virtual
+BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect )
+{
+ BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
+ if (!handled && getTabCount() > 0)
+ {
+ LLTabTuple* firsttuple = getTab(0);
+
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+ LLRect clip;
+ if (mIsVertical)
+ {
+ clip = 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 );
+ }
+ else
+ {
+ clip = 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 );
+ }
+
+ if( clip.pointInRect( x, y ) )
+ {
+ 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;
+ handled = tuple->mButton->handleToolTip( local_x, local_y, msg, sticky_rect );
+ if( handled )
+ {
+ break;
+ }
+ }
+ }
+
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( FALSE );
+ }
+ }
+ return handled;
+}
+
+// virtual
+BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
+{
+ if (!getEnabled()) return FALSE;
+
+ if (!gFocusMgr.childHasKeyboardFocus(this)) return FALSE;
+
+ BOOL handled = FALSE;
+ if (key == KEY_LEFT && mask == MASK_ALT)
+ {
+ selectPrevTab();
+ handled = TRUE;
+ }
+ else if (key == KEY_RIGHT && mask == MASK_ALT)
+ {
+ selectNextTab();
+ handled = TRUE;
+ }
+
+ if (handled)
+ {
+ if (getCurrentPanel())
+ {
+ getCurrentPanel()->setFocus(TRUE);
+ }
+ }
+
+ if (!gFocusMgr.childHasKeyboardFocus(getCurrentPanel()))
+ {
+ // if child has focus, but not the current panel, focus is on a button
+ if (mIsVertical)
+ {
+ switch(key)
+ {
+ case KEY_UP:
+ selectPrevTab();
+ handled = TRUE;
+ break;
+ case KEY_DOWN:
+ selectNextTab();
+ handled = TRUE;
+ break;
+ case KEY_LEFT:
+ handled = TRUE;
+ break;
+ case KEY_RIGHT:
+ if (getTabPosition() == LEFT && getCurrentPanel())
+ {
+ getCurrentPanel()->setFocus(TRUE);
+ }
+ handled = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch(key)
+ {
+ case KEY_UP:
+ if (getTabPosition() == BOTTOM && getCurrentPanel())
+ {
+ getCurrentPanel()->setFocus(TRUE);
+ }
+ handled = TRUE;
+ break;
+ case KEY_DOWN:
+ if (getTabPosition() == TOP && getCurrentPanel())
+ {
+ getCurrentPanel()->setFocus(TRUE);
+ }
+ handled = TRUE;
+ break;
+ case KEY_LEFT:
+ selectPrevTab();
+ handled = TRUE;
+ break;
+ case KEY_RIGHT:
+ selectNextTab();
+ handled = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return handled;
+}
+
+// virtual
+LLXMLNodePtr LLTabContainer::getXML(bool save_children) const
+{
+ LLXMLNodePtr node = LLPanel::getXML();
+ node->createChild("tab_position", TRUE)->setStringValue((getTabPosition() == TOP ? "top" : "bottom"));
+ return node;
+}
+
+// virtual
+BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, LLString &tooltip)
+{
+ BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
+
+ if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
+ {
+ if (has_scroll_arrows)
+ {
+ if (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->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();
+ mDragAndDropDelayTimer.stop();
+ }
+ }
+ }
+
+ return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
}
-void LLTabContainerCommon::removeTabPanel(LLPanel* child)
+void LLTabContainer::addTabPanel(LLPanel* child,
+ const LLString& label,
+ BOOL select,
+ void (*on_tab_clicked)(void*, bool),
+ void* userdata,
+ S32 indent,
+ BOOL placeholder,
+ eInsertionPoint insertion_point)
{
+ if (child->getParent() == this)
+ {
+ // already a child of mine
+ return;
+ }
+ const LLFontGL* font = gResMgr->getRes( mIsVertical ? LLFONT_SANSSERIF : LLFONT_SANSSERIF_SMALL );
+
+ // Store the original label for possible xml export.
+ child->setLabel(label);
+ LLString trimmed_label = label;
+ LLString::trim(trimmed_label);
+
+ S32 button_width = mMinTabWidth;
+ if (!mIsVertical)
+ {
+ button_width = llclamp(font->getWidth(trimmed_label) + TAB_PADDING, mMinTabWidth, mMaxTabWidth);
+ }
+
+ // Tab panel
+ S32 tab_panel_top;
+ S32 tab_panel_bottom;
+ if( getTabPosition() == LLTabContainer::TOP )
+ {
+ S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT;
+ tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP);
+ tab_panel_bottom = LLPANEL_BORDER_WIDTH;
+ }
+ else
+ {
+ tab_panel_top = getRect().getHeight() - getTopBorderHeight();
+ tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border
+ }
+
+ LLRect tab_panel_rect;
+ if (mIsVertical)
+ {
+ tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD,
+ getRect().getHeight() - LLPANEL_BORDER_WIDTH,
+ getRect().getWidth() - LLPANEL_BORDER_WIDTH,
+ LLPANEL_BORDER_WIDTH);
+ }
+ else
+ {
+ tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH,
+ tab_panel_top,
+ getRect().getWidth()-LLPANEL_BORDER_WIDTH,
+ tab_panel_bottom );
+ }
+ child->setFollowsAll();
+ child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
+ child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
+ child->setBackgroundVisible( FALSE ); // No need to overdraw
+ // add this child later
+
+ child->setVisible( FALSE ); // Will be made visible when selected
+
+ mTotalTabWidth += button_width;
+
+ // Tab button
+ LLRect btn_rect; // Note: btn_rect.mLeft is just a dummy. Will be updated in draw().
+ LLString tab_img;
+ LLString tab_selected_img;
+ S32 tab_fudge = 1; // To make new tab art look better, nudge buttons up 1 pel
+
+ if (mIsVertical)
+ {
+ btn_rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
+ (getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * getTabCount()),
+ mMinTabWidth,
+ BTN_HEIGHT);
+ }
+ else if( getTabPosition() == LLTabContainer::TOP )
+ {
+ btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
+ tab_img = "tab_top_blue.tga";
+ tab_selected_img = "tab_top_selected_blue.tga";
+ }
+ else
+ {
+ btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
+ tab_img = "tab_bottom_blue.tga";
+ tab_selected_img = "tab_bottom_selected_blue.tga";
+ }
+
+ LLTextBox* textbox = NULL;
+ LLButton* btn = NULL;
+
+ if (placeholder)
+ {
+ btn_rect.translate(0, -LLBUTTON_V_PAD-2);
+ textbox = new LLTextBox(trimmed_label, btn_rect, trimmed_label, font);
+
+ btn = new LLButton("", LLRect(0,0,0,0));
+ }
+ else
+ {
+ if (mIsVertical)
+ {
+ btn = new LLButton("vert tab button",
+ btn_rect,
+ "",
+ "",
+ "",
+ &LLTabContainer::onTabBtn, NULL,
+ font,
+ trimmed_label, trimmed_label);
+ btn->setImages("tab_left.tga", "tab_left_selected.tga");
+ btn->setScaleImage(TRUE);
+ btn->setHAlign(LLFontGL::LEFT);
+ btn->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
+ btn->setTabStop(FALSE);
+ if (indent)
+ {
+ btn->setLeftHPad(indent);
+ }
+ }
+ else
+ {
+ LLString tooltip = trimmed_label;
+ tooltip += "\nAlt-Left arrow for previous tab";
+ tooltip += "\nAlt-Right arrow for next tab";
+
+ btn = new LLButton(LLString(child->getName()) + " tab",
+ btn_rect,
+ "", "", "",
+ &LLTabContainer::onTabBtn, NULL, // set userdata below
+ font,
+ trimmed_label, trimmed_label );
+ btn->setVisible( FALSE );
+ btn->setToolTip( tooltip );
+ btn->setScaleImage(TRUE);
+ btn->setImages(tab_img, tab_selected_img);
+
+ // Try to squeeze in a bit more text
+ btn->setLeftHPad( 4 );
+ btn->setRightHPad( 2 );
+ btn->setHAlign(LLFontGL::LEFT);
+ btn->setTabStop(FALSE);
+ if (indent)
+ {
+ btn->setLeftHPad(indent);
+ }
+
+ if( getTabPosition() == TOP )
+ {
+ btn->setFollowsTop();
+ }
+ else
+ {
+ btn->setFollowsBottom();
+ }
+ }
+ }
+
+ LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, textbox );
+ insertTuple( tuple, insertion_point );
+
+ if (textbox)
+ {
+ textbox->setSaveToXML(false);
+ addChild( textbox, 0 );
+ }
+ if (btn)
+ {
+ btn->setSaveToXML(false);
+ btn->setCallbackUserData( tuple );
+ addChild( btn, 0 );
+ }
+ if (child)
+ {
+ addChild(child, 1);
+ }
+
+ if( select )
+ {
+ selectLastTab();
+ }
+
+ updateMaxScrollPos();
+}
+
+void LLTabContainer::addPlaceholder(LLPanel* child, const LLString& label)
+{
+ addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
+}
+
+void LLTabContainer::removeTabPanel(LLPanel* child)
+{
+ if (mIsVertical)
+ {
+ // Fix-up button sizes
+ S32 tab_count = 0;
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ LLRect rect;
+ rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
+ (getRect().getHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * (tab_count)),
+ mMinTabWidth,
+ BTN_HEIGHT);
+ if (tuple->mPlaceholderText)
+ {
+ tuple->mPlaceholderText->setRect(rect);
+ }
+ else
+ {
+ tuple->mButton->setRect(rect);
+ }
+ tab_count++;
+ }
+ }
+ else
+ {
+ // Adjust the total tab width.
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ if( tuple->mTabPanel == child )
+ {
+ mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+ break;
+ }
+ }
+ }
+
BOOL has_focus = gFocusMgr.childHasKeyboardFocus(this);
// If the tab being deleted is the selected one, select a different tab.
@@ -207,7 +944,27 @@ void LLTabContainerCommon::removeTabPanel(LLPanel* child)
updateMaxScrollPos();
}
-void LLTabContainerCommon::deleteAllTabs()
+void LLTabContainer::lockTabs(S32 num_tabs)
+{
+ // count current tabs or use supplied value and ensure no new tabs get
+ // inserted between them
+ mLockedTabCount = num_tabs > 0 ? llmin(getTabCount(), num_tabs) : getTabCount();
+}
+
+void LLTabContainer::unlockTabs()
+{
+ mLockedTabCount = 0;
+}
+
+void LLTabContainer::enableTabButton(S32 which, BOOL enable)
+{
+ if (which >= 0 && which < (S32)mTabList.size())
+ {
+ mTabList[which]->mButton->setEnabled(enable);
+ }
+}
+
+void LLTabContainer::deleteAllTabs()
{
// Remove all the tab buttons and delete them. Also, unlink all the child panels.
for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
@@ -229,56 +986,26 @@ void LLTabContainerCommon::deleteAllTabs()
mCurrentTabIdx = -1;
}
-
-LLPanel* LLTabContainerCommon::getCurrentPanel()
+LLPanel* LLTabContainer::getCurrentPanel()
{
- if (mCurrentTabIdx < 0 || mCurrentTabIdx >= (S32) mTabList.size()) return NULL;
-
- return mTabList[mCurrentTabIdx]->mTabPanel;
-}
-
-LLTabContainerCommon::LLTabTuple* LLTabContainerCommon::getTabByPanel(LLPanel* child)
-{
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ if (mCurrentTabIdx >= 0 && mCurrentTabIdx < (S32) mTabList.size())
{
- LLTabTuple* tuple = *iter;
- if( tuple->mTabPanel == child )
- {
- return tuple;
- }
+ return mTabList[mCurrentTabIdx]->mTabPanel;
}
return NULL;
}
-void LLTabContainerCommon::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*, bool))
-{
- LLTabTuple* tuplep = getTabByPanel(tab);
- if (tuplep)
- {
- tuplep->mOnChangeCallback = on_tab_clicked;
- }
-}
-
-void LLTabContainerCommon::setTabUserData(LLPanel* tab, void* userdata)
-{
- LLTabTuple* tuplep = getTabByPanel(tab);
- if (tuplep)
- {
- tuplep->mUserData = userdata;
- }
-}
-
-S32 LLTabContainerCommon::getCurrentPanelIndex()
+S32 LLTabContainer::getCurrentPanelIndex()
{
return mCurrentTabIdx;
}
-S32 LLTabContainerCommon::getTabCount()
+S32 LLTabContainer::getTabCount()
{
return mTabList.size();
}
-LLPanel* LLTabContainerCommon::getPanelByIndex(S32 index)
+LLPanel* LLTabContainer::getPanelByIndex(S32 index)
{
if (index >= 0 && index < (S32)mTabList.size())
{
@@ -287,7 +1014,7 @@ LLPanel* LLTabContainerCommon::getPanelByIndex(S32 index)
return NULL;
}
-S32 LLTabContainerCommon::getIndexForPanel(LLPanel* panel)
+S32 LLTabContainer::getIndexForPanel(LLPanel* panel)
{
for (S32 index = 0; index < (S32)mTabList.size(); index++)
{
@@ -299,7 +1026,7 @@ S32 LLTabContainerCommon::getIndexForPanel(LLPanel* panel)
return -1;
}
-S32 LLTabContainerCommon::getPanelIndexByTitle(const LLString& title)
+S32 LLTabContainer::getPanelIndexByTitle(const LLString& title)
{
for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
{
@@ -311,7 +1038,7 @@ S32 LLTabContainerCommon::getPanelIndexByTitle(const LLString& title)
return -1;
}
-LLPanel *LLTabContainerCommon::getPanelByName(const LLString& name)
+LLPanel *LLTabContainer::getPanelByName(const LLString& name)
{
for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
{
@@ -324,34 +1051,71 @@ LLPanel *LLTabContainerCommon::getPanelByName(const LLString& name)
return NULL;
}
+// Change the name of the button for the current tab.
+void LLTabContainer::setCurrentTabName(const LLString& name)
+{
+ // Might not have a tab selected
+ if (mCurrentTabIdx < 0) return;
+
+ mTabList[mCurrentTabIdx]->mButton->setLabelSelected(name);
+ mTabList[mCurrentTabIdx]->mButton->setLabelUnselected(name);
+}
-void LLTabContainerCommon::scrollNext()
+void LLTabContainer::selectFirstTab()
{
- // No wrap
- if( mScrollPos < mMaxScrollPos )
- {
- mScrollPos++;
- }
+ selectTab( 0 );
}
-void LLTabContainerCommon::scrollPrev()
+
+void LLTabContainer::selectLastTab()
{
- // No wrap
- if( mScrollPos > 0 )
+ selectTab( mTabList.size()-1 );
+}
+
+void LLTabContainer::selectNextTab()
+{
+ BOOL tab_has_focus = FALSE;
+ if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
+ {
+ tab_has_focus = TRUE;
+ }
+ S32 idx = mCurrentTabIdx+1;
+ if (idx >= (S32)mTabList.size())
+ idx = 0;
+ while (!selectTab(idx) && idx != mCurrentTabIdx)
{
- mScrollPos--;
+ idx = (idx + 1 ) % (S32)mTabList.size();
+ }
+
+ if (tab_has_focus)
+ {
+ mTabList[idx]->mButton->setFocus(TRUE);
}
}
-void LLTabContainerCommon::enableTabButton(S32 which, BOOL enable)
+void LLTabContainer::selectPrevTab()
{
- if (which >= 0 && which < (S32)mTabList.size())
+ BOOL tab_has_focus = FALSE;
+ if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
{
- mTabList[which]->mButton->setEnabled(enable);
+ tab_has_focus = TRUE;
}
-}
+ S32 idx = mCurrentTabIdx-1;
+ if (idx < 0)
+ idx = mTabList.size()-1;
+ while (!selectTab(idx) && idx != mCurrentTabIdx)
+ {
+ idx = idx - 1;
+ if (idx < 0)
+ idx = mTabList.size()-1;
+ }
+ if (tab_has_focus)
+ {
+ mTabList[idx]->mButton->setFocus(TRUE);
+ }
+}
-BOOL LLTabContainerCommon::selectTabPanel(LLPanel* child)
+BOOL LLTabContainer::selectTabPanel(LLPanel* child)
{
S32 idx = 0;
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
@@ -366,12 +1130,108 @@ BOOL LLTabContainerCommon::selectTabPanel(LLPanel* child)
return FALSE;
}
-BOOL LLTabContainerCommon::selectTabByName(const LLString& name)
+BOOL LLTabContainer::selectTab(S32 which)
+{
+ if (which >= getTabCount()) return FALSE;
+ if (which < 0) return FALSE;
+
+ //if( gFocusMgr.childHasKeyboardFocus( this ) )
+ //{
+ // gFocusMgr.setKeyboardFocus( NULL );
+ //}
+
+ LLTabTuple* selected_tuple = getTab(which);
+ if (!selected_tuple)
+ {
+ return FALSE;
+ }
+
+ BOOL is_visible = FALSE;
+ if (getTab(which)->mButton->getEnabled())
+ {
+ setCurrentPanelIndex(which);
+
+ S32 i = 0;
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ 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 );
+
+ if( is_selected && (mIsVertical || (getMaxScrollPos() > 0)))
+ {
+ // Make sure selected tab is within scroll region
+ if (mIsVertical)
+ {
+ S32 num_visible = getTabCount() - getMaxScrollPos();
+ if( i >= getScrollPos() && i <= getScrollPos() + num_visible)
+ {
+ setCurrentPanelIndex(which);
+ is_visible = TRUE;
+ }
+ else
+ {
+ is_visible = FALSE;
+ }
+ }
+ else
+ {
+ if( i < getScrollPos() )
+ {
+ setScrollPos(i);
+ }
+ 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 j = i - 1;
+ S32 min_scroll_pos = i;
+ if (running_tab_width < available_width_with_arrows)
+ {
+ while (j >= 0)
+ {
+ LLTabTuple* other_tuple = getTab(j);
+ running_tab_width += other_tuple->mButton->getRect().getWidth();
+ if (running_tab_width > available_width_with_arrows)
+ {
+ break;
+ }
+ j--;
+ }
+ min_scroll_pos = j + 1;
+ }
+ setScrollPos(llclamp(getScrollPos(), min_scroll_pos, i));
+ setScrollPos(llmin(getScrollPos(), getMaxScrollPos()));
+ }
+ is_visible = TRUE;
+ }
+ }
+ i++;
+ }
+ if( selected_tuple->mOnChangeCallback )
+ {
+ selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false );
+ }
+ }
+ if (mIsVertical && getCurrentPanelIndex() >= 0)
+ {
+ LLTabTuple* tuple = getTab(getCurrentPanelIndex());
+ tuple->mTabPanel->setVisible( TRUE );
+ tuple->mButton->setToggleState( TRUE );
+ }
+ return is_visible;
+}
+
+BOOL LLTabContainer::selectTabByName(const LLString& name)
{
LLPanel* panel = getPanelByName(name);
if (!panel)
{
- llwarns << "LLTabContainerCommon::selectTabByName("
+ llwarns << "LLTabContainer::selectTabByName("
<< name << ") failed" << llendl;
return FALSE;
}
@@ -380,74 +1240,131 @@ BOOL LLTabContainerCommon::selectTabByName(const LLString& name)
return result;
}
-
-void LLTabContainerCommon::selectFirstTab()
+BOOL LLTabContainer::getTabPanelFlashing(LLPanel *child)
{
- selectTab( 0 );
+ LLTabTuple* tuple = getTabByPanel(child);
+ if( tuple )
+ {
+ return tuple->mButton->getFlashing();
+ }
+ return FALSE;
}
-
-void LLTabContainerCommon::selectLastTab()
+void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state )
{
- selectTab( mTabList.size()-1 );
+ LLTabTuple* tuple = getTabByPanel(child);
+ if( tuple )
+ {
+ tuple->mButton->setFlashing( state );
+ }
}
-
-void LLTabContainerCommon::selectNextTab()
+void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
- BOOL tab_has_focus = FALSE;
- if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
- {
- tab_has_focus = TRUE;
- }
- S32 idx = mCurrentTabIdx+1;
- if (idx >= (S32)mTabList.size())
- idx = 0;
- while (!selectTab(idx) && idx != mCurrentTabIdx)
+ LLTabTuple* tuple = getTabByPanel(child);
+ if( tuple )
{
- idx = (idx + 1 ) % (S32)mTabList.size();
+ tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
+
+ if (!mIsVertical)
+ {
+ const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
+ // remove current width from total tab strip width
+ mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+
+ S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
+ tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
+ 0;
+
+ tuple->mPadding = image_overlay_width;
+
+ 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();
+
+ // tabs have changed size, might need to scroll to see current tab
+ updateMaxScrollPos();
+ }
}
+}
- if (tab_has_focus)
+void LLTabContainer::setTitle(const LLString& title)
+{
+ if (mTitleBox)
{
- mTabList[idx]->mButton->setFocus(TRUE);
+ mTitleBox->setText( title );
}
}
-void LLTabContainerCommon::selectPrevTab()
+const LLString LLTabContainer::getPanelTitle(S32 index)
{
- BOOL tab_has_focus = FALSE;
- if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
+ if (index >= 0 && index < (S32)mTabList.size())
{
- tab_has_focus = TRUE;
+ LLButton* tab_button = mTabList[index]->mButton;
+ return tab_button->getLabelSelected();
}
- S32 idx = mCurrentTabIdx-1;
- if (idx < 0)
- idx = mTabList.size()-1;
- while (!selectTab(idx) && idx != mCurrentTabIdx)
+ return LLString::null;
+}
+
+void LLTabContainer::setTopBorderHeight(S32 height)
+{
+ mTopBorderHeight = height;
+}
+
+S32 LLTabContainer::getTopBorderHeight() const
+{
+ return mTopBorderHeight;
+}
+
+void LLTabContainer::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*, bool))
+{
+ LLTabTuple* tuplep = getTabByPanel(tab);
+ if (tuplep)
{
- idx = idx - 1;
- if (idx < 0)
- idx = mTabList.size()-1;
+ tuplep->mOnChangeCallback = on_tab_clicked;
}
- if (tab_has_focus)
+}
+
+void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata)
+{
+ LLTabTuple* tuplep = getTabByPanel(tab);
+ if (tuplep)
{
- mTabList[idx]->mButton->setFocus(TRUE);
+ tuplep->mUserData = userdata;
}
-}
+}
+void LLTabContainer::setRightTabBtnOffset(S32 offset)
+{
+ mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 );
+ mRightTabBtnOffset = offset;
+ updateMaxScrollPos();
+}
-void LLTabContainerCommon::reshape(S32 width, S32 height, BOOL called_from_parent)
+void LLTabContainer::setPanelTitle(S32 index, const LLString& title)
{
- LLPanel::reshape( width, height, called_from_parent );
+ if (index >= 0 && index < getTabCount())
+ {
+ LLTabTuple* tuple = getTab(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 + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
+ mTotalTabWidth += tab_button->getRect().getWidth();
+ tab_button->setLabelSelected(title);
+ tab_button->setLabelUnselected(title);
+ }
updateMaxScrollPos();
}
+
// static
-void LLTabContainerCommon::onTabBtn( void* userdata )
+void LLTabContainer::onTabBtn( void* userdata )
{
LLTabTuple* tuple = (LLTabTuple*) userdata;
- LLTabContainerCommon* self = tuple->mTabContainer;
+ LLTabContainer* self = tuple->mTabContainer;
self->selectTabPanel( tuple->mTabPanel );
if( tuple->mOnChangeCallback )
@@ -459,7 +1376,7 @@ void LLTabContainerCommon::onTabBtn( void* userdata )
}
// static
-void LLTabContainerCommon::onCloseBtn( void* userdata )
+void LLTabContainer::onCloseBtn( void* userdata )
{
LLTabContainer* self = (LLTabContainer*) userdata;
if( self->mCloseCallback )
@@ -469,7 +1386,7 @@ void LLTabContainerCommon::onCloseBtn( void* userdata )
}
// static
-void LLTabContainerCommon::onNextBtn( void* userdata )
+void LLTabContainer::onNextBtn( void* userdata )
{
// Scroll tabs to the left
LLTabContainer* self = (LLTabContainer*) userdata;
@@ -481,7 +1398,7 @@ void LLTabContainerCommon::onNextBtn( void* userdata )
}
// static
-void LLTabContainerCommon::onNextBtnHeld( void* userdata )
+void LLTabContainer::onNextBtnHeld( void* userdata )
{
LLTabContainer* self = (LLTabContainer*) userdata;
if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
@@ -493,7 +1410,7 @@ void LLTabContainerCommon::onNextBtnHeld( void* userdata )
}
// static
-void LLTabContainerCommon::onPrevBtn( void* userdata )
+void LLTabContainer::onPrevBtn( void* userdata )
{
LLTabContainer* self = (LLTabContainer*) userdata;
if (!self->mScrolled)
@@ -503,26 +1420,22 @@ void LLTabContainerCommon::onPrevBtn( void* userdata )
self->mScrolled = FALSE;
}
-
-void LLTabContainerCommon::onJumpFirstBtn( void* userdata )
+// static
+void LLTabContainer::onJumpFirstBtn( void* userdata )
{
LLTabContainer* self = (LLTabContainer*) userdata;
-
self->mScrollPos = 0;
-
}
-
-void LLTabContainerCommon::onJumpLastBtn( void* userdata )
+// static
+void LLTabContainer::onJumpLastBtn( void* userdata )
{
LLTabContainer* self = (LLTabContainer*) userdata;
-
self->mScrollPos = self->mMaxScrollPos;
}
-
// static
-void LLTabContainerCommon::onPrevBtnHeld( void* userdata )
+void LLTabContainer::onPrevBtnHeld( void* userdata )
{
LLTabContainer* self = (LLTabContainer*) userdata;
if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
@@ -533,68 +1446,8 @@ void LLTabContainerCommon::onPrevBtnHeld( void* userdata )
}
}
-BOOL LLTabContainerCommon::getTabPanelFlashing(LLPanel *child)
-{
- LLTabTuple* tuple = getTabByPanel(child);
- if( tuple )
- {
- return tuple->mButton->getFlashing();
- }
- return FALSE;
-}
-
-void LLTabContainerCommon::setTabPanelFlashing(LLPanel* child, BOOL state )
-{
- LLTabTuple* tuple = getTabByPanel(child);
- if( tuple )
- {
- tuple->mButton->setFlashing( state );
- }
-}
-
-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, color);
- }
-}
-
-void LLTabContainerCommon::setTitle(const LLString& title)
-{
- if (mTitleBox)
- {
- mTitleBox->setText( title );
- }
-}
-
-const LLString LLTabContainerCommon::getPanelTitle(S32 index)
-{
- if (index >= 0 && index < (S32)mTabList.size())
- {
- LLButton* tab_button = mTabList[index]->mButton;
- return tab_button->getLabelSelected();
- }
- return LLString::null;
-}
-
-void LLTabContainerCommon::setTopBorderHeight(S32 height)
-{
- mTopBorderHeight = height;
-}
-
-// Change the name of the button for the current tab.
-void LLTabContainerCommon::setCurrentTabName(const LLString& name)
-{
- // Might not have a tab selected
- if (mCurrentTabIdx < 0) return;
-
- mTabList[mCurrentTabIdx]->mButton->setLabelSelected(name);
- mTabList[mCurrentTabIdx]->mButton->setLabelUnselected(name);
-}
-
-LLView* LLTabContainerCommon::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+// static
+LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
LLString name("tab_container");
node->getAttributeString("name", name);
@@ -626,58 +1479,30 @@ LLView* LLTabContainerCommon::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtr
BOOL border = FALSE;
node->getAttributeBOOL("border", border);
- // Create the correct container type.
- LLTabContainerCommon* tab_container = NULL;
-
- if (is_vertical)
+ LLTabContainer* tab_container = new LLTabContainer(name, LLRect::null, tab_position, border, is_vertical);
+
+ S32 tab_min_width = tab_container->mMinTabWidth;
+ if (node->hasAttribute("tab_width"))
{
- // Vertical tabs can specify tab width
- U32 tab_width = TABCNTRV_TAB_WIDTH;
- if (node->hasAttribute("tab_width"))
- {
- node->getAttributeU32("tab_width", tab_width);
- }
-
- tab_container = new LLTabContainerVertical(name,
- LLRect::null,
- NULL,
- NULL,
- tab_width,
- border);
-
+ node->getAttributeS32("tab_width", tab_min_width);
}
- else // horizontal tab container
+ else if( node->hasAttribute("tab_min_width"))
{
- // Horizontal tabs can have a title (?)
- LLString title(LLString::null);
- if (node->hasAttribute("title"))
- {
- node->getAttributeString("title", title);
- }
+ node->getAttributeS32("tab_min_width", tab_min_width);
+ }
- tab_container = new LLTabContainer(name,
- LLRect::null,
- tab_position,
- NULL,
- NULL,
- title,
- border);
-
- if(node->hasAttribute("tab_min_width"))
- {
- S32 minTabWidth=0;
- node->getAttributeS32("tab_min_width",minTabWidth);
- ((LLTabContainer*)tab_container)->setMinTabWidth(minTabWidth);
- }
- if(node->hasAttribute("tab_max_width"))
- {
- S32 maxTabWidth=0;
- node->getAttributeS32("tab_max_width",maxTabWidth);
- ((LLTabContainer*)tab_container)->setMaxTabWidth(maxTabWidth);
- }
+ S32 tab_max_width = tab_container->mMaxTabWidth;
+ if (node->hasAttribute("tab_max_width"))
+ {
+ node->getAttributeS32("tab_max_width", tab_max_width);
}
+
+ tab_container->setMinTabWidth(tab_min_width);
+ tab_container->setMaxTabWidth(tab_max_width);
- node->getAttributeBOOL("hide_tabs", tab_container->mTabsHidden);
+ BOOL hidden(tab_container->getTabsHidden());
+ node->getAttributeBOOL("hide_tabs", hidden);
+ tab_container->setTabsHidden(hidden);
tab_container->setPanelParameters(node, parent);
@@ -718,76 +1543,12 @@ LLView* LLTabContainerCommon::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtr
return tab_container;
}
-void LLTabContainerCommon::insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point)
-{
- switch(insertion_point)
- {
- case START:
- // insert the new tab in the front of the list
- mTabList.insert(mTabList.begin() + mLockedTabCount, tuple);
- break;
- case LEFT_OF_CURRENT:
- // insert the new tab before the current tab (but not before mLockedTabCount)
- {
- tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx);
- mTabList.insert(current_iter, tuple);
- }
- break;
-
- case RIGHT_OF_CURRENT:
- // insert the new tab after the current tab (but not before mLockedTabCount)
- {
- tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx + 1);
- mTabList.insert(current_iter, tuple);
- }
- break;
- case END:
- default:
- mTabList.push_back( tuple );
- }
-}
-
-
-LLTabContainer::LLTabContainer(
- const LLString& name, const LLRect& rect, TabPosition pos,
- void(*close_callback)(void*), void* callback_userdata,
- const LLString& title, BOOL bordered )
- :
- LLTabContainerCommon(name, rect, pos, close_callback, callback_userdata, bordered),
- mLeftArrowBtn(NULL),
- mJumpLeftArrowBtn(NULL),
- mRightArrowBtn(NULL),
- mJumpRightArrowBtn(NULL),
- mRightTabBtnOffset(0),
- mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
- mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
- mTotalTabWidth(0)
-{
- initButtons( );
-}
-
-LLTabContainer::LLTabContainer(
- const LLString& name, const LLString& rect_control, TabPosition pos,
- void(*close_callback)(void*), void* callback_userdata,
- const LLString& title, BOOL bordered )
- :
- LLTabContainerCommon(name, rect_control, pos, close_callback, callback_userdata, bordered),
- mLeftArrowBtn(NULL),
- mJumpLeftArrowBtn(NULL),
- mRightArrowBtn(NULL),
- mJumpRightArrowBtn(NULL),
- mRightTabBtnOffset(0),
- mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
- mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
- mTotalTabWidth(0)
-{
- initButtons( );
-}
+// private
void LLTabContainer::initButtons()
{
// Hack:
- if (mRect.getHeight() == 0 || mLeftArrowBtn)
+ if (getRect().getHeight() == 0 || mPrevArrowBtn)
{
return; // Don't have a rect yet or already got called
}
@@ -795,881 +1556,255 @@ void LLTabContainer::initButtons()
LLString out_id;
LLString in_id;
- S32 arrow_fudge = 1; // match new art better
-
- // tabs on bottom reserve room for resize handle (just in case)
- if (mTabPosition == BOTTOM)
+ if (mIsVertical)
{
- mRightTabBtnOffset = RESIZE_HANDLE_WIDTH;
- }
-
- // Left and right scroll arrows (for when there are too many tabs to show all at once).
- S32 btn_top = (mTabPosition == TOP ) ? mRect.getHeight() - mTopBorderHeight : 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 );
-
- 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 );
-
- S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1;
-
- LLRect right_arrow_btn_rect;
- right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad - TABCNTR_ARROW_BTN_SIZE,
- btn_top + arrow_fudge,
- TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
+ // Left and right scroll arrows (for when there are too many tabs to show all at once).
+ S32 btn_top = getRect().getHeight();
+ S32 btn_top_lower = getRect().mBottom+TABCNTRV_ARROW_BTN_SIZE;
+ LLRect up_arrow_btn_rect;
+ up_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE );
- LLRect jump_right_arrow_btn_rect;
- jump_right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad,
- btn_top + arrow_fudge,
- TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
+ LLRect down_arrow_btn_rect;
+ down_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top_lower, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE );
- out_id = "UIImgBtnJumpLeftOutUUID";
- in_id = "UIImgBtnJumpLeftInUUID";
- mJumpLeftArrowBtn = new LLButton(
- "Jump Left Arrow", jump_left_arrow_btn_rect,
- out_id, in_id, "",
- &LLTabContainer::onJumpFirstBtn, this, LLFontGL::sSansSerif );
- mJumpLeftArrowBtn->setFollowsLeft();
- mJumpLeftArrowBtn->setSaveToXML(false);
- mJumpLeftArrowBtn->setTabStop(FALSE);
- addChild(mJumpLeftArrowBtn);
+ out_id = "UIImgBtnScrollUpOutUUID";
+ in_id = "UIImgBtnScrollUpInUUID";
+ mPrevArrowBtn = new LLButton("Up Arrow", up_arrow_btn_rect,
+ out_id, in_id, "",
+ &onPrevBtn, this, NULL );
+ mPrevArrowBtn->setFollowsTop();
+ mPrevArrowBtn->setFollowsLeft();
- out_id = "UIImgBtnScrollLeftOutUUID";
- in_id = "UIImgBtnScrollLeftInUUID";
- mLeftArrowBtn = new LLButton(
- "Left Arrow", left_arrow_btn_rect,
- out_id, in_id, "",
- &LLTabContainer::onPrevBtn, this, LLFontGL::sSansSerif );
- mLeftArrowBtn->setHeldDownCallback(onPrevBtnHeld);
- mLeftArrowBtn->setFollowsLeft();
- mLeftArrowBtn->setSaveToXML(false);
- mLeftArrowBtn->setTabStop(FALSE);
- addChild(mLeftArrowBtn);
-
- out_id = "UIImgBtnJumpRightOutUUID";
- in_id = "UIImgBtnJumpRightInUUID";
- mJumpRightArrowBtn = new LLButton(
- "Jump Right Arrow", jump_right_arrow_btn_rect,
- out_id, in_id, "",
- &LLTabContainer::onJumpLastBtn, this,
- LLFontGL::sSansSerif);
- mJumpRightArrowBtn->setFollowsRight();
- mJumpRightArrowBtn->setSaveToXML(false);
- mJumpRightArrowBtn->setTabStop(FALSE);
- addChild(mJumpRightArrowBtn);
-
- out_id = "UIImgBtnScrollRightOutUUID";
- in_id = "UIImgBtnScrollRightInUUID";
- mRightArrowBtn = new LLButton(
- "Right Arrow", right_arrow_btn_rect,
- out_id, in_id, "",
- &LLTabContainer::onNextBtn, this,
- LLFontGL::sSansSerif);
- mRightArrowBtn->setFollowsRight();
- mRightArrowBtn->setHeldDownCallback(onNextBtnHeld);
- mRightArrowBtn->setSaveToXML(false);
- mRightArrowBtn->setTabStop(FALSE);
- addChild(mRightArrowBtn);
-
-
- if( mTabPosition == TOP )
- {
- mRightArrowBtn->setFollowsTop();
- mLeftArrowBtn->setFollowsTop();
- mJumpLeftArrowBtn->setFollowsTop();
- mJumpRightArrowBtn->setFollowsTop();
+ out_id = "UIImgBtnScrollDownOutUUID";
+ in_id = "UIImgBtnScrollDownInUUID";
+ mNextArrowBtn = new LLButton("Down Arrow", down_arrow_btn_rect,
+ out_id, in_id, "",
+ &onNextBtn, this, NULL );
+ mNextArrowBtn->setFollowsBottom();
+ mNextArrowBtn->setFollowsLeft();
}
- else
+ else // Horizontal
{
- mRightArrowBtn->setFollowsBottom();
- mLeftArrowBtn->setFollowsBottom();
- mJumpLeftArrowBtn->setFollowsBottom();
- mJumpRightArrowBtn->setFollowsBottom();
- }
-
- // set default tab group to be panel contents
- mDefaultTabGroup = 1;
-}
+ S32 arrow_fudge = 1; // match new art better
-LLTabContainer::~LLTabContainer()
-{
-}
-
-void LLTabContainer::addTabPanel(LLPanel* child,
- const LLString& label,
- BOOL select,
- void (*on_tab_clicked)(void*, bool),
- void* userdata,
- S32 indent,
- BOOL placeholder,
- eInsertionPoint insertion_point)
-{
- if (child->getParent() == this)
- {
- // already a child of mine
- return;
- }
- const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
+ // tabs on bottom reserve room for resize handle (just in case)
+ if (getTabPosition() == BOTTOM)
+ {
+ mRightTabBtnOffset = RESIZE_HANDLE_WIDTH;
+ }
- // Store the original label for possible xml export.
- child->setLabel(label);
- LLString trimmed_label = label;
- LLString::trim(trimmed_label);
+ // Left and right scroll arrows (for when there are too many tabs to show all at once).
+ S32 btn_top = (getTabPosition() == TOP ) ? getRect().getHeight() - getTopBorderHeight() : TABCNTR_ARROW_BTN_SIZE + 1;
- S32 button_width = llclamp(font->getWidth(trimmed_label) + TAB_PADDING, mMinTabWidth, mMaxTabWidth);
+ 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 );
- // Tab panel
- S32 tab_panel_top;
- S32 tab_panel_bottom;
- if( LLTabContainer::TOP == mTabPosition )
- {
- tab_panel_top = mRect.getHeight() - mTopBorderHeight - (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP);
- tab_panel_bottom = LLPANEL_BORDER_WIDTH;
- }
- else
- {
- tab_panel_top = mRect.getHeight() - mTopBorderHeight;
- tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border
- }
-
- LLRect tab_panel_rect(
- LLPANEL_BORDER_WIDTH,
- tab_panel_top,
- mRect.getWidth()-LLPANEL_BORDER_WIDTH,
- tab_panel_bottom );
+ 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 );
- child->setFollowsAll();
- child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
- child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
- child->setBackgroundVisible( FALSE ); // No need to overdraw
- // add this child later
+ S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1;
- child->setVisible( FALSE ); // Will be made visible when selected
+ 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 );
- mTotalTabWidth += button_width;
- // Tab button
- LLRect btn_rect; // Note: btn_rect.mLeft is just a dummy. Will be updated in draw().
- LLString tab_img;
- LLString tab_selected_img;
- S32 tab_fudge = 1; // To make new tab art look better, nudge buttons up 1 pel
+ 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 );
- if( LLTabContainer::TOP == mTabPosition )
- {
- btn_rect.setLeftTopAndSize( 0, mRect.getHeight() - mTopBorderHeight + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
- tab_img = "tab_top_blue.tga";
- tab_selected_img = "tab_top_selected_blue.tga";
- }
- else
- {
- btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
- tab_img = "tab_bottom_blue.tga";
- tab_selected_img = "tab_bottom_selected_blue.tga";
- }
+ out_id = "UIImgBtnJumpLeftOutUUID";
+ in_id = "UIImgBtnJumpLeftInUUID";
+ mJumpPrevArrowBtn = new LLButton("Jump Left Arrow", jump_left_arrow_btn_rect,
+ out_id, in_id, "",
+ &LLTabContainer::onJumpFirstBtn, this, LLFontGL::sSansSerif );
+ mJumpPrevArrowBtn->setFollowsLeft();
- if (placeholder)
- {
- // *FIX: wont work for horizontal tabs
- btn_rect.translate(0, -LLBUTTON_V_PAD-2);
- LLString box_label = trimmed_label;
- LLTextBox* text = new LLTextBox(box_label, btn_rect, box_label, font);
- addChild( text, 0 );
-
- LLButton* btn = new LLButton("", LLRect(0,0,0,0));
- LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, text );
- addChild( btn, 0 );
- addChild( child, 1 );
- insertTuple(tuple, insertion_point);
- }
- else
- {
- LLString tooltip = trimmed_label;
- tooltip += "\nAlt-Left arrow for previous tab";
- tooltip += "\nAlt-Right arrow for next tab";
-
- LLButton* btn = new LLButton(
- LLString(child->getName()) + " tab",
- btn_rect,
- "", "", "",
- &LLTabContainer::onTabBtn, NULL, // set userdata below
- font,
- trimmed_label, trimmed_label );
- btn->setSaveToXML(false);
- btn->setVisible( FALSE );
- btn->setToolTip( tooltip );
- btn->setScaleImage(TRUE);
- btn->setImages(tab_img, tab_selected_img);
-
- // Try to squeeze in a bit more text
- btn->setLeftHPad( 4 );
- btn->setRightHPad( 2 );
- btn->setHAlign(LLFontGL::LEFT);
- btn->setTabStop(FALSE);
- if (indent)
- {
- btn->setLeftHPad(indent);
- }
-
- if( mTabPosition == TOP )
+ out_id = "UIImgBtnScrollLeftOutUUID";
+ in_id = "UIImgBtnScrollLeftInUUID";
+ mPrevArrowBtn = new LLButton("Left Arrow", left_arrow_btn_rect,
+ out_id, in_id, "",
+ &LLTabContainer::onPrevBtn, this, LLFontGL::sSansSerif );
+ mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld);
+ mPrevArrowBtn->setFollowsLeft();
+
+ out_id = "UIImgBtnJumpRightOutUUID";
+ in_id = "UIImgBtnJumpRightInUUID";
+ mJumpNextArrowBtn = new LLButton("Jump Right Arrow", jump_right_arrow_btn_rect,
+ out_id, in_id, "",
+ &LLTabContainer::onJumpLastBtn, this,
+ LLFontGL::sSansSerif);
+ mJumpNextArrowBtn->setFollowsRight();
+
+ out_id = "UIImgBtnScrollRightOutUUID";
+ in_id = "UIImgBtnScrollRightInUUID";
+ mNextArrowBtn = new LLButton("Right Arrow", right_arrow_btn_rect,
+ out_id, in_id, "",
+ &LLTabContainer::onNextBtn, this,
+ LLFontGL::sSansSerif);
+ mNextArrowBtn->setFollowsRight();
+
+ if( getTabPosition() == TOP )
{
- btn->setFollowsTop();
+ mNextArrowBtn->setFollowsTop();
+ mPrevArrowBtn->setFollowsTop();
+ mJumpPrevArrowBtn->setFollowsTop();
+ mJumpNextArrowBtn->setFollowsTop();
}
else
{
- btn->setFollowsBottom();
+ mNextArrowBtn->setFollowsBottom();
+ mPrevArrowBtn->setFollowsBottom();
+ mJumpPrevArrowBtn->setFollowsBottom();
+ mJumpNextArrowBtn->setFollowsBottom();
}
-
- LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata );
- btn->setCallbackUserData( tuple );
- addChild( btn, 0 );
- addChild( child, 1 );
- insertTuple(tuple, insertion_point);
}
- updateMaxScrollPos();
+ mPrevArrowBtn->setHeldDownCallback(onPrevBtnHeld);
+ mPrevArrowBtn->setSaveToXML(false);
+ mPrevArrowBtn->setTabStop(FALSE);
+ addChild(mPrevArrowBtn);
- if( select )
+ mNextArrowBtn->setHeldDownCallback(onNextBtnHeld);
+ mNextArrowBtn->setSaveToXML(false);
+ mNextArrowBtn->setTabStop(FALSE);
+ addChild(mNextArrowBtn);
+
+ if (mJumpPrevArrowBtn)
{
- selectLastTab();
+ mJumpPrevArrowBtn->setSaveToXML(false);
+ mJumpPrevArrowBtn->setTabStop(FALSE);
+ addChild(mJumpPrevArrowBtn);
}
+
+ if (mJumpNextArrowBtn)
+ {
+ mJumpNextArrowBtn->setSaveToXML(false);
+ mJumpNextArrowBtn->setTabStop(FALSE);
+ addChild(mJumpNextArrowBtn);
+ }
+
+ // set default tab group to be panel contents
+ setDefaultTabGroup(1);
}
-void LLTabContainer::removeTabPanel(LLPanel* child)
+LLTabContainer::LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child)
{
- // Adjust the total tab width.
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
if( tuple->mTabPanel == child )
{
- mTotalTabWidth -= tuple->mButton->getRect().getWidth();
- break;
+ return tuple;
}
}
-
- LLTabContainerCommon::removeTabPanel(child);
-}
-
-void LLTabContainer::setPanelTitle(S32 index, const LLString& title)
-{
- if (index >= 0 && index < (S32)mTabList.size())
- {
- 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 + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
- mTotalTabWidth += tab_button->getRect().getWidth();
- tab_button->setLabelSelected(title);
- tab_button->setLabelUnselected(title);
- }
- updateMaxScrollPos();
+ return NULL;
}
-
-void LLTabContainer::updateMaxScrollPos()
+void LLTabContainer::insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point)
{
- S32 tab_space = 0;
- S32 available_space = 0;
- tab_space = mTotalTabWidth;
- available_space = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_TAB_H_PAD);
-
- if( tab_space > available_space )
+ switch(insertion_point)
{
- S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
- // subtract off reserved portion on left
- available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH;
-
- S32 running_tab_width = 0;
- mMaxScrollPos = mTabList.size();
- for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it)
+ case START:
+ // insert the new tab in the front of the list
+ mTabList.insert(mTabList.begin() + mLockedTabCount, tuple);
+ break;
+ case LEFT_OF_CURRENT:
+ // insert the new tab before the current tab (but not before mLockedTabCount)
{
- running_tab_width += (*tab_it)->mButton->getRect().getWidth();
- if (running_tab_width > available_width_with_arrows)
- {
- break;
- }
- mMaxScrollPos--;
+ tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx);
+ mTabList.insert(current_iter, tuple);
}
- // in case last tab doesn't actually fit on screen, make it the last scrolling position
- mMaxScrollPos = llmin(mMaxScrollPos, (S32)mTabList.size() - 1);
- }
- else
- {
- mMaxScrollPos = 0;
- mScrollPos = 0;
- }
- if (mScrollPos > mMaxScrollPos)
- {
- mScrollPos = mMaxScrollPos;
- }
-}
+ break;
-void LLTabContainer::commitHoveredButton(S32 x, S32 y)
-{
- if (hasMouseCapture())
- {
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ case RIGHT_OF_CURRENT:
+ // insert the new tab after the current tab (but not before mLockedTabCount)
{
- 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();
- }
+ tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx + 1);
+ mTabList.insert(current_iter, tuple);
}
+ break;
+ case END:
+ default:
+ mTabList.push_back( tuple );
}
}
-void LLTabContainer::setMinTabWidth(S32 width)
-{
- mMinTabWidth = width;
-}
-
-void LLTabContainer::setMaxTabWidth(S32 width)
-{
- mMaxTabWidth = width;
-}
-
-S32 LLTabContainer::getMinTabWidth() const
-{
- return mMinTabWidth;
-}
-S32 LLTabContainer::getMaxTabWidth() const
-{
- return mMaxTabWidth;
-}
-BOOL LLTabContainer::selectTab(S32 which)
+void LLTabContainer::updateMaxScrollPos()
{
- if (which >= (S32)mTabList.size()) return FALSE;
- if (which < 0) return FALSE;
-
- //if( gFocusMgr.childHasKeyboardFocus( this ) )
- //{
- // gFocusMgr.setKeyboardFocus( NULL );
- //}
-
- LLTabTuple* selected_tuple = mTabList[which];
- if (!selected_tuple)
- {
- return FALSE;
- }
-
- if (mTabList[which]->mButton->getEnabled())
+ BOOL no_scroll = TRUE;
+ if (mIsVertical)
{
- mCurrentTabIdx = which;
-
- S32 i = 0;
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount();
+ S32 available_height = getRect().getHeight() - getTopBorderHeight();
+ if( tab_total_height > available_height )
{
- 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 );
-
- if( is_selected && mMaxScrollPos > 0)
- {
- // Make sure selected tab is within scroll region
- if( i < mScrollPos )
- {
- mScrollPos = i;
- }
- else
- {
- S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
- S32 running_tab_width = tuple->mButton->getRect().getWidth();
- S32 j = i - 1;
- S32 min_scroll_pos = i;
- if (running_tab_width < available_width_with_arrows)
- {
- while (j >= 0)
- {
- LLTabTuple* other_tuple = mTabList[j];
- running_tab_width += other_tuple->mButton->getRect().getWidth();
- if (running_tab_width > available_width_with_arrows)
- {
- break;
- }
- j--;
- }
- min_scroll_pos = j + 1;
- }
- mScrollPos = llclamp(mScrollPos, min_scroll_pos, i);
- mScrollPos = llmin(mScrollPos, mMaxScrollPos);
- }
- }
- i++;
- }
- if( selected_tuple->mOnChangeCallback )
- {
- selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false );
+ S32 available_height_with_arrows = getRect().getHeight() - 2*(TABCNTRV_ARROW_BTN_SIZE + 3*TABCNTRV_PAD);
+ S32 additional_needed = tab_total_height - available_height_with_arrows;
+ setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) );
+ no_scroll = FALSE;
}
- return TRUE;
}
else
{
- return FALSE;
- }
-}
+ S32 tab_space = 0;
+ S32 available_space = 0;
+ tab_space = mTotalTabWidth;
+ available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_TAB_H_PAD);
-void LLTabContainer::draw()
-{
- S32 target_pixel_scroll = 0;
- S32 cur_scroll_pos = mScrollPos;
- if (cur_scroll_pos > 0)
- {
- S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ if( tab_space > available_space )
{
- if (cur_scroll_pos == 0)
- {
- break;
- }
- target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
- cur_scroll_pos--;
- }
+ S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
+ // subtract off reserved portion on left
+ available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH;
- // Show part of the tab to the left of what is fully visible
- target_pixel_scroll -= TABCNTR_TAB_PARTIAL_WIDTH;
- // clamp so that rightmost tab never leaves right side of screen
- target_pixel_scroll = llmin(mTotalTabWidth - available_width_with_arrows, target_pixel_scroll);
- }
-
- mScrollPosPixels = (S32)lerp((F32)mScrollPosPixels, (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f));
- if( getVisible() )
- {
- BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
- mJumpLeftArrowBtn->setVisible( has_scroll_arrows );
- mJumpRightArrowBtn->setVisible( has_scroll_arrows );
- mLeftArrowBtn->setVisible( has_scroll_arrows );
- mRightArrowBtn->setVisible( has_scroll_arrows );
-
- // Set the leftmost position of the tab buttons.
- S32 left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD);
- left -= mScrollPosPixels;
-
- // Hide all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
- }
-
- LLPanel::draw();
-
- // if tabs are hidden, don't draw them and leave them in the invisible state
- if (!mTabsHidden)
- {
- // Show all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( TRUE );
- }
-
- // Draw some of the buttons...
- LLRect clip_rect = getLocalRect();
- if (has_scroll_arrows)
+ S32 running_tab_width = 0;
+ setMaxScrollPos(getTabCount());
+ for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it)
{
- // ...but clip them.
- clip_rect.mLeft = mLeftArrowBtn->getRect().mRight;
- clip_rect.mRight = mRightArrowBtn->getRect().mLeft;
- }
- 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;
-
- tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 );
- left += tuple->mButton->getRect().getWidth();
-
- if( idx < mScrollPos )
- {
- if( tuple->mButton->getFlashing() )
- {
- mLeftArrowBtn->setFlashing( TRUE );
- }
- }
- else
- if( max_scroll_visible < idx )
+ running_tab_width += (*tab_it)->mButton->getRect().getWidth();
+ if (running_tab_width > available_width_with_arrows)
{
- 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();
+ break;
}
- LLUI::popMatrix();
-
- idx++;
+ setMaxScrollPos(getMaxScrollPos()-1);
}
+ // in case last tab doesn't actually fit on screen, make it the last scrolling position
+ setMaxScrollPos(llmin(getMaxScrollPos(), getTabCount() - 1));
+ no_scroll = FALSE;
}
-
- mLeftArrowBtn->setFlashing(FALSE);
- mRightArrowBtn->setFlashing(FALSE);
}
-}
-
-
-void LLTabContainer::setRightTabBtnOffset(S32 offset)
-{
- mRightArrowBtn->translate( -offset - mRightTabBtnOffset, 0 );
- mRightTabBtnOffset = offset;
- updateMaxScrollPos();
-}
-
-BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
- BOOL has_scroll_arrows = (mMaxScrollPos > 0);
-
- if (has_scroll_arrows)
- {
- if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
- handled = mJumpLeftArrowBtn->handleMouseDown(local_x, local_y, mask);
- }
- if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
- handled = mJumpRightArrowBtn->handleMouseDown(local_x, local_y, mask);
- }
- if (mLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
- handled = mLeftArrowBtn->handleMouseDown(local_x, local_y, mask);
- }
- else if (mRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mRightArrowBtn->getRect().mBottom;
- handled = mRightArrowBtn->handleMouseDown(local_x, local_y, mask);
- }
- }
- if (!handled)
+ if (no_scroll)
{
- handled = LLPanel::handleMouseDown( x, y, mask );
- }
-
- if (mTabList.size() > 0)
- {
- LLTabTuple* firsttuple = mTabList[0];
- LLRect tab_rect(has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft,
- firsttuple->mButton->getRect().mTop,
- has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mJumpRightArrowBtn->getRect().mRight,
- firsttuple->mButton->getRect().mBottom );
- if( tab_rect.pointInRect( x, y ) )
- {
- LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
- gFocusMgr.setMouseCapture(this);
- gFocusMgr.setKeyboardFocus(tab_button);
- }
- }
- return handled;
-}
-
-BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
-{
- BOOL handled = FALSE;
- BOOL has_scroll_arrows = (mMaxScrollPos > 0);
-
- if (has_scroll_arrows)
- {
- if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
- handled = mJumpLeftArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
- handled = mJumpRightArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
- handled = mLeftArrowBtn->handleHover(local_x, local_y, mask);
- }
- else if (mRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mRightArrowBtn->getRect().mBottom;
- handled = mRightArrowBtn->handleHover(local_x, local_y, mask);
- }
+ setMaxScrollPos(0);
+ setScrollPos(0);
}
- if (!handled)
+ if (getScrollPos() > getMaxScrollPos())
{
- handled = LLPanel::handleHover(x, y, mask);
+ setScrollPos(getMaxScrollPos()); // maybe just enforce this via limits in setScrollPos instead?
}
-
- commitHoveredButton(x, y);
- return handled;
}
-BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
+void LLTabContainer::commitHoveredButton(S32 x, S32 y)
{
- BOOL handled = FALSE;
- BOOL has_scroll_arrows = (mMaxScrollPos > 0);
-
- if (has_scroll_arrows)
- {
- if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
- handled = mJumpLeftArrowBtn->handleMouseUp(local_x, local_y, mask);
- }
- if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
- handled = mJumpRightArrowBtn->handleMouseUp(local_x, local_y, mask);
- }
- if (mLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
- handled = mLeftArrowBtn->handleMouseUp(local_x, local_y, mask);
- }
- else if (mRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mRightArrowBtn->getRect().mBottom;
- handled = mRightArrowBtn->handleMouseUp(local_x, local_y, mask);
- }
- }
- if (!handled)
- {
- handled = LLPanel::handleMouseUp( x, y, mask );
- }
-
- commitHoveredButton(x, y);
- LLPanel* cur_panel = getCurrentPanel();
if (hasMouseCapture())
{
- if (cur_panel)
- {
- if (!cur_panel->focusFirstItem(FALSE))
- {
- // if nothing in the panel gets focus, make sure the new tab does
- // otherwise the last tab might keep focus
- mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE);
- }
- }
- gFocusMgr.setMouseCapture(NULL);
- }
- return handled;
-}
-
-BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect )
-{
- BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
- if (!handled && mTabList.size() > 0)
- {
- LLTabTuple* firsttuple = mTabList[0];
-
- BOOL has_scroll_arrows = (mMaxScrollPos > 0);
- LLRect clip(
- has_scroll_arrows ? mJumpLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft,
- firsttuple->mButton->getRect().mTop,
- has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight,
- 0 );
- if( clip.pointInRect( x, y ) )
- {
- 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;
- handled = tuple->mButton->handleToolTip( local_x, local_y, msg, sticky_rect );
- if( handled )
- {
- break;
- }
- }
- }
-
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
- }
- }
- return handled;
-}
-
-BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
-{
- if (!getEnabled()) return FALSE;
-
- if (!gFocusMgr.childHasKeyboardFocus(this)) return FALSE;
-
- BOOL handled = FALSE;
- if (key == KEY_LEFT && mask == MASK_ALT)
- {
- selectPrevTab();
- handled = TRUE;
- }
- else if (key == KEY_RIGHT && mask == MASK_ALT)
- {
- selectNextTab();
- handled = TRUE;
- }
-
- if (handled)
- {
- if (getCurrentPanel())
- {
- getCurrentPanel()->setFocus(TRUE);
- }
- }
-
- if (!gFocusMgr.childHasKeyboardFocus(getCurrentPanel()))
- {
- // if child has focus, but not the current panel, focus
- // is on a button
- switch(key)
- {
- case KEY_UP:
- if (getTabPosition() == BOTTOM && getCurrentPanel())
- {
- getCurrentPanel()->setFocus(TRUE);
- }
- handled = TRUE;
- break;
- case KEY_DOWN:
- if (getTabPosition() == TOP && getCurrentPanel())
- {
- getCurrentPanel()->setFocus(TRUE);
- }
- handled = TRUE;
- break;
- case KEY_LEFT:
- selectPrevTab();
- handled = TRUE;
- break;
- case KEY_RIGHT:
- selectNextTab();
- handled = TRUE;
- break;
- default:
- break;
- }
- }
- return handled;
-}
-
-// virtual
-LLXMLNodePtr LLTabContainer::getXML(bool save_children) const
-{
- LLXMLNodePtr node = LLTabContainerCommon::getXML();
-
- node->createChild("tab_position", TRUE)->setStringValue((mTabPosition == TOP ? "top" : "bottom"));
-
- return node;
-}
-
-BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, LLString &tooltip)
-{
- BOOL has_scroll_arrows = (mMaxScrollPos > 0);
-
- if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
- {
-
- if (has_scroll_arrows)
- {
- if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
- mJumpLeftArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
- mJumpRightArrowBtn->handleHover(local_x, local_y, mask);
- }
- if (mLeftArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
- S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
- mLeftArrowBtn->handleHover(local_x, local_y, mask);
- }
- else if (mRightArrowBtn->getRect().pointInRect(x, y))
- {
- S32 local_x = x - mRightArrowBtn->getRect().mLeft;
- S32 local_y = y - mRightArrowBtn->getRect().mBottom;
- mRightArrowBtn->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->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();
- mDragAndDropDelayTimer.stop();
}
}
}
-
- return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
}
-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, color);
-
- const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
- // remove current width from total tab strip width
- mTotalTabWidth -= tuple->mButton->getRect().getWidth();
-
- S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
- tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
- 0;
-
- tuple->mPadding = image_overlay_width;
-
- 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();
-
- // tabs have changed size, might need to scroll to see current tab
- updateMaxScrollPos();
- }
-}