From c285f59ce2a05703e3a1232fcaf3ee3aea714b3f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 18 Feb 2024 12:52:19 +0100 Subject: Replace BOOL with bool in llwindow and dependent classes --- indra/llui/lltabcontainer.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index cb36f72f6e..512b2a9a30 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -541,11 +541,11 @@ void LLTabContainer::draw() // virtual -BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) +bool LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) { static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - BOOL handled = FALSE; - BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); + bool handled = false; + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); if (has_scroll_arrows) { @@ -617,10 +617,10 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) } // virtual -BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) +bool LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; - BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); + bool handled = false; + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); if (has_scroll_arrows) { @@ -663,10 +663,10 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) } // virtual -BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) +bool LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) { - BOOL handled = FALSE; - BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); + bool handled = false; + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); S32 local_x = x - getRect().mLeft; S32 local_y = y - getRect().mBottom; @@ -710,11 +710,11 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) { if (cur_panel) { - if (!cur_panel->focusFirstItem(FALSE)) + 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); + getTab(getCurrentPanelIndex())->mButton->setFocus(true); } } gFocusMgr.setMouseCapture(NULL); @@ -727,15 +727,15 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) } // virtual -BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask) +bool LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask) { static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - BOOL handled = LLPanel::handleToolTip( x, y, mask); + bool handled = LLPanel::handleToolTip( x, y, mask); if (!handled && getTabCount() > 0 && !getTabsHidden()) { LLTabTuple* firsttuple = getTab(0); - BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0); + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0); LLRect clip; if (mIsVertical) { -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/llui/lltabcontainer.cpp | 164 +++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 82 deletions(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 512b2a9a30..1328510a07 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -75,7 +75,7 @@ public: mTabContainer(c), mTabPanel(p), mButton(b), - mOldState(FALSE), + mOldState(false), mPlaceholderText(placeholder), mPadding(0), mVisible(true) @@ -84,7 +84,7 @@ public: LLTabContainer* mTabContainer; LLPanel* mTabPanel; LLButton* mButton; - BOOL mOldState; + bool mOldState; LLTextBox* mPlaceholderText; S32 mPadding; @@ -232,7 +232,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) : LLPanel(p), mCurrentTabIdx(-1), mTabsHidden(p.hide_tabs), - mScrolled(FALSE), + mScrolled(false), mScrollPos(0), mScrollPosPixels(0), mMaxScrollPos(0), @@ -306,14 +306,14 @@ void LLTabContainer::setValue(const LLSD& value) } //virtual -void LLTabContainer::reshape(S32 width, S32 height, BOOL called_from_parent) +void LLTabContainer::reshape(S32 width, S32 height, bool called_from_parent) { LLPanel::reshape( width, height, called_from_parent ); updateMaxScrollPos(); } //virtual -LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse) const +LLView* LLTabContainer::getChildView(const std::string& name, bool recurse) const { tuple_list_t::const_iterator itor; for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) @@ -341,7 +341,7 @@ LLView* LLTabContainer::getChildView(const std::string& name, BOOL recurse) cons } //virtual -LLView* LLTabContainer::findChildView(const std::string& name, BOOL recurse) const +LLView* LLTabContainer::findChildView(const std::string& name, bool recurse) const { tuple_list_t::const_iterator itor; for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) @@ -383,11 +383,11 @@ bool LLTabContainer::addChild(LLView* view, S32 tab_group) } } -BOOL LLTabContainer::postBuild() +bool LLTabContainer::postBuild() { selectFirstTab(); - return TRUE; + return true; } // virtual @@ -431,7 +431,7 @@ void LLTabContainer::draw() setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLSmoothInterpolation::getInterpolant(0.08f))); - BOOL has_scroll_arrows = !mHideScrollArrows && !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0)); + bool has_scroll_arrows = !mHideScrollArrows && !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0)); if (!mIsVertical) { mJumpPrevArrowBtn->setVisible( has_scroll_arrows ); @@ -459,7 +459,7 @@ void LLTabContainer::draw() for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( FALSE ); + tuple->mButton->setVisible( false ); } } @@ -478,7 +478,7 @@ void LLTabContainer::draw() for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( TRUE ); + tuple->mButton->setVisible( true ); } S32 max_scroll_visible = getTabCount() - getMaxScrollPos() + getScrollPos(); @@ -504,14 +504,14 @@ void LLTabContainer::draw() { if( tuple->mButton->getFlashing() ) { - mPrevArrowBtn->setFlashing( TRUE ); + mPrevArrowBtn->setFlashing( true ); } } else if( max_scroll_visible < idx ) { if( tuple->mButton->getFlashing() ) { - mNextArrowBtn->setFlashing( TRUE ); + mNextArrowBtn->setFlashing( true ); } } } @@ -604,7 +604,7 @@ bool LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) index = llclamp(index, 0, tab_count-1); LLButton* tab_button = getTab(index)->mButton; gFocusMgr.setMouseCapture(this); - tab_button->setFocus(TRUE); + tab_button->setFocus(true); mMouseDownTimer.start(); } } @@ -772,25 +772,25 @@ bool LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask) } // virtual -BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask) +bool LLTabContainer::handleKeyHere(KEY key, MASK mask) { - BOOL handled = FALSE; + bool handled = false; if (key == KEY_LEFT && mask == MASK_ALT) { selectPrevTab(); - handled = TRUE; + handled = true; } else if (key == KEY_RIGHT && mask == MASK_ALT) { selectNextTab(); - handled = TRUE; + handled = true; } if (handled) { if (getCurrentPanel()) { - getCurrentPanel()->setFocus(TRUE); + getCurrentPanel()->setFocus(true); } } @@ -803,21 +803,21 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask) { case KEY_UP: selectPrevTab(); - handled = TRUE; + handled = true; break; case KEY_DOWN: selectNextTab(); - handled = TRUE; + handled = true; break; case KEY_LEFT: - handled = TRUE; + handled = true; break; case KEY_RIGHT: if (getTabPosition() == LEFT && getCurrentPanel()) { - getCurrentPanel()->setFocus(TRUE); + getCurrentPanel()->setFocus(true); } - handled = TRUE; + handled = true; break; default: break; @@ -830,24 +830,24 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask) case KEY_UP: if (getTabPosition() == BOTTOM && getCurrentPanel()) { - getCurrentPanel()->setFocus(TRUE); + getCurrentPanel()->setFocus(true); } - handled = TRUE; + handled = true; break; case KEY_DOWN: if (getTabPosition() == TOP && getCurrentPanel()) { - getCurrentPanel()->setFocus(TRUE); + getCurrentPanel()->setFocus(true); } - handled = TRUE; + handled = true; break; case KEY_LEFT: selectPrevTab(); - handled = TRUE; + handled = true; break; case KEY_RIGHT: selectNextTab(); - handled = TRUE; + handled = true; break; default: break; @@ -858,9 +858,9 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask) } // virtual -BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip) +bool LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip) { - BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0); + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0); if(mOpenTabsOnDragAndDrop && !getTabsHidden()) { @@ -901,7 +901,7 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( TRUE ); + 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()) @@ -964,9 +964,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) const std::string& label = panel.label.isProvided() ? panel.label() : panel.panel()->getLabel(); - BOOL select = panel.select_tab(); + bool select = panel.select_tab(); S32 indent = panel.indent(); - BOOL placeholder = panel.is_placeholder; + bool placeholder = panel.is_placeholder; eInsertionPoint insertion_point = panel.insert_at(); static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); @@ -1030,10 +1030,10 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) } 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->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), true ); // add this child later - child->setVisible( FALSE ); // Will be made visible when selected + child->setVisible( false ); // Will be made visible when selected mTotalTabWidth += button_width; @@ -1255,7 +1255,7 @@ void LLTabContainer::removeTabPanel(LLPanel* child) } } - BOOL has_focus = gFocusMgr.childHasKeyboardFocus(this); + bool has_focus = gFocusMgr.childHasKeyboardFocus(this); // If the tab being deleted is the selected one, select a different tab. for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) @@ -1305,7 +1305,7 @@ void LLTabContainer::removeTabPanel(LLPanel* child) LLPanel* panelp = getPanelByIndex(mCurrentTabIdx); if (panelp) { - panelp->setFocus(TRUE); + panelp->setFocus(true); } } @@ -1324,7 +1324,7 @@ void LLTabContainer::unlockTabs() mLockedTabCount = 0; } -void LLTabContainer::enableTabButton(S32 which, BOOL enable) +void LLTabContainer::enableTabButton(S32 which, bool enable) { if (which >= 0 && which < (S32)mTabList.size()) { @@ -1453,10 +1453,10 @@ void LLTabContainer::selectNextTab() return; } - BOOL tab_has_focus = FALSE; + bool tab_has_focus = false; if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus()) { - tab_has_focus = TRUE; + tab_has_focus = true; } S32 idx = mCurrentTabIdx+1; if (idx >= (S32)mTabList.size()) @@ -1468,16 +1468,16 @@ void LLTabContainer::selectNextTab() if (tab_has_focus) { - mTabList[idx]->mButton->setFocus(TRUE); + mTabList[idx]->mButton->setFocus(true); } } void LLTabContainer::selectPrevTab() { - BOOL tab_has_focus = FALSE; + bool tab_has_focus = false; if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus()) { - tab_has_focus = TRUE; + tab_has_focus = true; } S32 idx = mCurrentTabIdx-1; if (idx < 0) @@ -1490,11 +1490,11 @@ void LLTabContainer::selectPrevTab() } if (tab_has_focus) { - mTabList[idx]->mButton->setFocus(TRUE); + mTabList[idx]->mButton->setFocus(true); } } -BOOL LLTabContainer::selectTabPanel(LLPanel* child) +bool LLTabContainer::selectTabPanel(LLPanel* child) { S32 idx = 0; for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) @@ -1506,25 +1506,25 @@ BOOL LLTabContainer::selectTabPanel(LLPanel* child) } idx++; } - return FALSE; + return false; } -BOOL LLTabContainer::selectTab(S32 which) +bool LLTabContainer::selectTab(S32 which) { if (which >= getTabCount() || which < 0) - return FALSE; + return false; LLTabTuple* selected_tuple = getTab(which); if (!selected_tuple) { - return FALSE; + return false; } LLSD cbdata; if (selected_tuple->mTabPanel) cbdata = selected_tuple->mTabPanel->getName(); - BOOL res = FALSE; + bool res = false; if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) ) { res = setTab(which); @@ -1538,16 +1538,16 @@ BOOL LLTabContainer::selectTab(S32 which) } // private -BOOL LLTabContainer::setTab(S32 which) +bool LLTabContainer::setTab(S32 which) { static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); LLTabTuple* selected_tuple = getTab(which); if (!selected_tuple) { - return FALSE; + return false; } - BOOL is_visible = FALSE; + bool is_visible = false; if( selected_tuple->mButton->getEnabled() && selected_tuple->mVisible ) { setCurrentPanelIndex(which); @@ -1556,7 +1556,7 @@ BOOL LLTabContainer::setTab(S32 which) for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) { LLTabTuple* tuple = *iter; - BOOL is_selected = ( tuple == selected_tuple ); + bool is_selected = ( tuple == selected_tuple ); // Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list if (tuple && tuple->mButton) { @@ -1583,11 +1583,11 @@ BOOL LLTabContainer::setTab(S32 which) if( i >= getScrollPos() && i <= getScrollPos() + num_visible) { setCurrentPanelIndex(which); - is_visible = TRUE; + is_visible = true; } else { - is_visible = FALSE; + is_visible = false; } } else if (!mHideScrollArrows && getMaxScrollPos() > 0) @@ -1619,11 +1619,11 @@ BOOL LLTabContainer::setTab(S32 which) setScrollPos(llclamp(getScrollPos(), min_scroll_pos, i)); setScrollPos(llmin(getScrollPos(), getMaxScrollPos())); } - is_visible = TRUE; + is_visible = true; } else { - is_visible = TRUE; + is_visible = true; } } i++; @@ -1632,36 +1632,36 @@ BOOL LLTabContainer::setTab(S32 which) if (mIsVertical && getCurrentPanelIndex() >= 0) { LLTabTuple* tuple = getTab(getCurrentPanelIndex()); - tuple->mTabPanel->setVisible( TRUE ); - tuple->mButton->setToggleState( TRUE ); + tuple->mTabPanel->setVisible( true ); + tuple->mButton->setToggleState( true ); } return is_visible; } -BOOL LLTabContainer::selectTabByName(const std::string& name) +bool LLTabContainer::selectTabByName(const std::string& name) { LLPanel* panel = getPanelByName(name); if (!panel) { LL_WARNS() << "LLTabContainer::selectTabByName(" << name << ") failed" << LL_ENDL; - return FALSE; + return false; } - BOOL result = selectTabPanel(panel); + bool result = selectTabPanel(panel); return result; } -BOOL LLTabContainer::getTabPanelFlashing(LLPanel *child) +bool LLTabContainer::getTabPanelFlashing(LLPanel *child) { LLTabTuple* tuple = getTabByPanel(child); if( tuple ) { return tuple->mButton->getFlashing(); } - return FALSE; + return false; } -void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state ) +void LLTabContainer::setTabPanelFlashing(LLPanel* child, bool state ) { LLTabTuple* tuple = getTabByPanel(child); if( tuple ) @@ -1811,7 +1811,7 @@ void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel ) if (tuple) { - tuple->mTabPanel->setFocus(TRUE); + tuple->mTabPanel->setFocus(true); } } @@ -1821,7 +1821,7 @@ void LLTabContainer::onNextBtn( const LLSD& data ) { scrollNext(); } - mScrolled = FALSE; + mScrolled = false; if(mCurrentTabIdx < mTabList.size()-1) { @@ -1840,7 +1840,7 @@ void LLTabContainer::onNextBtnHeld( const LLSD& data ) { selectNextTab(); } - mScrolled = TRUE; + mScrolled = true; } } @@ -1850,7 +1850,7 @@ void LLTabContainer::onPrevBtn( const LLSD& data ) { scrollPrev(); } - mScrolled = FALSE; + mScrolled = false; if(mCurrentTabIdx > 0) { @@ -1879,7 +1879,7 @@ void LLTabContainer::onPrevBtnHeld( const LLSD& data ) { selectPrevTab(); } - mScrolled = TRUE; + mScrolled = true; } } @@ -2009,21 +2009,21 @@ void LLTabContainer::initButtons() } } - mPrevArrowBtn->setTabStop(FALSE); + mPrevArrowBtn->setTabStop(false); addChild(mPrevArrowBtn); - mNextArrowBtn->setTabStop(FALSE); + mNextArrowBtn->setTabStop(false); addChild(mNextArrowBtn); if (mJumpPrevArrowBtn) { - mJumpPrevArrowBtn->setTabStop(FALSE); + mJumpPrevArrowBtn->setTabStop(false); addChild(mJumpPrevArrowBtn); } if (mJumpNextArrowBtn) { - mJumpNextArrowBtn->setTabStop(FALSE); + mJumpNextArrowBtn->setTabStop(false); addChild(mJumpNextArrowBtn); } @@ -2088,7 +2088,7 @@ void LLTabContainer::insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_p void LLTabContainer::updateMaxScrollPos() { static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - BOOL no_scroll = TRUE; + bool no_scroll = true; if (mIsVertical) { S32 tab_total_height = (BTN_HEIGHT + tabcntrv_pad) * getTabCount(); @@ -2099,7 +2099,7 @@ void LLTabContainer::updateMaxScrollPos() S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom; S32 additional_needed = tab_total_height - available_height_with_arrows; setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) ); - no_scroll = FALSE; + no_scroll = false; } } else @@ -2131,7 +2131,7 @@ void LLTabContainer::updateMaxScrollPos() } // in case last tab doesn't actually fit on screen, make it the last scrolling position setMaxScrollPos(llmin(getMaxScrollPos(), getTabCount() - 1)); - no_scroll = FALSE; + no_scroll = false; } } if (no_scroll) @@ -2197,9 +2197,9 @@ void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) } if( foundTab ) - this->setVisible( TRUE ); + this->setVisible( true ); else - this->setVisible( FALSE ); + this->setVisible( false ); updateMaxScrollPos(); } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llui/lltabcontainer.cpp | 4408 ++++++++++++++++++++--------------------- 1 file changed, 2204 insertions(+), 2204 deletions(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index a55e244711..752ef47d14 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1,2204 +1,2204 @@ -/** - * @file lltabcontainer.cpp - * @brief LLTabContainer class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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. - * - * 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. - * - * 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 "lllocalcliprect.h" -#include "llrect.h" -#include "llresizehandle.h" -#include "lltextbox.h" -#include "llcriticaldamp.h" -#include "lluictrlfactory.h" -#include "llrender.h" -#include "llfloater.h" -#include "lltrans.h" -#include "lluiusage.h" - -//---------------------------------------------------------------------------- - -// Implementation Notes: -// - Each tab points to a LLPanel (see LLTabTuple below) -// - When a tab is selected, the validation callback -// (LLUICtrl::mValidateSignal) is called -// - If the validation callback returns true (or none is provided), -// the tab is changed and the commit callback -// (LLUICtrl::mCommitSignal) is called -// - Callbacks pass the LLTabContainer as the control, -// and the NAME of the selected PANEL as the LLSD data - -//---------------------------------------------------------------------------- - -const F32 SCROLL_STEP_TIME = 0.4f; -const F32 SCROLL_DELAY_TIME = 0.5f; - -void LLTabContainer::TabPositions::declareValues() -{ - declare("top", LLTabContainer::TOP); - declare("bottom", LLTabContainer::BOTTOM); - declare("left", LLTabContainer::LEFT); -} - -//---------------------------------------------------------------------------- - -// Structure used to map tab buttons to and from tab panels -class LLTabTuple -{ -public: - LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, LLTextBox* placeholder = NULL) - : - mTabContainer(c), - mTabPanel(p), - mButton(b), - mOldState(false), - mPlaceholderText(placeholder), - mPadding(0), - mVisible(true) - {} - - LLTabContainer* mTabContainer; - LLPanel* mTabPanel; - LLButton* mButton; - bool mOldState; - LLTextBox* mPlaceholderText; - S32 mPadding; - - mutable bool mVisible; -}; - -//---------------------------------------------------------------------------- - -//============================================================================ -/* - * @file lltabcontainer.cpp - * @brief class implements LLButton with LLIconCtrl on it - */ -class LLCustomButtonIconCtrl : public LLButton -{ -public: - struct Params - : public LLInitParam::Block - { - // LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value - Optional 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 - struct Params : public LLPanel::Params{}; - LLPlaceHolderPanel(const Params& p) : LLPanel(p) - {} -}; -static LLDefaultChildRegistry::Register r1("placeholder"); -static LLDefaultChildRegistry::Register 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), - hide_scroll_arrows("hide_scroll_arrows", false), - tab_padding_right("tab_padding_right"), - 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), - enable_tabs_flashing("enable_tabs_flashing", false), - tabs_flashing_color("tabs_flashing_color"), - tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0), - use_ellipses("use_ellipses"), - font_halign("halign"), - use_tab_offset("use_tab_offset", false) -{} - -LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) -: LLPanel(p), - mCurrentTabIdx(-1), - mTabsHidden(p.hide_tabs), - mScrolled(false), - mScrollPos(0), - mScrollPosPixels(0), - mMaxScrollPos(0), - mTitleBox(NULL), - mTopBorderHeight(LLPANEL_BORDER_WIDTH), - mLockedTabCount(0), - 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 ), - mHideScrollArrows(p.hide_scroll_arrows), - // Horizontal Specific - mJumpPrevArrowBtn(NULL), - mJumpNextArrowBtn(NULL), - mRightTabBtnOffset(p.tab_padding_right), - mTotalTabWidth(0), - mTabPosition(p.tab_position), - 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), - mEnableTabsFlashing(p.enable_tabs_flashing), - mTabsFlashingColor(p.tabs_flashing_color), - mUseTabEllipses(p.use_ellipses), - mUseTabOffset(p.use_tab_offset) -{ - static LLUICachedControl tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0); - - mDragAndDropDelayTimer.stop(); - - if (p.tab_width.isProvided()) - { - mMinTabWidth = p.tab_width; - } - else if (!mIsVertical) - { - mMinTabWidth = p.tab_min_width; - } - else - { - // *HACK: support default min width for legacy vertical - // tab containers - mMinTabWidth = tabcntr_vert_tab_min_width; - } - - if (p.tabs_flashing_color.isProvided()) - { - mEnableTabsFlashing = true; - } - - initButtons( ); -} - -LLTabContainer::~LLTabContainer() -{ - std::for_each(mTabList.begin(), mTabList.end(), DeletePointer()); - mTabList.clear(); -} - -//virtual -void LLTabContainer::setValue(const LLSD& value) -{ - selectTab((S32) value.asInteger()); -} - -//virtual -void LLTabContainer::reshape(S32 width, S32 height, bool called_from_parent) -{ - LLPanel::reshape( width, height, called_from_parent ); - updateMaxScrollPos(); -} - -//virtual -LLView* LLTabContainer::getChildView(const std::string& name, bool recurse) const -{ - tuple_list_t::const_iterator itor; - for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) - { - LLPanel *panel = (*itor)->mTabPanel; - if (panel->getName() == name) - { - return panel; - } - } - - if (recurse) - { - for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) - { - LLPanel *panel = (*itor)->mTabPanel; - LLView *child = panel->getChildView(name, recurse); - if (child) - { - return child; - } - } - } - return LLView::getChildView(name, recurse); -} - -//virtual -LLView* LLTabContainer::findChildView(const std::string& name, bool recurse) const -{ - tuple_list_t::const_iterator itor; - for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) - { - LLPanel *panel = (*itor)->mTabPanel; - if (panel->getName() == name) - { - return panel; - } - } - - if (recurse) - { - for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) - { - LLPanel *panel = (*itor)->mTabPanel; - LLView *child = panel->findChildView(name, recurse); - if (child) - { - return child; - } - } - } - return LLView::findChildView(name, recurse); -} - -bool LLTabContainer::addChild(LLView* view, S32 tab_group) -{ - LLPanel* panelp = dynamic_cast(view); - - if (panelp) - { - addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast(view) != NULL)); - return true; - } - else - { - return LLUICtrl::addChild(view, tab_group); - } -} - -bool LLTabContainer::postBuild() -{ - selectFirstTab(); - - return true; -} - -// virtual -void LLTabContainer::draw() -{ - static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - static LLUICachedControl tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); - static LLUICachedControl tabcntr_tab_h_pad ("UITabCntrTabHPad", 0); - static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); - static LLUICachedControl tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0); - S32 target_pixel_scroll = 0; - S32 cur_scroll_pos = getScrollPos(); - if (cur_scroll_pos > 0) - { - if (mIsVertical) - { - target_pixel_scroll = cur_scroll_pos * (BTN_HEIGHT + tabcntrv_pad); - } - else - { - 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; - } - - if( (*iter)->mVisible ) - 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, LLSmoothInterpolation::getInterpolant(0.08f))); - - bool has_scroll_arrows = !mHideScrollArrows && !getTabsHidden() && ((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 - if (getTabsHidden()) - { - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( false ); - } - } - - { - 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()) - { - // Show all the buttons - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( true ); - } - - 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; - - if( !tuple->mVisible ) - { - tuple->mButton->setVisible( false ); - continue; - } - - 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 ); - } - } - } - - idx++; - } - - - if( mIsVertical && has_scroll_arrows ) - { - // Redraw the arrows so that they appears on top. - gGL.pushUIMatrix(); - gGL.translateUI((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f); - mPrevArrowBtn->draw(); - gGL.popUIMatrix(); - - gGL.pushUIMatrix(); - gGL.translateUI((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f); - mNextArrowBtn->draw(); - gGL.popUIMatrix(); - } - } - - mPrevArrowBtn->setFlashing(false); - mNextArrowBtn->setFlashing(false); -} - - -// virtual -bool LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) -{ - static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - bool handled = false; - bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); - - 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 ); - } - - S32 tab_count = getTabCount(); - 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 ); - } - 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 ) ) - { - S32 index = getCurrentPanelIndex(); - index = llclamp(index, 0, tab_count-1); - LLButton* tab_button = getTab(index)->mButton; - gFocusMgr.setMouseCapture(this); - tab_button->setFocus(true); - mMouseDownTimer.start(); - } - } - if (handled) { - // Note: May need to also capture local coords right here ? - LLViewerEventRecorder::instance().update_xui(getPathname( )); - } - - return handled; -} - -// virtual -bool LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) -{ - bool handled = false; - bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); - - 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); - } - - F32 drag_delay = 0.25f; // filter out clicks from dragging - if (mMouseDownTimer.getElapsedTimeF32() > drag_delay) - { - commitHoveredButton(x, y); - } - return handled; -} - -// virtual -bool LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) -{ - bool handled = false; - bool has_scroll_arrows = !mHideScrollArrows && (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)) - { - 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)) - { - 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)) - { - 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)) - { - local_x = x - mNextArrowBtn->getRect().mLeft; - 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); - mMouseDownTimer.stop(); - 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); - } - if (handled) { - // Note: may need to capture local coords here - LLViewerEventRecorder::instance().update_xui(getPathname( )); - } - return handled; -} - -// virtual -bool LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask) -{ - static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - bool handled = LLPanel::handleToolTip( x, y, mask); - if (!handled && getTabCount() > 0 && !getTabsHidden()) - { - LLTabTuple* firsttuple = getTab(0); - - bool has_scroll_arrows = !mHideScrollArrows && (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) - { - LLButton* tab_button = (*iter)->mButton; - if (!tab_button->getVisible()) continue; - S32 local_x = x - tab_button->getRect().mLeft; - S32 local_y = y - tab_button->getRect().mBottom; - handled = tab_button->handleToolTip(local_x, local_y, mask); - if( handled ) - { - break; - } - } - } - } - return handled; -} - -// virtual -bool LLTabContainer::handleKeyHere(KEY key, MASK mask) -{ - 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 -bool LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip) -{ - bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0); - - if(mOpenTabsOnDragAndDrop && !getTabsHidden()) - { - // In that case, we'll open the hovered tab while dragging and dropping items. - // This allows for drilling through tabs. - if (mDragAndDropDelayTimer.getStarted()) - { - if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME) - { - 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(); - } - } - // 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); -} - -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(params.tab_top_image_unselected)); - tuple->mButton->setImageSelected(static_cast(params.tab_top_image_selected)); - tuple->mButton->setImageFlash(static_cast(params.tab_top_image_flash)); - } - else if (pos == LLTabContainer::BOTTOM) - { - tuple->mButton->setImageUnselected(static_cast(params.tab_bottom_image_unselected)); - tuple->mButton->setImageSelected(static_cast(params.tab_bottom_image_selected)); - tuple->mButton->setImageFlash(static_cast(params.tab_bottom_image_flash)); - } - else if (pos == LLTabContainer::LEFT) - { - tuple->mButton->setImageUnselected(static_cast(params.tab_left_image_unselected)); - tuple->mButton->setImageSelected(static_cast(params.tab_left_image_selected)); - tuple->mButton->setImageFlash(static_cast(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(); - bool select = panel.select_tab(); - S32 indent = panel.indent(); - bool placeholder = panel.is_placeholder; - eInsertionPoint insertion_point = panel.insert_at(); - - static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - static LLUICachedControl tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0); - static LLUICachedControl tab_padding ("UITabPadding", 0); - if (child->getParent() == this) - { - // already a child of mine - return; - } - - // Store the original label for possible xml export. - child->setLabel(label); - std::string trimmed_label = label; - LLStringUtil::trim(trimmed_label); - - S32 button_width = mMinTabWidth; - if (!mIsVertical) - { - button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth); - } - - // Tab panel - S32 tab_panel_top; - S32 tab_panel_bottom; - if (!getTabsHidden()) - { - if( getTabPosition() == LLTabContainer::TOP ) - { - S32 tab_height = mIsVertical ? BTN_HEIGHT : mTabHeight; - 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 = (mTabHeight - tabcntr_button_panel_overlap); // Run to the edge, covering up the border - } - } - else - { - // Skip tab button space if tabs are invisible (EXT-576) - tab_panel_top = getRect().getHeight(); - tab_panel_bottom = LLPANEL_BORDER_WIDTH; - } - - LLRect tab_panel_rect; - if (!getTabsHidden() && mIsVertical) - { - 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); - } - else - { - S32 left_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 3 : LLPANEL_BORDER_WIDTH; - S32 right_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 2 : LLPANEL_BORDER_WIDTH; - tab_panel_rect = LLRect(left_offset, tab_panel_top, getRect().getWidth() - right_offset, 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 ); - // 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(). - LLUIImage* tab_img = NULL; - LLUIImage* tab_selected_img = NULL; - 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, mTabHeight); - 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 = 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, -6); // *TODO: make configurable - LLTextBox::Params params; - params.name(trimmed_label); - params.rect(btn_rect); - params.initial_value(trimmed_label); - params.font(mFont); - textbox = LLUICtrlFactory::create (params); - - LLButton::Params p; - p.name("placeholder"); - btn = LLUICtrlFactory::create(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) - { - 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); - } - - // inits flash timer - p.button_flash_enable = mEnableTabsFlashing; - p.flash_color = mTabsFlashingColor; - - // *TODO : It seems wrong not to use p in both cases considering the way p is initialized - if (mCustomIconCtrlUsed) - { - btn = LLUICtrlFactory::create(custom_btn_params); - } - else - { - btn = LLUICtrlFactory::create(p); - } - } - - 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) - { - addChild( textbox, 0 ); - } - if (btn) - { - 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); - - updateMaxScrollPos(); - - if( select ) - { - selectLastTab(); - mScrollPos = mMaxScrollPos; - } - -} - -void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label) -{ - addTabPanel(TabPanelParams().panel(child).label(label).is_placeholder(true)); -} - -void LLTabContainer::removeTabPanel(LLPanel* child) -{ - static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - 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. - for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - if( tuple->mTabPanel == child ) - { - // 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; - - break; - } - } - - // make sure we don't have more locked tabs than we have tabs - mLockedTabCount = llmin(getTabCount(), mLockedTabCount); - - if (mCurrentTabIdx >= (S32)mTabList.size()) - { - mCurrentTabIdx = mTabList.size()-1; - } - selectTab(mCurrentTabIdx); - if (has_focus) - { - LLPanel* panelp = getPanelByIndex(mCurrentTabIdx); - if (panelp) - { - panelp->setFocus(true); - } - } - - updateMaxScrollPos(); -} - -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); - } - // 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() -{ - // Remove all the tab buttons and delete them. Also, unlink all the child panels. - for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - - removeChild( tuple->mButton ); - delete tuple->mButton; - tuple->mButton = NULL; - - removeChild( tuple->mTabPanel ); -// delete tuple->mTabPanel; - tuple->mTabPanel = NULL; - } - - // Actually delete the tuples themselves - std::for_each(mTabList.begin(), mTabList.end(), DeletePointer()); - mTabList.clear(); - - // And there isn't a current tab any more - mCurrentTabIdx = -1; -} - -LLPanel* LLTabContainer::getCurrentPanel() -{ - if (mCurrentTabIdx >= 0 && mCurrentTabIdx < (S32) mTabList.size()) - { - return mTabList[mCurrentTabIdx]->mTabPanel; - } - return NULL; -} - -S32 LLTabContainer::getCurrentPanelIndex() -{ - return mCurrentTabIdx; -} - -S32 LLTabContainer::getTabCount() -{ - return mTabList.size(); -} - -LLPanel* LLTabContainer::getPanelByIndex(S32 index) -{ - if (index >= 0 && index < (S32)mTabList.size()) - { - return mTabList[index]->mTabPanel; - } - return NULL; -} - -S32 LLTabContainer::getIndexForPanel(LLPanel* panel) -{ - for (S32 index = 0; index < (S32)mTabList.size(); index++) - { - if (mTabList[index]->mTabPanel == panel) - { - return index; - } - } - return -1; -} - -S32 LLTabContainer::getPanelIndexByTitle(const std::string& title) -{ - for (S32 index = 0 ; index < (S32)mTabList.size(); index++) - { - if (title == mTabList[index]->mButton->getLabelSelected()) - { - return index; - } - } - return -1; -} - -LLPanel* LLTabContainer::getPanelByName(const std::string& name) -{ - for (S32 index = 0 ; index < (S32)mTabList.size(); index++) - { - LLPanel *panel = mTabList[index]->mTabPanel; - if (name == panel->getName()) - { - return panel; - } - } - return NULL; -} - -// Change the name of the button for the current tab. -void LLTabContainer::setCurrentTabName(const std::string& name) -{ - // Might not have a tab selected - if (mCurrentTabIdx < 0) return; - - mTabList[mCurrentTabIdx]->mButton->setLabelSelected(name); - mTabList[mCurrentTabIdx]->mButton->setLabelUnselected(name); -} - -void LLTabContainer::selectFirstTab() -{ - selectTab( 0 ); -} - - -void LLTabContainer::selectLastTab() -{ - selectTab( mTabList.size()-1 ); -} - -void LLTabContainer::selectNextTab() -{ - if (mTabList.size() == 0) - { - return; - } - - 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) - { - idx = (idx + 1 ) % (S32)mTabList.size(); - } - - if (tab_has_focus) - { - mTabList[idx]->mButton->setFocus(true); - } -} - -void LLTabContainer::selectPrevTab() -{ - bool tab_has_focus = false; - if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus()) - { - 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 LLTabContainer::selectTabPanel(LLPanel* child) -{ - S32 idx = 0; - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - if( tuple->mTabPanel == child ) - { - return selectTab( idx ); - } - idx++; - } - return false; -} - -bool LLTabContainer::selectTab(S32 which) -{ - if (which >= getTabCount() || which < 0) - return false; - - LLTabTuple* selected_tuple = getTab(which); - if (!selected_tuple) - return false; - - LLSD cbdata; - if (selected_tuple->mTabPanel) - cbdata = selected_tuple->mTabPanel->getName(); - - bool result = false; - if (!mValidateSignal || (*mValidateSignal)(this, cbdata)) - { - result = setTab(which); - if (result && mCommitSignal) - { - (*mCommitSignal)(this, cbdata); - } - } - - return result; -} - -// private -bool LLTabContainer::setTab(S32 which) -{ - static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); - LLTabTuple* selected_tuple = getTab(which); - if (!selected_tuple) - { - return false; - } - - bool is_visible = false; - if( selected_tuple->mButton->getEnabled() && selected_tuple->mVisible ) - { - 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 ); - // 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) - { - LLUIUsage::instance().logPanel(tuple->mTabPanel->getName()); - - // 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 (!mHideScrollArrows && getMaxScrollPos() > 0) - { - 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 && tuple->mButton ? tuple->mButton->getRect().getWidth() : 0); - 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 && other_tuple->mButton ? other_tuple->mButton->getRect().getWidth() : 0); - 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; - } - else - { - is_visible = true; - } - } - i++; - } - } - if (mIsVertical && getCurrentPanelIndex() >= 0) - { - LLTabTuple* tuple = getTab(getCurrentPanelIndex()); - tuple->mTabPanel->setVisible( true ); - tuple->mButton->setToggleState( true ); - } - return is_visible; -} - -bool LLTabContainer::selectTabByName(const std::string& name) -{ - LLPanel* panel = getPanelByName(name); - if (!panel) - { - LL_WARNS() << "LLTabContainer::selectTabByName(" << name << ") failed" << LL_ENDL; - return false; - } - - bool result = selectTabPanel(panel); - return result; -} - -bool LLTabContainer::getTabPanelFlashing(LLPanel *child) -{ - LLTabTuple* tuple = getTabByPanel(child); - if( tuple ) - { - return tuple->mButton->getFlashing(); - } - return false; -} - -void LLTabContainer::setTabPanelFlashing(LLPanel* child, bool state ) -{ - LLTabTuple* tuple = getTabByPanel(child); - if( tuple ) - { - tuple->mButton->setFlashing( state ); - } -} - -void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color) -{ - LLTabTuple* tuple = getTabByPanel(child); - if( tuple ) - { - tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color); - reshapeTuple(tuple); - } -} - -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(tuple->mButton); - if(button) - { - hasButton = true; - button->setIcon(icon); - reshapeTuple(tuple); - } - } - - 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(); - } -} - -void LLTabContainer::reshapeTuple(LLTabTuple* tuple) -{ - static LLUICachedControl tab_padding ("UITabPadding", 0); - - if (!mIsVertical) - { - S32 image_overlay_width = 0; - - if(mCustomIconCtrlUsed) - { - LLCustomButtonIconCtrl* button = dynamic_cast(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(); - } -} - -void LLTabContainer::setTitle(const std::string& title) -{ - if (mTitleBox) - { - mTitleBox->setText( title ); - } -} - -const std::string LLTabContainer::getPanelTitle(S32 index) -{ - if (index >= 0 && index < (S32)mTabList.size()) - { - LLButton* tab_button = mTabList[index]->mButton; - return tab_button->getLabelSelected(); - } - return LLStringUtil::null; -} - -void LLTabContainer::setTopBorderHeight(S32 height) -{ - mTopBorderHeight = height; -} - -S32 LLTabContainer::getTopBorderHeight() const -{ - return mTopBorderHeight; -} - -void LLTabContainer::setRightTabBtnOffset(S32 offset) -{ - mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 ); - mRightTabBtnOffset = offset; - updateMaxScrollPos(); -} - -void LLTabContainer::setPanelTitle(S32 index, const std::string& title) -{ - static LLUICachedControl tab_padding ("UITabPadding", 0); - - if (index >= 0 && index < getTabCount()) - { - LLTabTuple* tuple = getTab(index); - LLButton* tab_button = tuple->mButton; - const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall(); - 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(); -} - - -void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel ) -{ - LLTabTuple* tuple = getTabByPanel(panel); - selectTabPanel( panel ); - - if (tuple) - { - tuple->mTabPanel->setFocus(true); - } -} - -void LLTabContainer::onNextBtn( const LLSD& data ) -{ - if (!mScrolled) - { - scrollNext(); - } - mScrolled = false; - - if(mCurrentTabIdx < mTabList.size()-1) - { - selectNextTab(); - } -} - -void LLTabContainer::onNextBtnHeld( const LLSD& data ) -{ - if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) - { - mScrollTimer.reset(); - scrollNext(); - - if(mCurrentTabIdx < mTabList.size()-1) - { - selectNextTab(); - } - mScrolled = true; - } -} - -void LLTabContainer::onPrevBtn( const LLSD& data ) -{ - if (!mScrolled) - { - scrollPrev(); - } - mScrolled = false; - - if(mCurrentTabIdx > 0) - { - selectPrevTab(); - } -} - -void LLTabContainer::onJumpFirstBtn( const LLSD& data ) -{ - mScrollPos = 0; -} - -void LLTabContainer::onJumpLastBtn( const LLSD& data ) -{ - mScrollPos = mMaxScrollPos; -} - -void LLTabContainer::onPrevBtnHeld( const LLSD& data ) -{ - if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) - { - mScrollTimer.reset(); - scrollPrev(); - - if(mCurrentTabIdx > 0) - { - selectPrevTab(); - } - mScrolled = true; - } -} - -// private - -void LLTabContainer::initButtons() -{ - // Hack: - if (getRect().getHeight() == 0 || mPrevArrowBtn) - { - return; // Don't have a rect yet or already got called - } - - if (mIsVertical) - { - static LLUICachedControl tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); - // 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 down_arrow_btn_rect; - down_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top_lower, tabcntrv_arrow_btn_size, tabcntrv_arrow_btn_size ); - - LLButton::Params prev_btn_params; - prev_btn_params.name(std::string("Up Arrow")); - prev_btn_params.rect(up_arrow_btn_rect); - prev_btn_params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT); - prev_btn_params.image_unselected.name("scrollbutton_up_out_blue.tga"); - prev_btn_params.image_selected.name("scrollbutton_up_in_blue.tga"); - prev_btn_params.click_callback.function(boost::bind(&LLTabContainer::onPrevBtn, this, _2)); - mPrevArrowBtn = LLUICtrlFactory::create(prev_btn_params); - - LLButton::Params next_btn_params; - next_btn_params.name(std::string("Down Arrow")); - next_btn_params.rect(down_arrow_btn_rect); - next_btn_params.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_LEFT); - next_btn_params.image_unselected.name("scrollbutton_down_out_blue.tga"); - next_btn_params.image_selected.name("scrollbutton_down_in_blue.tga"); - next_btn_params.click_callback.function(boost::bind(&LLTabContainer::onNextBtn, this, _2)); - mNextArrowBtn = LLUICtrlFactory::create(next_btn_params); - } - else // Horizontal - { - static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); - S32 arrow_fudge = 1; // match new art better - - // 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; - - 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, 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, 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, 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, mTabHeight ); - - LLButton::Params p; - p.name(std::string("Jump Left Arrow")); - p.image_unselected.name("jump_left_out.tga"); - p.image_selected.name("jump_left_in.tga"); - p.click_callback.function(boost::bind(&LLTabContainer::onJumpFirstBtn, this, _2)); - p.rect(jump_left_arrow_btn_rect); - p.follows.flags(FOLLOWS_LEFT); - - mJumpPrevArrowBtn = LLUICtrlFactory::create(p); - - p = LLButton::Params(); - p.name(std::string("Left Arrow")); - p.rect(left_arrow_btn_rect); - p.follows.flags(FOLLOWS_LEFT); - p.image_unselected.name("scrollbutton_left_out_blue.tga"); - p.image_selected.name("scrollbutton_left_in_blue.tga"); - p.click_callback.function(boost::bind(&LLTabContainer::onPrevBtn, this, _2)); - p.mouse_held_callback.function(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2)); - - mPrevArrowBtn = LLUICtrlFactory::create(p); - - p = LLButton::Params(); - p.name(std::string("Jump Right Arrow")); - p.rect(jump_right_arrow_btn_rect); - p.follows.flags(FOLLOWS_RIGHT); - p.image_unselected.name("jump_right_out.tga"); - p.image_selected.name("jump_right_in.tga"); - p.click_callback.function(boost::bind(&LLTabContainer::onJumpLastBtn, this, _2)); - - mJumpNextArrowBtn = LLUICtrlFactory::create(p); - - p = LLButton::Params(); - p.name(std::string("Right Arrow")); - p.rect(right_arrow_btn_rect); - p.follows.flags(FOLLOWS_RIGHT); - p.image_unselected.name("scrollbutton_right_out_blue.tga"); - p.image_selected.name("scrollbutton_right_in_blue.tga"); - p.click_callback.function(boost::bind(&LLTabContainer::onNextBtn, this, _2)); - p.mouse_held_callback.function(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2)); - - mNextArrowBtn = LLUICtrlFactory::create(p); - - if( getTabPosition() == TOP ) - { - mNextArrowBtn->setFollowsTop(); - mPrevArrowBtn->setFollowsTop(); - mJumpPrevArrowBtn->setFollowsTop(); - mJumpNextArrowBtn->setFollowsTop(); - } - else - { - mNextArrowBtn->setFollowsBottom(); - mPrevArrowBtn->setFollowsBottom(); - mJumpPrevArrowBtn->setFollowsBottom(); - mJumpNextArrowBtn->setFollowsBottom(); - } - } - - mPrevArrowBtn->setTabStop(false); - addChild(mPrevArrowBtn); - - mNextArrowBtn->setTabStop(false); - addChild(mNextArrowBtn); - - if (mJumpPrevArrowBtn) - { - mJumpPrevArrowBtn->setTabStop(false); - addChild(mJumpPrevArrowBtn); - } - - if (mJumpNextArrowBtn) - { - mJumpNextArrowBtn->setTabStop(false); - addChild(mJumpNextArrowBtn); - } - - // set default tab group to be panel contents - setDefaultTabGroup(1); -} - -//this is a work around for the current LLPanel::initFromParams hack -//so that it doesn't overwrite the default tab group. -//will be removed when LLPanel is fixed soon. -void LLTabContainer::initFromParams(const LLPanel::Params& p) -{ - LLPanel::initFromParams(p); - - setDefaultTabGroup(1); -} - -LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child) -{ - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLTabTuple* tuple = *iter; - if( tuple->mTabPanel == child ) - { - return tuple; - } - } - return NULL; -} - -void LLTabContainer::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 ); - } -} - - - -void LLTabContainer::updateMaxScrollPos() -{ - static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); - bool no_scroll = true; - if (mIsVertical) - { - S32 tab_total_height = (BTN_HEIGHT + tabcntrv_pad) * getTabCount(); - S32 available_height = getRect().getHeight() - getTopBorderHeight(); - if( tab_total_height > available_height ) - { - static LLUICachedControl tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); - S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom; - S32 additional_needed = tab_total_height - available_height_with_arrows; - setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) ); - no_scroll = false; - } - } - else - { - static LLUICachedControl tabcntr_tab_h_pad ("UITabCntrTabHPad", 0); - static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); - static LLUICachedControl tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0); - S32 tab_space = 0; - S32 available_space = 0; - tab_space = mTotalTabWidth; - available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_tab_h_pad); - - if( tab_space > available_space ) - { - 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; - - S32 running_tab_width = 0; - setMaxScrollPos(getTabCount()); - for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it) - { - running_tab_width += (*tab_it)->mButton->getRect().getWidth(); - if (running_tab_width > available_width_with_arrows) - { - break; - } - 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; - } - } - if (no_scroll) - { - setMaxScrollPos(0); - setScrollPos(0); - } - if (getScrollPos() > getMaxScrollPos()) - { - setScrollPos(getMaxScrollPos()); // maybe just enforce this via limits in setScrollPos instead? - } -} - -void LLTabContainer::commitHoveredButton(S32 x, S32 y) -{ - if (!getTabsHidden() && hasMouseCapture()) - { - for (tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) - { - LLButton* button = (*iter)->mButton; - LLPanel* panel = (*iter)->mTabPanel; - if (button->getEnabled() && button->getVisible() && !panel->getVisible()) - { - S32 local_x = x - button->getRect().mLeft; - S32 local_y = y - button->getRect().mBottom; - if (button->pointInView(local_x, local_y)) - { - button->onCommit(); - break; - } - } - } - } -} - -S32 LLTabContainer::getTotalTabWidth() const -{ - return mTotalTabWidth; -} - -void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) -{ - for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr ) - { - LLTabTuple const *pTT = *itr; - if( pTT->mTabPanel == aPanel ) - { - pTT->mVisible = aVisible; - break; - } - } - - bool foundTab( false ); - for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr ) - { - LLTabTuple const *pTT = *itr; - if( pTT->mVisible ) - { - this->selectTab( itr - mTabList.begin() ); - foundTab = true; - break; - } - } - - if( foundTab ) - this->setVisible( true ); - else - this->setVisible( false ); - - updateMaxScrollPos(); -} +/** + * @file lltabcontainer.cpp + * @brief LLTabContainer class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * 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. + * + * 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. + * + * 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 "lllocalcliprect.h" +#include "llrect.h" +#include "llresizehandle.h" +#include "lltextbox.h" +#include "llcriticaldamp.h" +#include "lluictrlfactory.h" +#include "llrender.h" +#include "llfloater.h" +#include "lltrans.h" +#include "lluiusage.h" + +//---------------------------------------------------------------------------- + +// Implementation Notes: +// - Each tab points to a LLPanel (see LLTabTuple below) +// - When a tab is selected, the validation callback +// (LLUICtrl::mValidateSignal) is called +// - If the validation callback returns true (or none is provided), +// the tab is changed and the commit callback +// (LLUICtrl::mCommitSignal) is called +// - Callbacks pass the LLTabContainer as the control, +// and the NAME of the selected PANEL as the LLSD data + +//---------------------------------------------------------------------------- + +const F32 SCROLL_STEP_TIME = 0.4f; +const F32 SCROLL_DELAY_TIME = 0.5f; + +void LLTabContainer::TabPositions::declareValues() +{ + declare("top", LLTabContainer::TOP); + declare("bottom", LLTabContainer::BOTTOM); + declare("left", LLTabContainer::LEFT); +} + +//---------------------------------------------------------------------------- + +// Structure used to map tab buttons to and from tab panels +class LLTabTuple +{ +public: + LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, LLTextBox* placeholder = NULL) + : + mTabContainer(c), + mTabPanel(p), + mButton(b), + mOldState(false), + mPlaceholderText(placeholder), + mPadding(0), + mVisible(true) + {} + + LLTabContainer* mTabContainer; + LLPanel* mTabPanel; + LLButton* mButton; + bool mOldState; + LLTextBox* mPlaceholderText; + S32 mPadding; + + mutable bool mVisible; +}; + +//---------------------------------------------------------------------------- + +//============================================================================ +/* + * @file lltabcontainer.cpp + * @brief class implements LLButton with LLIconCtrl on it + */ +class LLCustomButtonIconCtrl : public LLButton +{ +public: + struct Params + : public LLInitParam::Block + { + // LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value + Optional 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 + struct Params : public LLPanel::Params{}; + LLPlaceHolderPanel(const Params& p) : LLPanel(p) + {} +}; +static LLDefaultChildRegistry::Register r1("placeholder"); +static LLDefaultChildRegistry::Register 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), + hide_scroll_arrows("hide_scroll_arrows", false), + tab_padding_right("tab_padding_right"), + 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), + enable_tabs_flashing("enable_tabs_flashing", false), + tabs_flashing_color("tabs_flashing_color"), + tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0), + use_ellipses("use_ellipses"), + font_halign("halign"), + use_tab_offset("use_tab_offset", false) +{} + +LLTabContainer::LLTabContainer(const LLTabContainer::Params& p) +: LLPanel(p), + mCurrentTabIdx(-1), + mTabsHidden(p.hide_tabs), + mScrolled(false), + mScrollPos(0), + mScrollPosPixels(0), + mMaxScrollPos(0), + mTitleBox(NULL), + mTopBorderHeight(LLPANEL_BORDER_WIDTH), + mLockedTabCount(0), + 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 ), + mHideScrollArrows(p.hide_scroll_arrows), + // Horizontal Specific + mJumpPrevArrowBtn(NULL), + mJumpNextArrowBtn(NULL), + mRightTabBtnOffset(p.tab_padding_right), + mTotalTabWidth(0), + mTabPosition(p.tab_position), + 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), + mEnableTabsFlashing(p.enable_tabs_flashing), + mTabsFlashingColor(p.tabs_flashing_color), + mUseTabEllipses(p.use_ellipses), + mUseTabOffset(p.use_tab_offset) +{ + static LLUICachedControl tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0); + + mDragAndDropDelayTimer.stop(); + + if (p.tab_width.isProvided()) + { + mMinTabWidth = p.tab_width; + } + else if (!mIsVertical) + { + mMinTabWidth = p.tab_min_width; + } + else + { + // *HACK: support default min width for legacy vertical + // tab containers + mMinTabWidth = tabcntr_vert_tab_min_width; + } + + if (p.tabs_flashing_color.isProvided()) + { + mEnableTabsFlashing = true; + } + + initButtons( ); +} + +LLTabContainer::~LLTabContainer() +{ + std::for_each(mTabList.begin(), mTabList.end(), DeletePointer()); + mTabList.clear(); +} + +//virtual +void LLTabContainer::setValue(const LLSD& value) +{ + selectTab((S32) value.asInteger()); +} + +//virtual +void LLTabContainer::reshape(S32 width, S32 height, bool called_from_parent) +{ + LLPanel::reshape( width, height, called_from_parent ); + updateMaxScrollPos(); +} + +//virtual +LLView* LLTabContainer::getChildView(const std::string& name, bool recurse) const +{ + tuple_list_t::const_iterator itor; + for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) + { + LLPanel *panel = (*itor)->mTabPanel; + if (panel->getName() == name) + { + return panel; + } + } + + if (recurse) + { + for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) + { + LLPanel *panel = (*itor)->mTabPanel; + LLView *child = panel->getChildView(name, recurse); + if (child) + { + return child; + } + } + } + return LLView::getChildView(name, recurse); +} + +//virtual +LLView* LLTabContainer::findChildView(const std::string& name, bool recurse) const +{ + tuple_list_t::const_iterator itor; + for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) + { + LLPanel *panel = (*itor)->mTabPanel; + if (panel->getName() == name) + { + return panel; + } + } + + if (recurse) + { + for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) + { + LLPanel *panel = (*itor)->mTabPanel; + LLView *child = panel->findChildView(name, recurse); + if (child) + { + return child; + } + } + } + return LLView::findChildView(name, recurse); +} + +bool LLTabContainer::addChild(LLView* view, S32 tab_group) +{ + LLPanel* panelp = dynamic_cast(view); + + if (panelp) + { + addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast(view) != NULL)); + return true; + } + else + { + return LLUICtrl::addChild(view, tab_group); + } +} + +bool LLTabContainer::postBuild() +{ + selectFirstTab(); + + return true; +} + +// virtual +void LLTabContainer::draw() +{ + static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); + static LLUICachedControl tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); + static LLUICachedControl tabcntr_tab_h_pad ("UITabCntrTabHPad", 0); + static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); + static LLUICachedControl tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0); + S32 target_pixel_scroll = 0; + S32 cur_scroll_pos = getScrollPos(); + if (cur_scroll_pos > 0) + { + if (mIsVertical) + { + target_pixel_scroll = cur_scroll_pos * (BTN_HEIGHT + tabcntrv_pad); + } + else + { + 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; + } + + if( (*iter)->mVisible ) + 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, LLSmoothInterpolation::getInterpolant(0.08f))); + + bool has_scroll_arrows = !mHideScrollArrows && !getTabsHidden() && ((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 + if (getTabsHidden()) + { + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + tuple->mButton->setVisible( false ); + } + } + + { + 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()) + { + // Show all the buttons + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + tuple->mButton->setVisible( true ); + } + + 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; + + if( !tuple->mVisible ) + { + tuple->mButton->setVisible( false ); + continue; + } + + 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 ); + } + } + } + + idx++; + } + + + if( mIsVertical && has_scroll_arrows ) + { + // Redraw the arrows so that they appears on top. + gGL.pushUIMatrix(); + gGL.translateUI((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f); + mPrevArrowBtn->draw(); + gGL.popUIMatrix(); + + gGL.pushUIMatrix(); + gGL.translateUI((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f); + mNextArrowBtn->draw(); + gGL.popUIMatrix(); + } + } + + mPrevArrowBtn->setFlashing(false); + mNextArrowBtn->setFlashing(false); +} + + +// virtual +bool LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) +{ + static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); + bool handled = false; + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); + + 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 ); + } + + S32 tab_count = getTabCount(); + 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 ); + } + 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 ) ) + { + S32 index = getCurrentPanelIndex(); + index = llclamp(index, 0, tab_count-1); + LLButton* tab_button = getTab(index)->mButton; + gFocusMgr.setMouseCapture(this); + tab_button->setFocus(true); + mMouseDownTimer.start(); + } + } + if (handled) { + // Note: May need to also capture local coords right here ? + LLViewerEventRecorder::instance().update_xui(getPathname( )); + } + + return handled; +} + +// virtual +bool LLTabContainer::handleHover( S32 x, S32 y, MASK mask ) +{ + bool handled = false; + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden(); + + 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); + } + + F32 drag_delay = 0.25f; // filter out clicks from dragging + if (mMouseDownTimer.getElapsedTimeF32() > drag_delay) + { + commitHoveredButton(x, y); + } + return handled; +} + +// virtual +bool LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + bool handled = false; + bool has_scroll_arrows = !mHideScrollArrows && (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)) + { + 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)) + { + 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)) + { + 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)) + { + local_x = x - mNextArrowBtn->getRect().mLeft; + 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); + mMouseDownTimer.stop(); + 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); + } + if (handled) { + // Note: may need to capture local coords here + LLViewerEventRecorder::instance().update_xui(getPathname( )); + } + return handled; +} + +// virtual +bool LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask) +{ + static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); + bool handled = LLPanel::handleToolTip( x, y, mask); + if (!handled && getTabCount() > 0 && !getTabsHidden()) + { + LLTabTuple* firsttuple = getTab(0); + + bool has_scroll_arrows = !mHideScrollArrows && (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) + { + LLButton* tab_button = (*iter)->mButton; + if (!tab_button->getVisible()) continue; + S32 local_x = x - tab_button->getRect().mLeft; + S32 local_y = y - tab_button->getRect().mBottom; + handled = tab_button->handleToolTip(local_x, local_y, mask); + if( handled ) + { + break; + } + } + } + } + return handled; +} + +// virtual +bool LLTabContainer::handleKeyHere(KEY key, MASK mask) +{ + 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 +bool LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip) +{ + bool has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0); + + if(mOpenTabsOnDragAndDrop && !getTabsHidden()) + { + // In that case, we'll open the hovered tab while dragging and dropping items. + // This allows for drilling through tabs. + if (mDragAndDropDelayTimer.getStarted()) + { + if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME) + { + 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(); + } + } + // 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); +} + +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(params.tab_top_image_unselected)); + tuple->mButton->setImageSelected(static_cast(params.tab_top_image_selected)); + tuple->mButton->setImageFlash(static_cast(params.tab_top_image_flash)); + } + else if (pos == LLTabContainer::BOTTOM) + { + tuple->mButton->setImageUnselected(static_cast(params.tab_bottom_image_unselected)); + tuple->mButton->setImageSelected(static_cast(params.tab_bottom_image_selected)); + tuple->mButton->setImageFlash(static_cast(params.tab_bottom_image_flash)); + } + else if (pos == LLTabContainer::LEFT) + { + tuple->mButton->setImageUnselected(static_cast(params.tab_left_image_unselected)); + tuple->mButton->setImageSelected(static_cast(params.tab_left_image_selected)); + tuple->mButton->setImageFlash(static_cast(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(); + bool select = panel.select_tab(); + S32 indent = panel.indent(); + bool placeholder = panel.is_placeholder; + eInsertionPoint insertion_point = panel.insert_at(); + + static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); + static LLUICachedControl tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0); + static LLUICachedControl tab_padding ("UITabPadding", 0); + if (child->getParent() == this) + { + // already a child of mine + return; + } + + // Store the original label for possible xml export. + child->setLabel(label); + std::string trimmed_label = label; + LLStringUtil::trim(trimmed_label); + + S32 button_width = mMinTabWidth; + if (!mIsVertical) + { + button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth); + } + + // Tab panel + S32 tab_panel_top; + S32 tab_panel_bottom; + if (!getTabsHidden()) + { + if( getTabPosition() == LLTabContainer::TOP ) + { + S32 tab_height = mIsVertical ? BTN_HEIGHT : mTabHeight; + 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 = (mTabHeight - tabcntr_button_panel_overlap); // Run to the edge, covering up the border + } + } + else + { + // Skip tab button space if tabs are invisible (EXT-576) + tab_panel_top = getRect().getHeight(); + tab_panel_bottom = LLPANEL_BORDER_WIDTH; + } + + LLRect tab_panel_rect; + if (!getTabsHidden() && mIsVertical) + { + 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); + } + else + { + S32 left_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 3 : LLPANEL_BORDER_WIDTH; + S32 right_offset = mUseTabOffset ? LLPANEL_BORDER_WIDTH * 2 : LLPANEL_BORDER_WIDTH; + tab_panel_rect = LLRect(left_offset, tab_panel_top, getRect().getWidth() - right_offset, 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 ); + // 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(). + LLUIImage* tab_img = NULL; + LLUIImage* tab_selected_img = NULL; + 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, mTabHeight); + 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 = 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, -6); // *TODO: make configurable + LLTextBox::Params params; + params.name(trimmed_label); + params.rect(btn_rect); + params.initial_value(trimmed_label); + params.font(mFont); + textbox = LLUICtrlFactory::create (params); + + LLButton::Params p; + p.name("placeholder"); + btn = LLUICtrlFactory::create(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) + { + 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); + } + + // inits flash timer + p.button_flash_enable = mEnableTabsFlashing; + p.flash_color = mTabsFlashingColor; + + // *TODO : It seems wrong not to use p in both cases considering the way p is initialized + if (mCustomIconCtrlUsed) + { + btn = LLUICtrlFactory::create(custom_btn_params); + } + else + { + btn = LLUICtrlFactory::create(p); + } + } + + 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) + { + addChild( textbox, 0 ); + } + if (btn) + { + 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); + + updateMaxScrollPos(); + + if( select ) + { + selectLastTab(); + mScrollPos = mMaxScrollPos; + } + +} + +void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label) +{ + addTabPanel(TabPanelParams().panel(child).label(label).is_placeholder(true)); +} + +void LLTabContainer::removeTabPanel(LLPanel* child) +{ + static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); + 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. + for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + if( tuple->mTabPanel == child ) + { + // 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; + + break; + } + } + + // make sure we don't have more locked tabs than we have tabs + mLockedTabCount = llmin(getTabCount(), mLockedTabCount); + + if (mCurrentTabIdx >= (S32)mTabList.size()) + { + mCurrentTabIdx = mTabList.size()-1; + } + selectTab(mCurrentTabIdx); + if (has_focus) + { + LLPanel* panelp = getPanelByIndex(mCurrentTabIdx); + if (panelp) + { + panelp->setFocus(true); + } + } + + updateMaxScrollPos(); +} + +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); + } + // 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() +{ + // Remove all the tab buttons and delete them. Also, unlink all the child panels. + for(std::vector::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + + removeChild( tuple->mButton ); + delete tuple->mButton; + tuple->mButton = NULL; + + removeChild( tuple->mTabPanel ); +// delete tuple->mTabPanel; + tuple->mTabPanel = NULL; + } + + // Actually delete the tuples themselves + std::for_each(mTabList.begin(), mTabList.end(), DeletePointer()); + mTabList.clear(); + + // And there isn't a current tab any more + mCurrentTabIdx = -1; +} + +LLPanel* LLTabContainer::getCurrentPanel() +{ + if (mCurrentTabIdx >= 0 && mCurrentTabIdx < (S32) mTabList.size()) + { + return mTabList[mCurrentTabIdx]->mTabPanel; + } + return NULL; +} + +S32 LLTabContainer::getCurrentPanelIndex() +{ + return mCurrentTabIdx; +} + +S32 LLTabContainer::getTabCount() +{ + return mTabList.size(); +} + +LLPanel* LLTabContainer::getPanelByIndex(S32 index) +{ + if (index >= 0 && index < (S32)mTabList.size()) + { + return mTabList[index]->mTabPanel; + } + return NULL; +} + +S32 LLTabContainer::getIndexForPanel(LLPanel* panel) +{ + for (S32 index = 0; index < (S32)mTabList.size(); index++) + { + if (mTabList[index]->mTabPanel == panel) + { + return index; + } + } + return -1; +} + +S32 LLTabContainer::getPanelIndexByTitle(const std::string& title) +{ + for (S32 index = 0 ; index < (S32)mTabList.size(); index++) + { + if (title == mTabList[index]->mButton->getLabelSelected()) + { + return index; + } + } + return -1; +} + +LLPanel* LLTabContainer::getPanelByName(const std::string& name) +{ + for (S32 index = 0 ; index < (S32)mTabList.size(); index++) + { + LLPanel *panel = mTabList[index]->mTabPanel; + if (name == panel->getName()) + { + return panel; + } + } + return NULL; +} + +// Change the name of the button for the current tab. +void LLTabContainer::setCurrentTabName(const std::string& name) +{ + // Might not have a tab selected + if (mCurrentTabIdx < 0) return; + + mTabList[mCurrentTabIdx]->mButton->setLabelSelected(name); + mTabList[mCurrentTabIdx]->mButton->setLabelUnselected(name); +} + +void LLTabContainer::selectFirstTab() +{ + selectTab( 0 ); +} + + +void LLTabContainer::selectLastTab() +{ + selectTab( mTabList.size()-1 ); +} + +void LLTabContainer::selectNextTab() +{ + if (mTabList.size() == 0) + { + return; + } + + 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) + { + idx = (idx + 1 ) % (S32)mTabList.size(); + } + + if (tab_has_focus) + { + mTabList[idx]->mButton->setFocus(true); + } +} + +void LLTabContainer::selectPrevTab() +{ + bool tab_has_focus = false; + if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus()) + { + 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 LLTabContainer::selectTabPanel(LLPanel* child) +{ + S32 idx = 0; + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + if( tuple->mTabPanel == child ) + { + return selectTab( idx ); + } + idx++; + } + return false; +} + +bool LLTabContainer::selectTab(S32 which) +{ + if (which >= getTabCount() || which < 0) + return false; + + LLTabTuple* selected_tuple = getTab(which); + if (!selected_tuple) + return false; + + LLSD cbdata; + if (selected_tuple->mTabPanel) + cbdata = selected_tuple->mTabPanel->getName(); + + bool result = false; + if (!mValidateSignal || (*mValidateSignal)(this, cbdata)) + { + result = setTab(which); + if (result && mCommitSignal) + { + (*mCommitSignal)(this, cbdata); + } + } + + return result; +} + +// private +bool LLTabContainer::setTab(S32 which) +{ + static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); + LLTabTuple* selected_tuple = getTab(which); + if (!selected_tuple) + { + return false; + } + + bool is_visible = false; + if( selected_tuple->mButton->getEnabled() && selected_tuple->mVisible ) + { + 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 ); + // 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) + { + LLUIUsage::instance().logPanel(tuple->mTabPanel->getName()); + + // 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 (!mHideScrollArrows && getMaxScrollPos() > 0) + { + 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 && tuple->mButton ? tuple->mButton->getRect().getWidth() : 0); + 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 && other_tuple->mButton ? other_tuple->mButton->getRect().getWidth() : 0); + 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; + } + else + { + is_visible = true; + } + } + i++; + } + } + if (mIsVertical && getCurrentPanelIndex() >= 0) + { + LLTabTuple* tuple = getTab(getCurrentPanelIndex()); + tuple->mTabPanel->setVisible( true ); + tuple->mButton->setToggleState( true ); + } + return is_visible; +} + +bool LLTabContainer::selectTabByName(const std::string& name) +{ + LLPanel* panel = getPanelByName(name); + if (!panel) + { + LL_WARNS() << "LLTabContainer::selectTabByName(" << name << ") failed" << LL_ENDL; + return false; + } + + bool result = selectTabPanel(panel); + return result; +} + +bool LLTabContainer::getTabPanelFlashing(LLPanel *child) +{ + LLTabTuple* tuple = getTabByPanel(child); + if( tuple ) + { + return tuple->mButton->getFlashing(); + } + return false; +} + +void LLTabContainer::setTabPanelFlashing(LLPanel* child, bool state ) +{ + LLTabTuple* tuple = getTabByPanel(child); + if( tuple ) + { + tuple->mButton->setFlashing( state ); + } +} + +void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color) +{ + LLTabTuple* tuple = getTabByPanel(child); + if( tuple ) + { + tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color); + reshapeTuple(tuple); + } +} + +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(tuple->mButton); + if(button) + { + hasButton = true; + button->setIcon(icon); + reshapeTuple(tuple); + } + } + + 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(); + } +} + +void LLTabContainer::reshapeTuple(LLTabTuple* tuple) +{ + static LLUICachedControl tab_padding ("UITabPadding", 0); + + if (!mIsVertical) + { + S32 image_overlay_width = 0; + + if(mCustomIconCtrlUsed) + { + LLCustomButtonIconCtrl* button = dynamic_cast(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(); + } +} + +void LLTabContainer::setTitle(const std::string& title) +{ + if (mTitleBox) + { + mTitleBox->setText( title ); + } +} + +const std::string LLTabContainer::getPanelTitle(S32 index) +{ + if (index >= 0 && index < (S32)mTabList.size()) + { + LLButton* tab_button = mTabList[index]->mButton; + return tab_button->getLabelSelected(); + } + return LLStringUtil::null; +} + +void LLTabContainer::setTopBorderHeight(S32 height) +{ + mTopBorderHeight = height; +} + +S32 LLTabContainer::getTopBorderHeight() const +{ + return mTopBorderHeight; +} + +void LLTabContainer::setRightTabBtnOffset(S32 offset) +{ + mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 ); + mRightTabBtnOffset = offset; + updateMaxScrollPos(); +} + +void LLTabContainer::setPanelTitle(S32 index, const std::string& title) +{ + static LLUICachedControl tab_padding ("UITabPadding", 0); + + if (index >= 0 && index < getTabCount()) + { + LLTabTuple* tuple = getTab(index); + LLButton* tab_button = tuple->mButton; + const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall(); + 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(); +} + + +void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel ) +{ + LLTabTuple* tuple = getTabByPanel(panel); + selectTabPanel( panel ); + + if (tuple) + { + tuple->mTabPanel->setFocus(true); + } +} + +void LLTabContainer::onNextBtn( const LLSD& data ) +{ + if (!mScrolled) + { + scrollNext(); + } + mScrolled = false; + + if(mCurrentTabIdx < mTabList.size()-1) + { + selectNextTab(); + } +} + +void LLTabContainer::onNextBtnHeld( const LLSD& data ) +{ + if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) + { + mScrollTimer.reset(); + scrollNext(); + + if(mCurrentTabIdx < mTabList.size()-1) + { + selectNextTab(); + } + mScrolled = true; + } +} + +void LLTabContainer::onPrevBtn( const LLSD& data ) +{ + if (!mScrolled) + { + scrollPrev(); + } + mScrolled = false; + + if(mCurrentTabIdx > 0) + { + selectPrevTab(); + } +} + +void LLTabContainer::onJumpFirstBtn( const LLSD& data ) +{ + mScrollPos = 0; +} + +void LLTabContainer::onJumpLastBtn( const LLSD& data ) +{ + mScrollPos = mMaxScrollPos; +} + +void LLTabContainer::onPrevBtnHeld( const LLSD& data ) +{ + if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME) + { + mScrollTimer.reset(); + scrollPrev(); + + if(mCurrentTabIdx > 0) + { + selectPrevTab(); + } + mScrolled = true; + } +} + +// private + +void LLTabContainer::initButtons() +{ + // Hack: + if (getRect().getHeight() == 0 || mPrevArrowBtn) + { + return; // Don't have a rect yet or already got called + } + + if (mIsVertical) + { + static LLUICachedControl tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); + // 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 down_arrow_btn_rect; + down_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top_lower, tabcntrv_arrow_btn_size, tabcntrv_arrow_btn_size ); + + LLButton::Params prev_btn_params; + prev_btn_params.name(std::string("Up Arrow")); + prev_btn_params.rect(up_arrow_btn_rect); + prev_btn_params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT); + prev_btn_params.image_unselected.name("scrollbutton_up_out_blue.tga"); + prev_btn_params.image_selected.name("scrollbutton_up_in_blue.tga"); + prev_btn_params.click_callback.function(boost::bind(&LLTabContainer::onPrevBtn, this, _2)); + mPrevArrowBtn = LLUICtrlFactory::create(prev_btn_params); + + LLButton::Params next_btn_params; + next_btn_params.name(std::string("Down Arrow")); + next_btn_params.rect(down_arrow_btn_rect); + next_btn_params.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_LEFT); + next_btn_params.image_unselected.name("scrollbutton_down_out_blue.tga"); + next_btn_params.image_selected.name("scrollbutton_down_in_blue.tga"); + next_btn_params.click_callback.function(boost::bind(&LLTabContainer::onNextBtn, this, _2)); + mNextArrowBtn = LLUICtrlFactory::create(next_btn_params); + } + else // Horizontal + { + static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); + S32 arrow_fudge = 1; // match new art better + + // 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; + + 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, 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, 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, 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, mTabHeight ); + + LLButton::Params p; + p.name(std::string("Jump Left Arrow")); + p.image_unselected.name("jump_left_out.tga"); + p.image_selected.name("jump_left_in.tga"); + p.click_callback.function(boost::bind(&LLTabContainer::onJumpFirstBtn, this, _2)); + p.rect(jump_left_arrow_btn_rect); + p.follows.flags(FOLLOWS_LEFT); + + mJumpPrevArrowBtn = LLUICtrlFactory::create(p); + + p = LLButton::Params(); + p.name(std::string("Left Arrow")); + p.rect(left_arrow_btn_rect); + p.follows.flags(FOLLOWS_LEFT); + p.image_unselected.name("scrollbutton_left_out_blue.tga"); + p.image_selected.name("scrollbutton_left_in_blue.tga"); + p.click_callback.function(boost::bind(&LLTabContainer::onPrevBtn, this, _2)); + p.mouse_held_callback.function(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2)); + + mPrevArrowBtn = LLUICtrlFactory::create(p); + + p = LLButton::Params(); + p.name(std::string("Jump Right Arrow")); + p.rect(jump_right_arrow_btn_rect); + p.follows.flags(FOLLOWS_RIGHT); + p.image_unselected.name("jump_right_out.tga"); + p.image_selected.name("jump_right_in.tga"); + p.click_callback.function(boost::bind(&LLTabContainer::onJumpLastBtn, this, _2)); + + mJumpNextArrowBtn = LLUICtrlFactory::create(p); + + p = LLButton::Params(); + p.name(std::string("Right Arrow")); + p.rect(right_arrow_btn_rect); + p.follows.flags(FOLLOWS_RIGHT); + p.image_unselected.name("scrollbutton_right_out_blue.tga"); + p.image_selected.name("scrollbutton_right_in_blue.tga"); + p.click_callback.function(boost::bind(&LLTabContainer::onNextBtn, this, _2)); + p.mouse_held_callback.function(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2)); + + mNextArrowBtn = LLUICtrlFactory::create(p); + + if( getTabPosition() == TOP ) + { + mNextArrowBtn->setFollowsTop(); + mPrevArrowBtn->setFollowsTop(); + mJumpPrevArrowBtn->setFollowsTop(); + mJumpNextArrowBtn->setFollowsTop(); + } + else + { + mNextArrowBtn->setFollowsBottom(); + mPrevArrowBtn->setFollowsBottom(); + mJumpPrevArrowBtn->setFollowsBottom(); + mJumpNextArrowBtn->setFollowsBottom(); + } + } + + mPrevArrowBtn->setTabStop(false); + addChild(mPrevArrowBtn); + + mNextArrowBtn->setTabStop(false); + addChild(mNextArrowBtn); + + if (mJumpPrevArrowBtn) + { + mJumpPrevArrowBtn->setTabStop(false); + addChild(mJumpPrevArrowBtn); + } + + if (mJumpNextArrowBtn) + { + mJumpNextArrowBtn->setTabStop(false); + addChild(mJumpNextArrowBtn); + } + + // set default tab group to be panel contents + setDefaultTabGroup(1); +} + +//this is a work around for the current LLPanel::initFromParams hack +//so that it doesn't overwrite the default tab group. +//will be removed when LLPanel is fixed soon. +void LLTabContainer::initFromParams(const LLPanel::Params& p) +{ + LLPanel::initFromParams(p); + + setDefaultTabGroup(1); +} + +LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child) +{ + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + if( tuple->mTabPanel == child ) + { + return tuple; + } + } + return NULL; +} + +void LLTabContainer::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 ); + } +} + + + +void LLTabContainer::updateMaxScrollPos() +{ + static LLUICachedControl tabcntrv_pad ("UITabCntrvPad", 0); + bool no_scroll = true; + if (mIsVertical) + { + S32 tab_total_height = (BTN_HEIGHT + tabcntrv_pad) * getTabCount(); + S32 available_height = getRect().getHeight() - getTopBorderHeight(); + if( tab_total_height > available_height ) + { + static LLUICachedControl tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0); + S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom; + S32 additional_needed = tab_total_height - available_height_with_arrows; + setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) ); + no_scroll = false; + } + } + else + { + static LLUICachedControl tabcntr_tab_h_pad ("UITabCntrTabHPad", 0); + static LLUICachedControl tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0); + static LLUICachedControl tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0); + S32 tab_space = 0; + S32 available_space = 0; + tab_space = mTotalTabWidth; + available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_tab_h_pad); + + if( tab_space > available_space ) + { + 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; + + S32 running_tab_width = 0; + setMaxScrollPos(getTabCount()); + for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it) + { + running_tab_width += (*tab_it)->mButton->getRect().getWidth(); + if (running_tab_width > available_width_with_arrows) + { + break; + } + 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; + } + } + if (no_scroll) + { + setMaxScrollPos(0); + setScrollPos(0); + } + if (getScrollPos() > getMaxScrollPos()) + { + setScrollPos(getMaxScrollPos()); // maybe just enforce this via limits in setScrollPos instead? + } +} + +void LLTabContainer::commitHoveredButton(S32 x, S32 y) +{ + if (!getTabsHidden() && hasMouseCapture()) + { + for (tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLButton* button = (*iter)->mButton; + LLPanel* panel = (*iter)->mTabPanel; + if (button->getEnabled() && button->getVisible() && !panel->getVisible()) + { + S32 local_x = x - button->getRect().mLeft; + S32 local_y = y - button->getRect().mBottom; + if (button->pointInView(local_x, local_y)) + { + button->onCommit(); + break; + } + } + } + } +} + +S32 LLTabContainer::getTotalTabWidth() const +{ + return mTotalTabWidth; +} + +void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) +{ + for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr ) + { + LLTabTuple const *pTT = *itr; + if( pTT->mTabPanel == aPanel ) + { + pTT->mVisible = aVisible; + break; + } + } + + bool foundTab( false ); + for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr ) + { + LLTabTuple const *pTT = *itr; + if( pTT->mVisible ) + { + this->selectTab( itr - mTabList.begin() ); + foundTab = true; + break; + } + } + + if( foundTab ) + this->setVisible( true ); + else + this->setVisible( false ); + + updateMaxScrollPos(); +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/llui/lltabcontainer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 752ef47d14..06f584d372 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1298,7 +1298,7 @@ void LLTabContainer::removeTabPanel(LLPanel* child) if (mCurrentTabIdx >= (S32)mTabList.size()) { - mCurrentTabIdx = mTabList.size()-1; + mCurrentTabIdx = static_cast(mTabList.size()) - 1; } selectTab(mCurrentTabIdx); if (has_focus) @@ -1377,7 +1377,7 @@ S32 LLTabContainer::getCurrentPanelIndex() S32 LLTabContainer::getTabCount() { - return mTabList.size(); + return static_cast(mTabList.size()); } LLPanel* LLTabContainer::getPanelByIndex(S32 index) @@ -1444,7 +1444,7 @@ void LLTabContainer::selectFirstTab() void LLTabContainer::selectLastTab() { - selectTab( mTabList.size()-1 ); + selectTab(static_cast(mTabList.size()) - 1); } void LLTabContainer::selectNextTab() @@ -1482,12 +1482,12 @@ void LLTabContainer::selectPrevTab() } S32 idx = mCurrentTabIdx-1; if (idx < 0) - idx = mTabList.size()-1; + idx = static_cast(mTabList.size()) - 1; while (!selectTab(idx) && idx != mCurrentTabIdx) { idx = idx - 1; if (idx < 0) - idx = mTabList.size()-1; + idx = static_cast(mTabList.size()) - 1; } if (tab_has_focus) { -- cgit v1.2.3 From e834e77988fcf637ee0f3e4c5c0875e47044e324 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Mon, 1 Jul 2024 21:48:34 -0400 Subject: Reduce string temporaries from findChild and getChild --- indra/llui/lltabcontainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 06f584d372..f10d545126 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -315,7 +315,7 @@ void LLTabContainer::reshape(S32 width, S32 height, bool called_from_parent) } //virtual -LLView* LLTabContainer::getChildView(const std::string& name, bool recurse) const +LLView* LLTabContainer::getChildView(std::string_view name, bool recurse) const { tuple_list_t::const_iterator itor; for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) @@ -343,7 +343,7 @@ LLView* LLTabContainer::getChildView(const std::string& name, bool recurse) cons } //virtual -LLView* LLTabContainer::findChildView(const std::string& name, bool recurse) const +LLView* LLTabContainer::findChildView(std::string_view name, bool recurse) const { tuple_list_t::const_iterator itor; for (itor = mTabList.begin(); itor != mTabList.end(); ++itor) -- cgit v1.2.3 From 14cbf331cbf345bac83606ee5f56c994694420b3 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Tue, 2 Jul 2024 08:56:42 -0400 Subject: Reduce string temporaries from LLTabContainer, LLMenuGL, LLLayoutStack, and LLKeywords using string_view --- indra/llui/lltabcontainer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index f10d545126..0a617558d2 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1401,7 +1401,7 @@ S32 LLTabContainer::getIndexForPanel(LLPanel* panel) return -1; } -S32 LLTabContainer::getPanelIndexByTitle(const std::string& title) +S32 LLTabContainer::getPanelIndexByTitle(std::string_view title) { for (S32 index = 0 ; index < (S32)mTabList.size(); index++) { @@ -1413,7 +1413,7 @@ S32 LLTabContainer::getPanelIndexByTitle(const std::string& title) return -1; } -LLPanel* LLTabContainer::getPanelByName(const std::string& name) +LLPanel* LLTabContainer::getPanelByName(std::string_view name) { for (S32 index = 0 ; index < (S32)mTabList.size(); index++) { @@ -1637,7 +1637,7 @@ bool LLTabContainer::setTab(S32 which) return is_visible; } -bool LLTabContainer::selectTabByName(const std::string& name) +bool LLTabContainer::selectTabByName(std::string_view name) { LLPanel* panel = getPanelByName(name); if (!panel) -- cgit v1.2.3 From 9fdca96f8bd2211a99fe88e57b70cbecefa20b6d Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 8 Jul 2024 20:27:14 +0200 Subject: Re-enable compiler warnings C4244 and C4396 except for lltracerecording.h and llunittype.h for now --- indra/llui/lltabcontainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llui/lltabcontainer.cpp') diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 0a617558d2..595ab0bd2b 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -2189,7 +2189,7 @@ void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible ) LLTabTuple const *pTT = *itr; if( pTT->mVisible ) { - this->selectTab( itr - mTabList.begin() ); + this->selectTab((S32)(itr - mTabList.begin())); foundTab = true; break; } -- cgit v1.2.3