Example #1
0
void LLTabContainer::updateMaxScrollPos()
{
	BOOL no_scroll = TRUE;
	if (mIsVertical)
	{
		S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount();
		S32 available_height = getRect().getHeight() - getTopBorderHeight();
		if( tab_total_height > available_height )
		{
			S32 available_height_with_arrows = getRect().getHeight() - 2*(TABCNTRV_ARROW_BTN_SIZE + 3*TABCNTRV_PAD);
			S32 additional_needed = tab_total_height - available_height_with_arrows;
			setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) );
			no_scroll = FALSE;
		}
	}
	else
	{
		S32 tab_space = 0;
		S32 available_space = 0;
		tab_space = mTotalTabWidth;
		available_space = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_TAB_H_PAD);

		if( tab_space > available_space )
		{
			S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE  + TABCNTR_ARROW_BTN_SIZE + 1);
			// subtract off reserved portion on left
			available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH;

			S32 running_tab_width = 0;
			setMaxScrollPos(getTabCount());
			for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it)
			{
				running_tab_width += (*tab_it)->mButton->getRect().getWidth();
				if (running_tab_width > available_width_with_arrows)
				{
					break;
				}
				setMaxScrollPos(getMaxScrollPos()-1);
			}
			// in case last tab doesn't actually fit on screen, make it the last scrolling position
			setMaxScrollPos(llmin(getMaxScrollPos(), getTabCount() - 1));
			no_scroll = FALSE;
		}
	}
	if (no_scroll)
	{
		setMaxScrollPos(0);
		setScrollPos(0);
	}
	if (getScrollPos() > getMaxScrollPos())
	{
		setScrollPos(getMaxScrollPos()); // maybe just enforce this via limits in setScrollPos instead?
	}
}
Example #2
0
/*************************************************************************
Add a new tab
*************************************************************************/
void TabControl::addTab(Window* wnd)
{
    // abort attempts to add null window pointers, but log it for tracking.
    if (!wnd)
    {
        Logger::getSingleton().logEvent("Attempt to add null window pointer as "
            "tab to TabControl '" + getName() + "'.  Ignoring!", Informative);

        return;
    }

    // Create a new TabButton
    addButtonForTabContent(wnd);
    // Add the window to the content pane
    getTabPane()->addChildWindow(wnd);
    // Auto-select?
    if (getTabCount() == 1)
        setSelectedTab(wnd->getName());
    else
        // initialise invisible content
        wnd->setVisible(false);

	// when adding the 1st page, autosize tab pane height
    if (d_tabHeight.d_scale == 0 && d_tabHeight.d_offset == -1)
        d_tabHeight.d_offset = 8 + getFont()->getFontHeight ();

    // Just request redraw
    performChildWindowLayout();
    invalidate();
    // Subscribe to text changed event so that we can resize as needed
    d_eventConnections[wnd] =
        wnd->subscribeEvent(Window::EventTextChanged,
            Event::Subscriber(&TabControl::handleContentWindowTextChanged,
                              this));
}
Example #3
0
BOOL LLTabContainer::selectTab(S32 which)
{
	if (which >= getTabCount()) return FALSE;
	if (which < 0) return FALSE;

	//if( gFocusMgr.childHasKeyboardFocus( this ) )
	//{
	//	gFocusMgr.setKeyboardFocus( NULL );
	//}

	LLTabTuple* selected_tuple = getTab(which);
	if (!selected_tuple)
	{
		return FALSE;
	}

	if (!selected_tuple->mPrecommitChangeCallback)
	{
		return setTab(which);
	}

	mNextTabIdx = which;
	selected_tuple->mPrecommitChangeCallback(selected_tuple->mUserData, false);
	return TRUE;
}
Example #4
0
/*************************************************************************
Remove a tab by ID
*************************************************************************/
void TabControl::removeTab(uint ID)
{
    // do nothing if given window is not attached as a tab.
    if (!d_tabContentPane->isChild(ID))
        return;

    Window* wnd = d_tabContentPane->getChild(ID);
    // Was this selected?
    bool reselect = wnd->isVisible();
    // Tab buttons are the 2nd onward children
    d_tabContentPane->removeChildWindow(ID);

    // remove button too
    removeButtonForTabContent(wnd);

    if (reselect)
    {
        // Select another tab
        if (getTabCount() > 0)
        {
            setSelectedTab(d_tabContentPane->getChildAtIdx(0)->getName());
        }
    }

    performChildWindowLayout();

    requestRedraw();

}
Example #5
0
int TabControl::writeChildWindowsXML(XMLSerializer& xml_stream) const
{
    int childOutputCount = Window::writeChildWindowsXML(xml_stream);

    // since TabControl content is actually added to the component tab
    // content pane window, this overridden function exists to dump those
    // out as if they were our own children.
    for (size_t i = 0; i < getTabCount(); ++i)
    {
        getTabContentsAtIndex(i)->writeXMLToStream(xml_stream);
        ++childOutputCount;
    }

    return childOutputCount;
}
Example #6
0
void LLTabContainer::setPanelTitle(S32 index, const std::string& title)
{
	if (index >= 0 && index < getTabCount())
	{
		LLTabTuple* tuple = getTab(index);
		LLButton* tab_button = tuple->mButton;
		const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
		mTotalTabWidth -= tab_button->getRect().getWidth();
		tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
		mTotalTabWidth += tab_button->getRect().getWidth();
		tab_button->setLabelSelected(title);
		tab_button->setLabelUnselected(title);
	}
	updateMaxScrollPos();
}
Example #7
0
// virtual
BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect )
{
	BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
	if (!handled && getTabCount() > 0) 
	{
		LLTabTuple* firsttuple = getTab(0);

		BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
		LLRect clip;
		if (mIsVertical)
		{
			clip = LLRect(firsttuple->mButton->getRect().mLeft,
						  has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - TABCNTRV_PAD : mPrevArrowBtn->getRect().mTop,
						  firsttuple->mButton->getRect().mRight,
						  has_scroll_arrows ? mNextArrowBtn->getRect().mTop + TABCNTRV_PAD : mNextArrowBtn->getRect().mBottom );
		}
		else
		{
			clip = LLRect(has_scroll_arrows ? mPrevArrowBtn->getRect().mRight : mJumpPrevArrowBtn->getRect().mLeft,
						  firsttuple->mButton->getRect().mTop,
						  has_scroll_arrows ? mNextArrowBtn->getRect().mLeft : mJumpNextArrowBtn->getRect().mRight,
						  firsttuple->mButton->getRect().mBottom );
		}

		if( clip.pointInRect( x, y ) )
		{
			for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
			{
				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;
				}
			}
		}

		for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
		{
			LLTabTuple* tuple = *iter;
			tuple->mButton->setVisible( FALSE );
		}
	}
	return handled;
}
Example #8
0
void TabControl::removeTab_impl(Window* window)
{
    // silently abort if window to be removed is 0.
    if (!window)
        return;

    // delete connection to event we subscribed earlier
    d_eventConnections.erase(window);
    // Was this selected?
    bool reselect = window->isVisible();
    // Tab buttons are the 2nd onward children
    getTabPane()->removeChildWindow(window);

    // remove button too
    removeButtonForTabContent(window);

    if (reselect && (getTabCount() > 0))
        // Select another tab
        setSelectedTab(getTabPane()->getChildAtIdx(0)->getName());

    performChildWindowLayout();

    invalidate();
}
Example #9
0
/*************************************************************************
Add a new tab
*************************************************************************/
void TabControl::addTab(Window* wnd)
{
    // Create a new TabButton
    addButtonForTabContent(wnd);
    // Add the window to the content pane
    d_tabContentPane->addChildWindow(wnd);
    // Auto-select?
    if (getTabCount() == 1)
    {
        setSelectedTab(wnd->getName());
    }
    else
    {
        // initialise invisible content
        wnd->setVisible(false);
    }
    // Just request redraw
    performChildWindowLayout();
    requestRedraw();
    // Subscribe to text changed event so that we can resize as needed
    wnd->subscribeEvent(Window::EventTextChanged, 
        Event::Subscriber(&TabControl::handleContentWindowTextChanged, this));

}
Example #10
0
void LLTabContainer::lockTabs(S32 num_tabs)
{
	// count current tabs or use supplied value and ensure no new tabs get
	// inserted between them
	mLockedTabCount = num_tabs > 0 ? llmin(getTabCount(), num_tabs) : getTabCount();
}
Example #11
0
void LLTabContainer::removeTabPanel(LLPanel* child)
{
	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 )
		{
 			removeChild( tuple->mButton );
 			delete tuple->mButton;

 			removeChild( tuple->mTabPanel );
// 			delete tuple->mTabPanel;
			
			mTabList.erase( iter );
			delete tuple;

			break;
		}
	}

	// make sure we don't have more locked tabs than we have tabs
	mLockedTabCount = llmin(getTabCount(), mLockedTabCount);

	if (mCurrentTabIdx >= (S32)mTabList.size())
	{
		mCurrentTabIdx = mTabList.size()-1;
	}
	selectTab(mCurrentTabIdx);
	if (has_focus)
	{
		LLPanel* panelp = getPanelByIndex(mCurrentTabIdx);
		if (panelp)
		{
			panelp->setFocus(TRUE);
		}
	}

	updateMaxScrollPos();
}
Example #12
0
void LLTabContainer::addTabPanel(LLPanel* child, 
								 const std::string& 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);
	std::string trimmed_label = label;
	LLStringUtil::trim(trimmed_label);

	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;
	if( getTabPosition() == LLTabContainer::TOP )
	{
		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
	{
		tab_panel_top = getRect().getHeight() - getTopBorderHeight();
		tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP);  // Run to the edge, covering up the border
	}
	
	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().
	std::string tab_img;
	std::string tab_selected_img;
	S32 tab_fudge = 1;		//  To make new tab art look better, nudge buttons up 1 pel

	if (mIsVertical)
	{
		btn_rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2,	// JC - Fudge factor
								   (getRect().getHeight() - getTopBorderHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * getTabCount()),
								   mMinTabWidth,
								   BTN_HEIGHT);
	}
	else if( getTabPosition() == LLTabContainer::TOP )
	{
		btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, 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";
	}

	LLTextBox* textbox = NULL;
	LLButton* btn = NULL;
	
	if (placeholder)
	{
		btn_rect.translate(0, -LLBUTTON_V_PAD-2);
		textbox = new LLTextBox(trimmed_label, btn_rect, trimmed_label, font);
		
		btn = new LLButton(LLStringUtil::null, LLRect(0,0,0,0));
	}
	else
	{
		if (mIsVertical)
		{
			btn = new LLButton(std::string("vert tab button"),
							   btn_rect,
							   LLStringUtil::null,
							   LLStringUtil::null, 
							   LLStringUtil::null, 
							   &LLTabContainer::onTabBtn, NULL,
							   font,
							   trimmed_label, trimmed_label);
			btn->setImages(std::string("tab_left.tga"), std::string("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);
			}
		}
		else
		{
			std::string tooltip = trimmed_label;
			tooltip += "\nAlt-Left arrow for previous tab";
			tooltip += "\nAlt-Right arrow for next tab";

			btn = new LLButton(std::string(child->getName()) + " tab",
							   btn_rect, 
							   LLStringUtil::null, LLStringUtil::null, LLStringUtil::null,
							   &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();
			}
		}
	}
	
	LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, textbox );
	insertTuple( tuple, insertion_point );

	if (textbox)
	{
		textbox->setSaveToXML(false);
		addChild( textbox, 0 );
	}
	if (btn)
	{
		btn->setSaveToXML(false);
		btn->setCallbackUserData( tuple );
		addChild( btn, 0 );
	}
	if (child)
	{
		addChild(child, 1);
	}
	
	if( select )
	{
		selectLastTab();
	}

	updateMaxScrollPos();
}
Example #13
0
// virtual
BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
{
	BOOL handled = FALSE;
	BOOL has_scroll_arrows = (getMaxScrollPos() > 0);

	if (has_scroll_arrows)
	{
		if (mJumpPrevArrowBtn&& mJumpPrevArrowBtn->getRect().pointInRect(x, y))
		{
			S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
			S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
			handled = mJumpPrevArrowBtn->handleMouseDown(local_x, local_y, mask);
		}
		else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
		{
			S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
			S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
			handled = mJumpNextArrowBtn->handleMouseDown(local_x, local_y, mask);
		}
		else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y))
		{
			S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
			S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
			handled = mPrevArrowBtn->handleMouseDown(local_x, local_y, mask);
		}
		else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y))
		{
			S32 local_x = x - mNextArrowBtn->getRect().mLeft;
			S32 local_y = y - mNextArrowBtn->getRect().mBottom;
			handled = mNextArrowBtn->handleMouseDown(local_x, local_y, mask);
		}
	}
	if (!handled)
	{
		handled = LLPanel::handleMouseDown( x, y, mask );
	}

	S32 tab_count = getTabCount();
	if (tab_count > 0)
	{
		LLTabTuple* firsttuple = getTab(0);
		LLRect tab_rect;
		if (mIsVertical)
		{
			tab_rect = LLRect(firsttuple->mButton->getRect().mLeft,
							  has_scroll_arrows ? mPrevArrowBtn->getRect().mBottom - TABCNTRV_PAD : mPrevArrowBtn->getRect().mTop,
							  firsttuple->mButton->getRect().mRight,
							  has_scroll_arrows ? mNextArrowBtn->getRect().mTop + TABCNTRV_PAD : mNextArrowBtn->getRect().mBottom );
		}
		else
		{
			tab_rect = LLRect(has_scroll_arrows ? mPrevArrowBtn->getRect().mRight : mJumpPrevArrowBtn->getRect().mLeft,
							  firsttuple->mButton->getRect().mTop,
							  has_scroll_arrows ? mNextArrowBtn->getRect().mLeft : mJumpNextArrowBtn->getRect().mRight,
							  firsttuple->mButton->getRect().mBottom );
		}
		if( tab_rect.pointInRect( x, y ) )
		{
			S32 index = getCurrentPanelIndex();
			index = llclamp(index, 0, tab_count-1);
			LLButton* tab_button = getTab(index)->mButton;
			gFocusMgr.setMouseCapture(this);
			gFocusMgr.setKeyboardFocus(tab_button);
		}
	}
	return handled;
}
Example #14
0
// virtual
void LLTabContainer::draw()
{
	S32 target_pixel_scroll = 0;
	S32 cur_scroll_pos = getScrollPos();
	if (cur_scroll_pos > 0)
	{
		if (!mIsVertical)
		{
			S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE  + TABCNTR_ARROW_BTN_SIZE + 1);
			for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
			{
				if (cur_scroll_pos == 0)
				{
					break;
				}
				target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
				cur_scroll_pos--;
			}

			// Show part of the tab to the left of what is fully visible
			target_pixel_scroll -= TABCNTR_TAB_PARTIAL_WIDTH;
			// clamp so that rightmost tab never leaves right side of screen
			target_pixel_scroll = llmin(mTotalTabWidth - available_width_with_arrows, target_pixel_scroll);
		}
		else
		{
			S32 available_height_with_arrows = getRect().getHeight() - getTopBorderHeight() - (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
			for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
			{
				if (cur_scroll_pos==0)
				{
					break;
				}
				target_pixel_scroll += (*iter)->mButton->getRect().getHeight();
				cur_scroll_pos--;
			}
			S32 total_tab_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount() + TABCNTRV_PAD;
			// clamp so that the bottom tab never leaves bottom of panel
			target_pixel_scroll = llmin(total_tab_height - available_height_with_arrows, target_pixel_scroll);
		}
	}

	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 );

	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
		for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
		{
			LLTabTuple* tuple = *iter;
			tuple->mButton->setVisible( TRUE );
		}

		// Draw some of the buttons...
		LLRect clip_rect = getLocalRect();
		if (has_scroll_arrows)
		{
			// ...but clip them.
			if (mIsVertical)
			{
				clip_rect.mBottom = mNextArrowBtn->getRect().mTop + 3*TABCNTRV_PAD;
				clip_rect.mTop = mPrevArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD;
			}
			else
			{
				clip_rect.mLeft = mPrevArrowBtn->getRect().mRight;
				clip_rect.mRight = mNextArrowBtn->getRect().mLeft;
			}
		}
		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() )
				{
					if( tuple->mButton->getFlashing() )
					{
						mPrevArrowBtn->setFlashing( TRUE );
					}
				}
				else if( max_scroll_visible < idx )
				{
					if( tuple->mButton->getFlashing() )
					{
						mNextArrowBtn->setFlashing( TRUE );
					}
				}
			}
			LLUI::pushMatrix();
			{
				LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
				tuple->mButton->draw();
			}
			LLUI::popMatrix();

			idx++;
		}


		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();
		}
	}

	mPrevArrowBtn->setFlashing(FALSE);
	mNextArrowBtn->setFlashing(FALSE);
}
Example #15
0
BOOL LLTabContainer::setTab(S32 which)
{
	if (which == -1)
	{
		if (mNextTabIdx == -1)
		{
			return FALSE;
		}
		which = mNextTabIdx;
		mNextTabIdx = -1;
	}

	LLTabTuple* selected_tuple = getTab(which);
	if (!selected_tuple)
	{
		return FALSE;
	}

	BOOL is_visible = FALSE;
	if (selected_tuple->mButton->getEnabled())
	{
		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 );
			tuple->mTabPanel->setVisible( is_selected );
// 			tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
			tuple->mButton->setToggleState( is_selected );
			// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
			tuple->mButton->setTabStop( is_selected );
			
			if( is_selected && (mIsVertical || (getMaxScrollPos() > 0)))
			{
				// Make sure selected tab is within scroll region
				if (mIsVertical)
				{
					S32 num_visible = getTabCount() - getMaxScrollPos();
					if( i >= getScrollPos() && i <= getScrollPos() + num_visible)
					{
						setCurrentPanelIndex(which);
						is_visible = TRUE;
					}
					else
					{
						is_visible = FALSE;
					}
				}
				else
				{
					if( i < getScrollPos() )
					{
						setScrollPos(i);
					}
					else
					{
						S32 available_width_with_arrows = getRect().getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE  + TABCNTR_ARROW_BTN_SIZE + 1);
						S32 running_tab_width = tuple->mButton->getRect().getWidth();
						S32 j = i - 1;
						S32 min_scroll_pos = i;
						if (running_tab_width < available_width_with_arrows)
						{
							while (j >= 0)
							{
								LLTabTuple* other_tuple = getTab(j);
								running_tab_width += other_tuple->mButton->getRect().getWidth();
								if (running_tab_width > available_width_with_arrows)
								{
									break;
								}
								j--;
							}
							min_scroll_pos = j + 1;
						}
						setScrollPos(llclamp(getScrollPos(), min_scroll_pos, i));
						setScrollPos(llmin(getScrollPos(), getMaxScrollPos()));
					}
					is_visible = TRUE;
				}
			}
			i++;
		}
		if( selected_tuple->mOnChangeCallback )
		{
			selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false );
		}
	}
	if (mIsVertical && getCurrentPanelIndex() >= 0)
	{
		LLTabTuple* tuple = getTab(getCurrentPanelIndex());
		tuple->mTabPanel->setVisible( TRUE );
		tuple->mButton->setToggleState( TRUE );
	}
	return is_visible;
}