Newer
Older
Steven Bennetts
committed
* @brief LLTabContainer class
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* 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
Richard Nelson
committed
#include "llviewereventrecorder.h"
Richard Nelson
committed
#include "lllocalcliprect.h"
#include "llrect.h"
#include "llresizehandle.h"
#include "lltextbox.h"
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
#include "llrender.h"
#include "llfloater.h"
Leyla Farazha
committed
#include "lltrans.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_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<Params, LLButton::Params>
{
// LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value
Optional<S32> icon_ctrl_pad;
Params()
: icon_ctrl_pad("icon_ctrl_pad", 1)
{}
};
protected:
friend class LLUICtrlFactory;
LLCustomButtonIconCtrl(const Params& p)
: LLButton(p),
Ychebotarev ProductEngine
committed
mIconCtrlPad(p.icon_ctrl_pad)
public:
void updateLayout()
{
LLRect button_rect = getRect();
LLRect icon_rect = mIcon->getRect();
Ychebotarev ProductEngine
committed
S32 icon_size = button_rect.getHeight() - 2*mIconCtrlPad;
switch(mIconAlignment)
{
case LLFontGL::LEFT:
Ychebotarev ProductEngine
committed
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:
Ychebotarev ProductEngine
committed
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();
}
}
Paul Guslisty
committed
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)
{}
};
James Cook
committed
static LLDefaultChildRegistry::Register<LLPlaceHolderPanel> r1("placeholder");
static LLDefaultChildRegistry::Register<LLTabContainer> r2("tab_container");
LLTabContainer::TabParams::TabParams()
: tab_top_image_unselected("tab_top_image_unselected"),
tab_top_image_selected("tab_top_image_selected"),
tab_top_image_flash("tab_top_image_flash"),
tab_bottom_image_unselected("tab_bottom_image_unselected"),
tab_bottom_image_selected("tab_bottom_image_selected"),
tab_bottom_image_flash("tab_bottom_image_flash"),
tab_left_image_unselected("tab_left_image_unselected"),
tab_left_image_selected("tab_left_image_selected"),
tab_left_image_flash("tab_left_image_flash")
LLTabContainer::Params::Params()
: tab_width("tab_width"),
tab_min_width("tab_min_width"),
tab_max_width("tab_max_width"),
tab_height("tab_height"),
label_pad_bottom("label_pad_bottom"),
label_pad_left("label_pad_left"),
tab_position("tab_position"),
hide_tabs("hide_tabs", false),
Mnikolenko Productengine
committed
hide_scroll_arrows("hide_scroll_arrows", false),
James Cook
committed
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),
Merov Linden
committed
open_tabs_on_drag_and_drop("open_tabs_on_drag_and_drop", false),
andreykproductengine
committed
enable_tabs_flashing("enable_tabs_flashing", false),
tabs_flashing_color("tabs_flashing_color"),
Paul Guslisty
committed
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
Paul Guslisty
committed
use_ellipses("use_ellipses"),
font_halign("halign")
LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
: LLPanel(p),
mTabsHidden(p.hide_tabs),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
mMaxScrollPos(0),
mTitleBox(NULL),
mTopBorderHeight(LLPANEL_BORDER_WIDTH),
Steven Bennetts
committed
mLockedTabCount(0),
mMinTabWidth(0),
mMaxTabWidth(p.tab_max_width),
mTabHeight(p.tab_height),
mLabelPadBottom(p.label_pad_bottom),
mLabelPadLeft(p.label_pad_left),
Steven Bennetts
committed
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical( p.tab_position == LEFT ),
Mnikolenko Productengine
committed
mHideScrollArrows(p.hide_scroll_arrows),
Steven Bennetts
committed
// Horizontal Specific
mJumpPrevArrowBtn(NULL),
mJumpNextArrowBtn(NULL),
mRightTabBtnOffset(p.tab_padding_right),
mTotalTabWidth(0),
mTabPosition(p.tab_position),
Leyla Farazha
committed
mFont(p.font),
mFirstTabParams(p.first_tab),
mMiddleTabParams(p.middle_tab),
mLastTabParams(p.last_tab),
mCustomIconCtrlUsed(p.use_custom_icon_ctrl),
Merov Linden
committed
mOpenTabsOnDragAndDrop(p.open_tabs_on_drag_and_drop),
Paul Guslisty
committed
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
mEnableTabsFlashing(p.enable_tabs_flashing),
mTabsFlashingColor(p.tabs_flashing_color),
mUseTabEllipses(p.use_ellipses)
{
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
mDragAndDropDelayTimer.stop();
if (p.tab_width.isProvided())
{
mMinTabWidth = p.tab_width;
}
else if (!mIsVertical)
Steven Bennetts
committed
{
mMinTabWidth = p.tab_min_width;
Steven Bennetts
committed
}
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;
}
Steven Bennetts
committed
initButtons( );
Steven Bennetts
committed
LLTabContainer::~LLTabContainer()
{
std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
Steven Bennetts
committed
}
Steven Bennetts
committed
//virtual
void LLTabContainer::setValue(const LLSD& value)
Steven Bennetts
committed
selectTab((S32) value.asInteger());
}
//virtual
void LLTabContainer::reshape(S32 width, S32 height, BOOL called_from_parent)
Steven Bennetts
committed
LLPanel::reshape( width, height, called_from_parent );
updateMaxScrollPos();
Steven Bennetts
committed
//virtual

Rye Mutt
committed
LLView* LLTabContainer::getChildView(std::string_view 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);
return LLView::getChildView(name, recurse);
}
//virtual

Rye Mutt
committed
LLView* LLTabContainer::findChildView(std::string_view 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<LLPanel*>(view);
if (panelp)
{
addTabPanel(TabPanelParams().panel(panelp).label(panelp->getLabel()).is_placeholder(dynamic_cast<LLPlaceHolderPanel*>(view) != NULL));
return true;
}
else
{
return LLUICtrl::addChild(view, tab_group);
}
}
BOOL LLTabContainer::postBuild()
{
selectFirstTab();
return TRUE;
}
Steven Bennetts
committed
// virtual
void LLTabContainer::draw()
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
static LLUICachedControl<S32> tabcntr_tab_h_pad ("UITabCntrTabHPad", 0);
static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
static LLUICachedControl<S32> tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0);
Steven Bennetts
committed
S32 target_pixel_scroll = 0;
S32 cur_scroll_pos = getScrollPos();
Steven Bennetts
committed
if (cur_scroll_pos > 0)
andreykproductengine
committed
if (mIsVertical)
andreykproductengine
committed
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)
Steven Bennetts
committed
{
if (cur_scroll_pos == 0)
{
break;
}
if( (*iter)->mVisible )
target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
cur_scroll_pos--;
Steven Bennetts
committed
}
// 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);
}
Steven Bennetts
committed
setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLSmoothInterpolation::getInterpolant(0.08f)));
Mnikolenko Productengine
committed
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
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
Steven Bennetts
committed
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
tuple->mButton->setVisible( TRUE );
Steven Bennetts
committed
}
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() )
Steven Bennetts
committed
{
if( tuple->mButton->getFlashing() )
Steven Bennetts
committed
{
mPrevArrowBtn->setFlashing( TRUE );
Steven Bennetts
committed
}
}
else if( max_scroll_visible < idx )
Steven Bennetts
committed
{
if( tuple->mButton->getFlashing() )
{
mNextArrowBtn->setFlashing( TRUE );
}
Steven Bennetts
committed
}
Steven Bennetts
committed
}
if( mIsVertical && has_scroll_arrows )
{
// Redraw the arrows so that they appears on top.
Palmer Truelson
committed
gGL.pushUIMatrix();
gGL.translateUI((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
mPrevArrowBtn->draw();
Palmer Truelson
committed
gGL.popUIMatrix();
Palmer Truelson
committed
gGL.pushUIMatrix();
gGL.translateUI((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
mNextArrowBtn->draw();
Palmer Truelson
committed
gGL.popUIMatrix();
Steven Bennetts
committed
}
mPrevArrowBtn->setFlashing(false);
mNextArrowBtn->setFlashing(false);
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
Steven Bennetts
committed
BOOL handled = FALSE;
Mnikolenko Productengine
committed
BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden();
Steven Bennetts
committed
if (has_scroll_arrows)
Steven Bennetts
committed
if (mJumpPrevArrowBtn&& mJumpPrevArrowBtn->getRect().pointInRect(x, y))
Steven Bennetts
committed
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);
Steven Bennetts
committed
if (!handled)
{
handled = LLPanel::handleMouseDown( x, y, mask );
}
S32 tab_count = getTabCount();
Richard Linden
committed
if (tab_count > 0 && !getTabsHidden())
Steven Bennetts
committed
LLTabTuple* firsttuple = getTab(0);
LLRect tab_rect;
if (mIsVertical)
Steven Bennetts
committed
tab_rect = LLRect(firsttuple->mButton->getRect().mLeft,
Richard Linden
committed
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 );
Steven Bennetts
committed
}
else
{
tab_rect = LLRect(has_scroll_arrows ? mPrevArrowBtn->getRect().mRight : mJumpPrevArrowBtn->getRect().mLeft,
Richard Linden
committed
firsttuple->mButton->getRect().mTop,
has_scroll_arrows ? mNextArrowBtn->getRect().mLeft : mJumpNextArrowBtn->getRect().mRight,
firsttuple->mButton->getRect().mBottom );
Steven Bennetts
committed
}
if( tab_rect.pointInRect( x, y ) )
{
S32 index = getCurrentPanelIndex();
index = llclamp(index, 0, tab_count-1);
LLButton* tab_button = getTab(index)->mButton;
Steven Bennetts
committed
gFocusMgr.setMouseCapture(this);
tab_button->setFocus(TRUE);
#if AL_VIEWER_EVENT_RECORDER
if (handled && LLViewerEventRecorder::getLoggingStatus()) {
// Note: May need to also capture local coords right here ?
LLViewerEventRecorder::instance().update_xui(getPathname( ));
}
#endif
Steven Bennetts
committed
return handled;
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
Steven Bennetts
committed
BOOL handled = FALSE;
Mnikolenko Productengine
committed
BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden();
Steven Bennetts
committed
if (has_scroll_arrows)
Steven Bennetts
committed
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
Steven Bennetts
committed
S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
handled = mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
Steven Bennetts
committed
else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
Steven Bennetts
committed
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);
Steven Bennetts
committed
if (!handled)
Steven Bennetts
committed
handled = LLPanel::handleHover(x, y, mask);
Steven Bennetts
committed
commitHoveredButton(x, y);
return handled;
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
Steven Bennetts
committed
BOOL handled = FALSE;
Mnikolenko Productengine
committed
BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0) && !getTabsHidden();
S32 local_x = x - getRect().mLeft;
S32 local_y = y - getRect().mBottom;
Steven Bennetts
committed
if (has_scroll_arrows)
{
Steven Bennetts
committed
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
{
local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
Steven Bennetts
committed
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;
Steven Bennetts
committed
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;
Steven Bennetts
committed
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;
Steven Bennetts
committed
handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
}
Steven Bennetts
committed
if (!handled)
Steven Bennetts
committed
handled = LLPanel::handleMouseUp( x, y, mask );
Steven Bennetts
committed
commitHoveredButton(x, y);
LLPanel* cur_panel = getCurrentPanel();
if (hasMouseCapture())
Steven Bennetts
committed
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 AL_VIEWER_EVENT_RECORDER
if (handled && LLViewerEventRecorder::getLoggingStatus()) {
// Note: may need to capture local coords here
LLViewerEventRecorder::instance().update_xui(getPathname( ));
}
#endif
Steven Bennetts
committed
return handled;
Steven Bennetts
committed
// virtual
James Cook
committed
BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
James Cook
committed
BOOL handled = LLPanel::handleToolTip( x, y, mask);
Richard Linden
committed
if (!handled && getTabCount() > 0 && !getTabsHidden())
Steven Bennetts
committed
LLTabTuple* firsttuple = getTab(0);
Mnikolenko Productengine
committed
BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0);
Steven Bennetts
committed
LLRect clip;
if (mIsVertical)
Steven Bennetts
committed
clip = LLRect(firsttuple->mButton->getRect().mLeft,
has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - tabcntrv_pad : mPrevArrowBtn->getRect().mTop,
Steven Bennetts
committed
firsttuple->mButton->getRect().mRight,
has_scroll_arrows ? mNextArrowBtn->getRect().mTop + tabcntrv_pad : mNextArrowBtn->getRect().mBottom );
Steven Bennetts
committed
else
Steven Bennetts
committed
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 );
Steven Bennetts
committed
if( clip.pointInRect( x, y ) )
Steven Bennetts
committed
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
maxim_productengine
committed
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);
Steven Bennetts
committed
if( handled )
{
break;
}
}
Steven Bennetts
committed
return handled;
}
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask)
Steven Bennetts
committed
{
BOOL handled = FALSE;
if (key == KEY_LEFT && mask == MASK_ALT)
Steven Bennetts
committed
selectPrevTab();
handled = TRUE;
}
else if (key == KEY_RIGHT && mask == MASK_ALT)
{
selectNextTab();
handled = TRUE;
Steven Bennetts
committed
if (handled)
Steven Bennetts
committed
if (getCurrentPanel())
Steven Bennetts
committed
getCurrentPanel()->setFocus(TRUE);
Steven Bennetts
committed
if (!gFocusMgr.childHasKeyboardFocus(getCurrentPanel()))
Steven Bennetts
committed
// if child has focus, but not the current panel, focus is on a button
if (mIsVertical)
Steven Bennetts
committed
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;
}
Steven Bennetts
committed
else
Steven Bennetts
committed
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
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;
}
Steven Bennetts
committed
return handled;
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip)
Mnikolenko Productengine
committed
BOOL has_scroll_arrows = !mHideScrollArrows && (getMaxScrollPos() > 0);
Merov Linden
committed
if(mOpenTabsOnDragAndDrop && !getTabsHidden())
Merov Linden
committed
// In that case, we'll open the hovered tab while dragging and dropping items.
// This allows for drilling through tabs.
if (mDragAndDropDelayTimer.getStarted())
Steven Bennetts
committed
{
Merov Linden
committed
if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME)
Steven Bennetts
committed
{
Merov Linden
committed
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
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);
}
}
Josh Bell
committed
Merov Linden
committed
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.
Steven Bennetts
committed
mDragAndDropDelayTimer.stop();
}
}
Merov Linden
committed
else
{
// Start a timer so we don't open tabs as soon as we hover on them
mDragAndDropDelayTimer.start();
}
Steven Bennetts
committed
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, const TabParams& params, LLTabContainer::TabPosition pos)
{
if (tuple && tuple->mButton)
{
if (pos == LLTabContainer::TOP)
{
tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_top_image_unselected));
tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_top_image_selected));
tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_top_image_flash));
}
else if (pos == LLTabContainer::BOTTOM)
{
tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_bottom_image_unselected));
tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_bottom_image_selected));
tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_bottom_image_flash));
}
else if (pos == LLTabContainer::LEFT)
{
tuple->mButton->setImageUnselected(static_cast<LLUIImage*>(params.tab_left_image_unselected));
tuple->mButton->setImageSelected(static_cast<LLUIImage*>(params.tab_left_image_selected));
tuple->mButton->setImageFlash(static_cast<LLUIImage*>(params.tab_left_image_flash));
}
}
}
void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLPanel* child = panel.panel();
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<S32> tabcntrv_pad ("UITabCntrvPad", 0);
static LLUICachedControl<S32> tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0);
static LLUICachedControl<S32> 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);
Steven Bennetts
committed
S32 button_width = mMinTabWidth;
if (!mIsVertical)
{
button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
Steven Bennetts
committed
}
// Tab panel
S32 tab_panel_top;
S32 tab_panel_bottom;
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
//Scip tab button space if they are invisible(EXT - 576)
tab_panel_top = getRect().getHeight();
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
Steven Bennetts
committed
LLRect tab_panel_rect;
Steven Bennetts
committed
{
Paul Guslisty
committed
tab_panel_rect = LLRect(mMinTabWidth + mRightTabBtnOffset + (LLPANEL_BORDER_WIDTH * 2) + tabcntrv_pad,
Steven Bennetts
committed
getRect().getHeight() - LLPANEL_BORDER_WIDTH,
getRect().getWidth() - LLPANEL_BORDER_WIDTH,
LLPANEL_BORDER_WIDTH);
}
else
{
tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH,
tab_panel_top,
getRect().getWidth()-LLPANEL_BORDER_WIDTH,
tab_panel_bottom );
}
child->setFollowsAll();
child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
// 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
Steven Bennetts
committed
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()),
Steven Bennetts
committed
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;
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;
Steven Bennetts
committed
LLTextBox* textbox = NULL;
LLButton* btn = NULL;
Ychebotarev ProductEngine
committed
LLCustomButtonIconCtrl::Params custom_btn_params;
{
custom_btn_params.icon_ctrl_pad(mTabIconCtrlPad);
}
LLButton::Params normal_btn_params;
Steven Bennetts
committed
btn_rect.translate(0, -6); // *TODO: make configurable
LLTextBox::Params params;
params.name(trimmed_label);
params.rect(btn_rect);
James Cook
committed
params.initial_value(trimmed_label);
textbox = LLUICtrlFactory::create<LLTextBox> (params);
Steven Bennetts
committed
LLButton::Params p;
p.name("placeholder");
btn = LLUICtrlFactory::create<LLButton>(p);
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;
Steven Bennetts
committed
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;
{
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);
}
andreykproductengine
committed
// 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<LLCustomButtonIconCtrl>(custom_btn_params);
}
else
{
btn = LLUICtrlFactory::create<LLButton>(p);
Steven Bennetts
committed
}
LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox );
Steven Bennetts
committed
insertTuple( tuple, insertion_point );
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
// 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())
Steven Bennetts
committed
{
if (textbox)
{
addChild( textbox, 0 );
}
if (btn)
{
addChild( btn, 0 );
}
Stinson Linden
committed
else
{
if (textbox)
{
LLUICtrl::addChild(textbox, 0);
}
if (btn)
{
LLUICtrl::addChild(btn, 0);
}
}
Steven Bennetts
committed
if (child)
{
LLUICtrl::addChild(child, 1);
Steven Bennetts
committed
}
sendChildToFront(mPrevArrowBtn);
sendChildToFront(mNextArrowBtn);
sendChildToFront(mJumpPrevArrowBtn);
sendChildToFront(mJumpNextArrowBtn);
andreykproductengine
committed
updateMaxScrollPos();
andreykproductengine
committed
mScrollPos = mMaxScrollPos;
Steven Bennetts
committed
}
void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label)
Steven Bennetts
committed
{
addTabPanel(TabPanelParams().panel(child).label(label).is_placeholder(true));
}
void LLTabContainer::removeTabPanel(LLPanel* child)
{
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
Steven Bennetts
committed
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)),
Steven Bennetts
committed
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
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<LLTabTuple*>::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());
}
Seth ProductEngine
committed
if (!getTabsHidden())
{
// We need to remove tab buttons only if the tabs are not hidden.
removeChild( tuple->mButton );
}
Steven Bennetts
committed
delete tuple->mButton;
Merov Linden
committed
tuple->mButton = NULL;
Steven Bennetts
committed
removeChild( tuple->mTabPanel );
// delete tuple->mTabPanel;
Merov Linden
committed
tuple->mTabPanel = NULL;
Steven Bennetts
committed
mTabList.erase( iter );
delete tuple;
Steven Bennetts
committed
// 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();
Steven Bennetts
committed
void LLTabContainer::lockTabs(S32 num_tabs)
Steven Bennetts
committed
// 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())
Steven Bennetts
committed
mTabList[which]->mButton->setEnabled(enable);
Merov Linden
committed
// 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();
Steven Bennetts
committed
void LLTabContainer::deleteAllTabs()
{
// Remove all the tab buttons and delete them. Also, unlink all the child panels.
for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
Steven Bennetts
committed
removeChild( tuple->mButton );
delete tuple->mButton;
Merov Linden
committed
tuple->mButton = NULL;
Steven Bennetts
committed
removeChild( tuple->mTabPanel );
// delete tuple->mTabPanel;
Merov Linden
committed
tuple->mTabPanel = NULL;
Steven Bennetts
committed
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
}
// 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()
Steven Bennetts
committed
return mTabList.size();
}
Steven Bennetts
committed
LLPanel* LLTabContainer::getPanelByIndex(S32 index)
{
if (index >= 0 && index < (S32)mTabList.size())
Steven Bennetts
committed
return mTabList[index]->mTabPanel;
}
return NULL;
}
Steven Bennetts
committed
S32 LLTabContainer::getIndexForPanel(LLPanel* panel)
{
for (S32 index = 0; index < (S32)mTabList.size(); index++)
{
if (mTabList[index]->mTabPanel == panel)
Steven Bennetts
committed
return index;
Steven Bennetts
committed
return -1;
}
S32 LLTabContainer::getPanelIndexByTitle(std::string_view title)
Steven Bennetts
committed
{
for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
Steven Bennetts
committed
if (title == mTabList[index]->mButton->getLabelSelected())
{
return index;
}
Steven Bennetts
committed
return -1;
LLPanel* LLTabContainer::getPanelByName(std::string_view name)
Steven Bennetts
committed
for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
Steven Bennetts
committed
LLPanel *panel = mTabList[index]->mTabPanel;
if (name == panel->getName())
Steven Bennetts
committed
return panel;
Steven Bennetts
committed
return NULL;
}
// Change the name of the button for the current tab.
void LLTabContainer::setCurrentTabName(const std::string& name)
Steven Bennetts
committed
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
{
// 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()
{
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);
}
}
Steven Bennetts
committed
BOOL LLTabContainer::selectTabPanel(LLPanel* child)
Steven Bennetts
committed
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;
Steven Bennetts
committed
LLTabTuple* selected_tuple = getTab(which);
if (!selected_tuple)
{
return FALSE;
}
LLSD cbdata;
if (selected_tuple->mTabPanel)
cbdata = selected_tuple->mTabPanel->getName();
BOOL res = FALSE;
if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) )
res = setTab(which);
if (res && mCommitSignal)
(*mCommitSignal)(this, cbdata);
return res;
BOOL LLTabContainer::setTab(S32 which)
{
static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
LLTabTuple* selected_tuple = getTab(which);
if (!selected_tuple)
{
return FALSE;
}
Steven Bennetts
committed
BOOL is_visible = FALSE;
if( selected_tuple->mButton->getEnabled() && selected_tuple->mVisible )
Steven Bennetts
committed
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 );
Merov Linden
committed
// Although the selected tab must be complete, we may have hollow LLTabTuple tucked in the list
Merov Linden
committed
if (tuple && tuple->mButton)
Merov Linden
committed
{
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 );
}
Merov Linden
committed
if (tuple && tuple->mTabPanel)
Merov Linden
committed
{
tuple->mTabPanel->setVisible( is_selected );
//tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
}
if (is_selected)
{
// Make sure selected tab is within scroll region
Steven Bennetts
committed
if (mIsVertical)
Steven Bennetts
committed
S32 num_visible = getTabCount() - getMaxScrollPos();
if( i >= getScrollPos() && i <= getScrollPos() + num_visible)
{
setCurrentPanelIndex(which);
is_visible = TRUE;
}
else
{
is_visible = FALSE;
}
Mnikolenko Productengine
committed
else if (!mHideScrollArrows && getMaxScrollPos() > 0)
Steven Bennetts
committed
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);
Merov Linden
committed
S32 running_tab_width = (tuple && tuple->mButton ? tuple->mButton->getRect().getWidth() : 0);
Steven Bennetts
committed
S32 j = i - 1;
S32 min_scroll_pos = i;
if (running_tab_width < available_width_with_arrows)
Steven Bennetts
committed
while (j >= 0)
Steven Bennetts
committed
LLTabTuple* other_tuple = getTab(j);
Merov Linden
committed
running_tab_width += (other_tuple && other_tuple->mButton ? other_tuple->mButton->getRect().getWidth() : 0);
Steven Bennetts
committed
if (running_tab_width > available_width_with_arrows)
{
break;
}
j--;
Steven Bennetts
committed
min_scroll_pos = j + 1;
Steven Bennetts
committed
setScrollPos(llclamp(getScrollPos(), min_scroll_pos, i));
setScrollPos(llmin(getScrollPos(), getMaxScrollPos()));
Steven Bennetts
committed
is_visible = TRUE;
else
{
is_visible = TRUE;
}
Steven Bennetts
committed
if (mIsVertical && getCurrentPanelIndex() >= 0)
Steven Bennetts
committed
LLTabTuple* tuple = getTab(getCurrentPanelIndex());
tuple->mTabPanel->setVisible( TRUE );
tuple->mButton->setToggleState( TRUE );
Steven Bennetts
committed
return is_visible;
BOOL LLTabContainer::selectTabByName(std::string_view name)
Steven Bennetts
committed
LLPanel* panel = getPanelByName(name);
if (!panel)
LL_WARNS() << "LLTabContainer::selectTabByName(" << name << ") failed" << LL_ENDL;
Steven Bennetts
committed
return FALSE;
}
Steven Bennetts
committed
BOOL result = selectTabPanel(panel);
return result;
}
BOOL LLTabContainer::getTabPanelFlashing(LLPanel *child)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
return tuple->mButton->getFlashing();
Steven Bennetts
committed
return FALSE;
}
Steven Bennetts
committed
void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state )
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
Steven Bennetts
committed
tuple->mButton->setFlashing( state );
}
}
Steven Bennetts
committed
void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
Paul Guslisty
committed
tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color);
Steven Bennetts
committed
}
}
void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
{
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
Paul Guslisty
committed
tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color);
Paul Guslisty
committed
}
}
void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
{
LLTabTuple* tuple = getTabByPanel(child);
LLCustomButtonIconCtrl* button;
Stinson Linden
committed
bool hasButton = false;
if(tuple)
{
button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
if(button)
{
Stinson Linden
committed
hasButton = true;
Paul Guslisty
committed
reshapeTuple(tuple);
Paul Guslisty
committed
}
Stinson Linden
committed
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();
}
Paul Guslisty
committed
}
void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
Paul Guslisty
committed
{
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
Paul Guslisty
committed
if (!mIsVertical)
{
Paul Guslisty
committed
S32 image_overlay_width = 0;
Paul Guslisty
committed
if(mCustomIconCtrlUsed)
{
LLCustomButtonIconCtrl* button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
Paul Guslisty
committed
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;
}
Paul Guslisty
committed
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
Paul Guslisty
committed
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)
Steven Bennetts
committed
{
if (mTitleBox)
{
mTitleBox->setText( title );
}
}
const std::string LLTabContainer::getPanelTitle(S32 index)
Steven Bennetts
committed
{
if (index >= 0 && index < (S32)mTabList.size())
{
LLButton* tab_button = mTabList[index]->mButton;
return tab_button->getLabelSelected();
}
return LLStringUtil::null;
Steven Bennetts
committed
}
Steven Bennetts
committed
void LLTabContainer::setTopBorderHeight(S32 height)
{
mTopBorderHeight = height;
}
S32 LLTabContainer::getTopBorderHeight() const
{
return mTopBorderHeight;
}
void LLTabContainer::setRightTabBtnOffset(S32 offset)
{
Steven Bennetts
committed
mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 );
mRightTabBtnOffset = offset;
updateMaxScrollPos();
}
void LLTabContainer::setPanelTitle(S32 index, const std::string& title)
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
Steven Bennetts
committed
if (index >= 0 && index < getTabCount())
{
LLTabTuple* tuple = getTab(index);
LLButton* tab_button = tuple->mButton;
const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
Steven Bennetts
committed
mTotalTabWidth -= tab_button->getRect().getWidth();
tab_button->reshape(llclamp(fontp->getWidth(title) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
Steven Bennetts
committed
mTotalTabWidth += tab_button->getRect().getWidth();
tab_button->setLabelSelected(title);
tab_button->setLabelUnselected(title);
}
updateMaxScrollPos();
}
Steven Bennetts
committed
void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel )
Steven Bennetts
committed
{
LLTabTuple* tuple = getTabByPanel(panel);
selectTabPanel( panel );
Steven Bennetts
committed
Steven Bennetts
committed
}
void LLTabContainer::onNextBtn( const LLSD& data )
Steven Bennetts
committed
{
if (!mScrolled)
scrollNext();
mScrolled = FALSE;
Mnikolenko ProductEngine
committed
if(mCurrentTabIdx < mTabList.size()-1)
{
selectNextTab();
}
void LLTabContainer::onNextBtnHeld( const LLSD& data )
if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
Steven Bennetts
committed
{
mScrollTimer.reset();
scrollNext();
Mnikolenko ProductEngine
committed
if(mCurrentTabIdx < mTabList.size()-1)
{
selectNextTab();
}
mScrolled = TRUE;
Steven Bennetts
committed
}
}
void LLTabContainer::onPrevBtn( const LLSD& data )
Steven Bennetts
committed
{
if (!mScrolled)
Steven Bennetts
committed
{
scrollPrev();
mScrolled = FALSE;
Mnikolenko ProductEngine
committed
if(mCurrentTabIdx > 0)
{
selectPrevTab();
}
Steven Bennetts
committed
}
void LLTabContainer::onJumpFirstBtn( const LLSD& data )
Steven Bennetts
committed
{
mScrollPos = 0;
Steven Bennetts
committed
}
void LLTabContainer::onJumpLastBtn( const LLSD& data )
Steven Bennetts
committed
{
mScrollPos = mMaxScrollPos;
Steven Bennetts
committed
}
void LLTabContainer::onPrevBtnHeld( const LLSD& data )
Steven Bennetts
committed
{
if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
mScrollTimer.reset();
scrollPrev();
Mnikolenko ProductEngine
committed
if(mCurrentTabIdx > 0)
{
selectPrevTab();
}
mScrolled = TRUE;
Steven Bennetts
committed
// private
void LLTabContainer::initButtons()
Steven Bennetts
committed
// Hack:
if (getRect().getHeight() == 0 || mPrevArrowBtn)
Steven Bennetts
committed
return; // Don't have a rect yet or already got called
}
if (mIsVertical)
{
static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
Steven Bennetts
committed
// 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;
Steven Bennetts
committed
LLRect up_arrow_btn_rect;
up_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top, tabcntrv_arrow_btn_size, tabcntrv_arrow_btn_size );
Steven Bennetts
committed
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<LLButton>(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<LLButton>(next_btn_params);
Steven Bennetts
committed
}
else // Horizontal
{
static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
Steven Bennetts
committed
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;
Steven Bennetts
committed
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 );
Steven Bennetts
committed
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 );
Steven Bennetts
committed
S32 right_pad = tabcntr_arrow_btn_size + LLPANEL_BORDER_WIDTH + 1;
Steven Bennetts
committed
LLRect right_arrow_btn_rect;
right_arrow_btn_rect.setLeftTopAndSize( getRect().getWidth() - mRightTabBtnOffset - right_pad - tabcntr_arrow_btn_size,
Steven Bennetts
committed
btn_top + arrow_fudge,
tabcntr_arrow_btn_size, mTabHeight );
Steven Bennetts
committed
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 );
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
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<LLButton>(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<LLButton>(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<LLButton>(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<LLButton>(p);
Steven Bennetts
committed
if( getTabPosition() == TOP )
Steven Bennetts
committed
mNextArrowBtn->setFollowsTop();
mPrevArrowBtn->setFollowsTop();
mJumpPrevArrowBtn->setFollowsTop();
mJumpNextArrowBtn->setFollowsTop();
}
else
{
mNextArrowBtn->setFollowsBottom();
mPrevArrowBtn->setFollowsBottom();
mJumpPrevArrowBtn->setFollowsBottom();
mJumpNextArrowBtn->setFollowsBottom();
Steven Bennetts
committed
mPrevArrowBtn->setTabStop(FALSE);
addChild(mPrevArrowBtn);
Steven Bennetts
committed
mNextArrowBtn->setTabStop(FALSE);
addChild(mNextArrowBtn);
Steven Bennetts
committed
if (mJumpPrevArrowBtn)
Steven Bennetts
committed
mJumpPrevArrowBtn->setTabStop(FALSE);
addChild(mJumpPrevArrowBtn);
Steven Bennetts
committed
if (mJumpNextArrowBtn)
Steven Bennetts
committed
mJumpNextArrowBtn->setTabStop(FALSE);
addChild(mJumpNextArrowBtn);
Steven Bennetts
committed
// 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)
Steven Bennetts
committed
{
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
Steven Bennetts
committed
LLTabTuple* tuple = *iter;
if( tuple->mTabPanel == child )
Steven Bennetts
committed
return tuple;
Steven Bennetts
committed
return NULL;
}
Steven Bennetts
committed
void LLTabContainer::insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point)
{
switch(insertion_point)
Steven Bennetts
committed
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)
Steven Bennetts
committed
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);
Steven Bennetts
committed
break;
case END:
default:
mTabList.push_back( tuple );
Steven Bennetts
committed
void LLTabContainer::updateMaxScrollPos()
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
Steven Bennetts
committed
BOOL no_scroll = TRUE;
if (mIsVertical)
S32 tab_total_height = (BTN_HEIGHT + tabcntrv_pad) * getTabCount();
Steven Bennetts
committed
S32 available_height = getRect().getHeight() - getTopBorderHeight();
if( tab_total_height > available_height )
static LLUICachedControl<S32> tabcntrv_arrow_btn_size ("UITabCntrvArrowBtnSize", 0);
andreykproductengine
committed
S32 available_height_with_arrows = getRect().getHeight() - 2*(tabcntrv_arrow_btn_size + 3*tabcntrv_pad) - mNextArrowBtn->getRect().mBottom;
Steven Bennetts
committed
S32 additional_needed = tab_total_height - available_height_with_arrows;
andreykproductengine
committed
setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT + tabcntrv_pad) ) );
Steven Bennetts
committed
no_scroll = FALSE;
Steven Bennetts
committed
}
else
{
static LLUICachedControl<S32> tabcntr_tab_h_pad ("UITabCntrTabHPad", 0);
static LLUICachedControl<S32> tabcntr_arrow_btn_size ("UITabCntrArrowBtnSize", 0);
static LLUICachedControl<S32> tabcntr_tab_partial_width ("UITabCntrTabPartialWidth", 0);
Steven Bennetts
committed
S32 tab_space = 0;
S32 available_space = 0;
tab_space = mTotalTabWidth;
available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_tab_h_pad);
Steven Bennetts
committed
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);
Steven Bennetts
committed
// subtract off reserved portion on left
available_width_with_arrows -= tabcntr_tab_partial_width;
Steven Bennetts
committed
S32 running_tab_width = 0;
setMaxScrollPos(getTabCount());
for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it)
Steven Bennetts
committed
running_tab_width += (*tab_it)->mButton->getRect().getWidth();
if (running_tab_width > available_width_with_arrows)
{
break;
}
setMaxScrollPos(getMaxScrollPos()-1);
Steven Bennetts
committed
// in case last tab doesn't actually fit on screen, make it the last scrolling position
setMaxScrollPos(llmin(getMaxScrollPos(), getTabCount() - 1));
no_scroll = FALSE;
Steven Bennetts
committed
if (no_scroll)
{
setMaxScrollPos(0);
setScrollPos(0);
}
if (getScrollPos() > getMaxScrollPos())
{
setScrollPos(getMaxScrollPos()); // maybe just enforce this via limits in setScrollPos instead?
}
Steven Bennetts
committed
void LLTabContainer::commitHoveredButton(S32 x, S32 y)
{
{
Steven Bennetts
committed
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
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();
}
}
}
S32 LLTabContainer::getTotalTabWidth() const
{
return mTotalTabWidth;
}
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
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();
}