Newer
Older
Steven Bennetts
committed
* @brief LLTabContainer class
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
Richard Nelson
committed
Richard Nelson
committed
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;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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)
{}
LLTabContainer* mTabContainer;
LLPanel* mTabPanel;
LLButton* mButton;
BOOL mOldState;
LLTextBox* mPlaceholderText;
S32 mPadding;
};
//----------------------------------------------------------------------------
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_bottom_image_unselected("tab_bottom_image_unselected"),
tab_bottom_image_selected("tab_bottom_image_selected"),
tab_left_image_unselected("tab_left_image_unselected"),
tab_left_image_selected("tab_left_image_selected")
{}
LLTabContainer::Params::Params()
: tab_width("tab_width"),
tab_min_width("tab_min_width"),
tab_max_width("tab_max_width"),
tab_height("tab_height"),
tab_position("tab_position"),
hide_tabs("hide_tabs", false),
James Cook
committed
tab_padding_right("tab_padding_right"),
first_tab("first_tab"),
middle_tab("middle_tab"),
last_tab("last_tab")
{
name(std::string("tab_container"));
mouse_opaque = false;
}
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),
Steven Bennetts
committed
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical( p.tab_position == LEFT ),
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)
{
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;
}
Steven Bennetts
committed
initButtons( );
Steven Bennetts
committed
LLTabContainer::~LLTabContainer()
{
std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
}
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
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);
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
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<LLPanel*>(view);
if (panelp)
{
panelp->setSaveToXML(TRUE);
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)
S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + tabcntr_arrow_btn_size + tabcntr_arrow_btn_size + 1);
if (!mIsVertical)
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
Steven Bennetts
committed
{
if (cur_scroll_pos == 0)
{
break;
}
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, LLCriticalDamp::getInterpolant(0.08f)));
Steven Bennetts
committed
BOOL has_scroll_arrows = !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;
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.
gGL.pushMatrix();
gGL.translatef((F32)mPrevArrowBtn->getRect().mLeft, (F32)mPrevArrowBtn->getRect().mBottom, 0.f);
mPrevArrowBtn->draw();
gGL.popMatrix();
gGL.pushMatrix();
gGL.translatef((F32)mNextArrowBtn->getRect().mLeft, (F32)mNextArrowBtn->getRect().mBottom, 0.f);
mNextArrowBtn->draw();
gGL.popMatrix();
}
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;
BOOL has_scroll_arrows = (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();
if (tab_count > 0)
Steven Bennetts
committed
LLTabTuple* firsttuple = getTab(0);
LLRect tab_rect;
if (mIsVertical)
Steven Bennetts
committed
tab_rect = 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
{
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;
Steven Bennetts
committed
gFocusMgr.setMouseCapture(this);
tab_button->setFocus(TRUE);
Steven Bennetts
committed
return handled;
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
Steven Bennetts
committed
BOOL handled = FALSE;
BOOL has_scroll_arrows = (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;
BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
Steven Bennetts
committed
if (has_scroll_arrows)
{
Steven Bennetts
committed
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
handled = mJumpPrevArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
handled = mJumpNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
handled = mPrevArrowBtn->handleMouseUp(local_x, local_y, mask);
}
else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mNextArrowBtn->getRect().mLeft;
S32 local_y = y - mNextArrowBtn->getRect().mBottom;
handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask);
}
}
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);
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);
Steven Bennetts
committed
if (!handled && getTabCount() > 0)
Steven Bennetts
committed
LLTabTuple* firsttuple = getTab(0);
Steven Bennetts
committed
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
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)
{
LLTabTuple* tuple = *iter;
tuple->mButton->setVisible( TRUE );
S32 local_x = x - tuple->mButton->getRect().mLeft;
S32 local_y = y - tuple->mButton->getRect().mBottom;
James Cook
committed
handled = tuple->mButton->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
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
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)
Steven Bennetts
committed
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
Richard Nelson
committed
if( mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
Steven Bennetts
committed
if (has_scroll_arrows)
{
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
Steven Bennetts
committed
{
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))
Steven Bennetts
committed
{
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
Steven Bennetts
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();
mDragAndDropDelayTimer.stop();
}
}
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, 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));
}
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));
}
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));
}
}
}
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
{
tab_panel_rect = LLRect(mMinTabWidth + (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;
if (placeholder)
{
btn_rect.translate(0, -LLBUTTON_V_PAD-2);
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);
Steven Bennetts
committed
if (mIsVertical)
LLButton::Params p;
p.name(std::string("vert tab button"));
p.rect(btn_rect);
p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
p.label(trimmed_label);
p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
p.image_selected(mMiddleTabParams.tab_left_image_selected);
p.scale_image(true);
p.tab_stop(false);
Leyla Farazha
committed
p.label_shadow(false);
Steven Bennetts
committed
if (indent)
{
p.pad_left(indent);
Steven Bennetts
committed
}
btn = LLUICtrlFactory::create<LLButton>(p);
LLButton::Params p;
p.name(std::string(child->getName()) + " tab");
p.rect(btn_rect);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
p.label(trimmed_label);
p.visible(false);
p.scale_image(true);
p.image_unselected(tab_img);
p.image_selected(tab_selected_img);
p.tab_stop(false);
Leyla Farazha
committed
p.label_shadow(false);
Steven Bennetts
committed
// Try to squeeze in a bit more text
p.pad_left(4);
p.pad_right(2);
p.follows.flags = FOLLOWS_LEFT;
p.follows.flags = FOLLOWS_LEFT;
Steven Bennetts
committed
if (indent)
{
p.pad_left(indent);
Steven Bennetts
committed
}
if( getTabPosition() == TOP )
{
p.follows.flags = p.follows.flags() | FOLLOWS_TOP;
Steven Bennetts
committed
}
else
{
p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
Steven Bennetts
committed
}
++ btn = LLUICtrlFactory::create<LLButton>(p);
Steven Bennetts
committed
}
LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox );
Steven Bennetts
committed
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());
}
}