Newer
Older
Steven Bennetts
committed
* @brief LLTabContainer class
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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$
*/
#include "linden_common.h"
#include "lltabcontainer.h"
#include "llfocusmgr.h"
#include "llbutton.h"
#include "llrect.h"
#include "llresmgr.h"
#include "llresizehandle.h"
#include "lltextbox.h"
#include "llcriticaldamp.h"
#include "lluictrlfactory.h"
#include "lltabcontainervertical.h"
#include "llglimmediate.h"
const F32 SCROLL_DELAY_TIME = 0.5f;
const S32 TAB_PADDING = 15;
const S32 TABCNTR_TAB_MIN_WIDTH = 60;
Steven Bennetts
committed
const S32 TABCNTR_VERT_TAB_MIN_WIDTH = 100;
const S32 TABCNTR_TAB_MAX_WIDTH = 150;
const S32 TABCNTR_TAB_PARTIAL_WIDTH = 12; // When tabs are parially obscured, how much can you still see.
const S32 TABCNTR_TAB_HEIGHT = 16;
const S32 TABCNTR_ARROW_BTN_SIZE = 16;
const S32 TABCNTR_BUTTON_PANEL_OVERLAP = 1; // how many pixels the tab buttons and tab panels overlap.
const S32 TABCNTR_TAB_H_PAD = 4;
Steven Bennetts
committed
const S32 TABCNTR_CLOSE_BTN_SIZE = 16;
const S32 TABCNTR_HEADER_HEIGHT = LLPANEL_BORDER_WIDTH + TABCNTR_CLOSE_BTN_SIZE;
Steven Bennetts
committed
const S32 TABCNTRV_CLOSE_BTN_SIZE = 16;
const S32 TABCNTRV_HEADER_HEIGHT = LLPANEL_BORDER_WIDTH + TABCNTRV_CLOSE_BTN_SIZE;
//const S32 TABCNTRV_TAB_WIDTH = 100;
const S32 TABCNTRV_ARROW_BTN_SIZE = 16;
const S32 TABCNTRV_PAD = 0;
static LLRegisterWidget<LLTabContainer> r("tab_container");
Steven Bennetts
committed
LLTabContainer::LLTabContainer(const LLString& name, const LLRect& rect, TabPosition pos,
BOOL bordered, BOOL is_vertical )
:
LLPanel(name, rect, bordered),
mCurrentTabIdx(-1),
mScrolled(FALSE),
mScrollPos(0),
mScrollPosPixels(0),
mMaxScrollPos(0),
Steven Bennetts
committed
mCloseCallback( NULL ),
mCallbackUserdata( NULL ),
mTitleBox(NULL),
mTopBorderHeight(LLPANEL_BORDER_WIDTH),
mTabPosition(pos),
Steven Bennetts
committed
mLockedTabCount(0),
mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical(is_vertical),
// Horizontal Specific
mJumpPrevArrowBtn(NULL),
mJumpNextArrowBtn(NULL),
mRightTabBtnOffset(0),
mTotalTabWidth(0)
Steven Bennetts
committed
//RN: HACK to support default min width for legacy vertical tab containers
if (mIsVertical)
{
mMinTabWidth = TABCNTR_VERT_TAB_MIN_WIDTH;
}
Steven Bennetts
committed
initButtons( );
mDragAndDropDelayTimer.stop();
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 LLString& name, BOOL recurse, BOOL create_if_missing) 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, FALSE);
return LLView::getChildView(name, recurse, create_if_missing);
Steven Bennetts
committed
// virtual
void LLTabContainer::draw()
Steven Bennetts
committed
S32 target_pixel_scroll = 0;
S32 cur_scroll_pos = mIsVertical ? 0 : getScrollPos();
if (cur_scroll_pos > 0)
Steven Bennetts
committed
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;
}
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)));
BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
if (!mIsVertical)
mJumpPrevArrowBtn->setVisible( has_scroll_arrows );
mJumpNextArrowBtn->setVisible( has_scroll_arrows );
}
mPrevArrowBtn->setVisible( has_scroll_arrows );
mNextArrowBtn->setVisible( has_scroll_arrows );
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
S32 left = 0, top = 0;
if (mIsVertical)
{
top = getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1 - (has_scroll_arrows ? TABCNTRV_ARROW_BTN_SIZE : 0);
top += getScrollPosPixels();
}
else
{
// Set the leftmost position of the tab buttons.
left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD);
left -= getScrollPosPixels();
}
// Hide all the buttons
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
tuple->mButton->setVisible( FALSE );
}
LLPanel::draw();
// if tabs are hidden, don't draw them and leave them in the invisible state
if (!getTabsHidden())
{
// Show all the buttons
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
}
// Draw some of the buttons...
LLRect clip_rect = getLocalRect();
if (has_scroll_arrows)
Steven Bennetts
committed
{
// ...but clip them.
if (mIsVertical)
Steven Bennetts
committed
{
clip_rect.mBottom = mNextArrowBtn->getRect().mTop + 3*TABCNTRV_PAD;
clip_rect.mTop = mPrevArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD;
Steven Bennetts
committed
}
Steven Bennetts
committed
{
clip_rect.mLeft = mPrevArrowBtn->getRect().mRight;
clip_rect.mRight = mNextArrowBtn->getRect().mLeft;
Steven Bennetts
committed
}
}
LLLocalClipRect clip(clip_rect);
S32 max_scroll_visible = getTabCount() - getMaxScrollPos() + getScrollPos();
S32 idx = 0;
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
tuple->mButton->translate( left ? left - tuple->mButton->getRect().mLeft : 0,
top ? top - tuple->mButton->getRect().mTop : 0 );
if (top) top -= BTN_HEIGHT + TABCNTRV_PAD;
if (left) left += tuple->mButton->getRect().getWidth();
if (!mIsVertical)
{
if( idx < getScrollPos() )
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
}
}
LLUI::pushMatrix();
Steven Bennetts
committed
{
LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
tuple->mButton->draw();
Steven Bennetts
committed
}
LLUI::popMatrix();
idx++;
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 )
Steven Bennetts
committed
BOOL handled = FALSE;
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
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,
firsttuple->mButton->getRect().mRight,
has_scroll_arrows ? mNextArrowBtn->getRect().mTop + TABCNTRV_PAD : mNextArrowBtn->getRect().mBottom );
}
else
{
tab_rect = LLRect(has_scroll_arrows ? mPrevArrowBtn->getRect().mRight : mJumpPrevArrowBtn->getRect().mLeft,
firsttuple->mButton->getRect().mTop,
has_scroll_arrows ? mNextArrowBtn->getRect().mLeft : mJumpNextArrowBtn->getRect().mRight,
firsttuple->mButton->getRect().mBottom );
}
if( tab_rect.pointInRect( x, y ) )
{
S32 index = getCurrentPanelIndex();
index = llclamp(index, 0, tab_count-1);
LLButton* tab_button = getTab(index)->mButton;
Steven Bennetts
committed
gFocusMgr.setMouseCapture(this);
gFocusMgr.setKeyboardFocus(tab_button);
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);
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);
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
BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect )
Steven Bennetts
committed
BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
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,
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;
handled = tuple->mButton->handleToolTip( local_x, local_y, msg, sticky_rect );
if( handled )
{
break;
}
}
Steven Bennetts
committed
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
Steven Bennetts
committed
LLTabTuple* tuple = *iter;
tuple->mButton->setVisible( FALSE );
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
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
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
LLXMLNodePtr LLTabContainer::getXML(bool save_children) const
Steven Bennetts
committed
LLXMLNodePtr node = LLPanel::getXML();
node->createChild("tab_position", TRUE)->setStringValue((getTabPosition() == TOP ? "top" : "bottom"));
return node;
Steven Bennetts
committed
// virtual
BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, LLString &tooltip)
Steven Bennetts
committed
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
Steven Bennetts
committed
if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
Steven Bennetts
committed
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
if (has_scroll_arrows)
{
if (mJumpPrevArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
}
if (mJumpNextArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
mJumpNextArrowBtn->handleHover(local_x, local_y, mask);
}
if (mPrevArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
mPrevArrowBtn->handleHover(local_x, local_y, mask);
}
else if (mNextArrowBtn->getRect().pointInRect(x, y))
{
S32 local_x = x - mNextArrowBtn->getRect().mLeft;
S32 local_y = y - mNextArrowBtn->getRect().mBottom;
mNextArrowBtn->handleHover(local_x, local_y, mask);
}
}
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* child,
const LLString& label,
BOOL select,
void (*on_tab_clicked)(void*, bool),
void* userdata,
S32 indent,
BOOL placeholder,
eInsertionPoint insertion_point)
{
if (child->getParent() == this)
{
// already a child of mine
return;
}
const LLFontGL* font = LLResMgr::getInstance()->getRes( mIsVertical ? LLFONT_SANSSERIF : LLFONT_SANSSERIF_SMALL );
// Store the original label for possible xml export.
child->setLabel(label);
LLString trimmed_label = label;
LLString::trim(trimmed_label);
Steven Bennetts
committed
S32 button_width = mMinTabWidth;
if (!mIsVertical)
{
button_width = llclamp(font->getWidth(trimmed_label) + TAB_PADDING, mMinTabWidth, mMaxTabWidth);
}
// Tab panel
S32 tab_panel_top;
S32 tab_panel_bottom;
Steven Bennetts
committed
if( getTabPosition() == LLTabContainer::TOP )
Steven Bennetts
committed
S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT;
tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP);
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
}
else
{
Steven Bennetts
committed
tab_panel_top = getRect().getHeight() - getTopBorderHeight();
tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border
}
Steven Bennetts
committed
LLRect tab_panel_rect;
if (mIsVertical)
{
tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD,
getRect().getHeight() - LLPANEL_BORDER_WIDTH,
getRect().getWidth() - LLPANEL_BORDER_WIDTH,
LLPANEL_BORDER_WIDTH);
}
else
{
tab_panel_rect = LLRect(LLPANEL_BORDER_WIDTH,
tab_panel_top,
getRect().getWidth()-LLPANEL_BORDER_WIDTH,
tab_panel_bottom );
}
child->setFollowsAll();
child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
// add this child later
child->setVisible( FALSE ); // Will be made visible when selected
mTotalTabWidth += button_width;
// Tab button
LLRect btn_rect; // Note: btn_rect.mLeft is just a dummy. Will be updated in draw().
LLString tab_img;
LLString tab_selected_img;
S32 tab_fudge = 1; // To make new tab art look better, nudge buttons up 1 pel
Steven Bennetts
committed
if (mIsVertical)
Steven Bennetts
committed
btn_rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
(getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * getTabCount()),
mMinTabWidth,
BTN_HEIGHT);
}
else if( getTabPosition() == LLTabContainer::TOP )
{
btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
tab_img = "tab_top_blue.tga";
tab_selected_img = "tab_top_selected_blue.tga";
}
else
{
btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
tab_img = "tab_bottom_blue.tga";
tab_selected_img = "tab_bottom_selected_blue.tga";
Steven Bennetts
committed
LLTextBox* textbox = NULL;
LLButton* btn = NULL;
if (placeholder)
{
btn_rect.translate(0, -LLBUTTON_V_PAD-2);
Steven Bennetts
committed
textbox = new LLTextBox(trimmed_label, btn_rect, trimmed_label, font);
btn = new LLButton("", LLRect(0,0,0,0));
Steven Bennetts
committed
if (mIsVertical)
Steven Bennetts
committed
btn = new LLButton("vert tab button",
btn_rect,
"",
"",
"",
&LLTabContainer::onTabBtn, NULL,
font,
trimmed_label, trimmed_label);
btn->setImages("tab_left.tga", "tab_left_selected.tga");
btn->setScaleImage(TRUE);
btn->setHAlign(LLFontGL::LEFT);
btn->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT);
btn->setTabStop(FALSE);
if (indent)
{
btn->setLeftHPad(indent);
}
Steven Bennetts
committed
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
LLString tooltip = trimmed_label;
tooltip += "\nAlt-Left arrow for previous tab";
tooltip += "\nAlt-Right arrow for next tab";
btn = new LLButton(LLString(child->getName()) + " tab",
btn_rect,
"", "", "",
&LLTabContainer::onTabBtn, NULL, // set userdata below
font,
trimmed_label, trimmed_label );
btn->setVisible( FALSE );
btn->setToolTip( tooltip );
btn->setScaleImage(TRUE);
btn->setImages(tab_img, tab_selected_img);
// Try to squeeze in a bit more text
btn->setLeftHPad( 4 );
btn->setRightHPad( 2 );
btn->setHAlign(LLFontGL::LEFT);
btn->setTabStop(FALSE);
if (indent)
{
btn->setLeftHPad(indent);
}
if( getTabPosition() == TOP )
{
btn->setFollowsTop();
}
else
{
btn->setFollowsBottom();
}
Steven Bennetts
committed
}
LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, textbox );
insertTuple( tuple, insertion_point );
Steven Bennetts
committed
if (textbox)
{
textbox->setSaveToXML(false);
addChild( textbox, 0 );
}
if (btn)
{
btn->setSaveToXML(false);
btn->setCallbackUserData( tuple );
addChild( btn, 0 );
}
Steven Bennetts
committed
if (child)
{
addChild(child, 1);
}
Steven Bennetts
committed
updateMaxScrollPos();
}
void LLTabContainer::addPlaceholder(LLPanel* child, const LLString& label)
{
addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
}
void LLTabContainer::removeTabPanel(LLPanel* child)
{
Steven Bennetts
committed
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
if (mIsVertical)
{
// Fix-up button sizes
S32 tab_count = 0;
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
LLRect rect;
rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor
(getRect().getHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * (tab_count)),
mMinTabWidth,
BTN_HEIGHT);
if (tuple->mPlaceholderText)
{
tuple->mPlaceholderText->setRect(rect);
}
else
{
tuple->mButton->setRect(rect);
}
tab_count++;
}
}
else
{
// Adjust the total tab width.
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
if( tuple->mTabPanel == child )
{
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
break;
}
}
}
BOOL has_focus = gFocusMgr.childHasKeyboardFocus(this);
// If the tab being deleted is the selected one, select a different tab.
for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
if( tuple->mTabPanel == child )
{
Steven Bennetts
committed
removeChild( tuple->mButton );
delete tuple->mButton;
removeChild( tuple->mTabPanel );
// delete tuple->mTabPanel;
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);
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
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
removeChild( tuple->mButton );
delete tuple->mButton;
removeChild( tuple->mTabPanel );
// delete tuple->mTabPanel;
}
// 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;
}