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