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
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;
58
59
60
61
62
63
64
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
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;
};
//----------------------------------------------------------------------------
//============================================================================
/*
* @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():
Ychebotarev ProductEngine
committed
icon_ctrl_pad("icon_ctrl_pad", 1)
{}
};
protected:
friend class LLUICtrlFactory;
LLCustomButtonIconCtrl(const Params& p):
LLButton(p),
mIcon(NULL),
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),
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),
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 ),
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),
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;
}
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);
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
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)
{
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.
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;
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();
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);
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);
Richard Linden
committed
if (!handled && getTabCount() > 0 && !getTabsHidden())
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
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
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);
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
825
826
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
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, 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