00001
00032 #include "linden_common.h"
00033
00034 #include "lltabcontainer.h"
00035
00036 #include "llfocusmgr.h"
00037 #include "llfontgl.h"
00038 #include "llgl.h"
00039
00040 #include "llbutton.h"
00041 #include "llrect.h"
00042 #include "llpanel.h"
00043 #include "llresmgr.h"
00044 #include "llkeyboard.h"
00045 #include "llresizehandle.h"
00046 #include "llui.h"
00047 #include "lltextbox.h"
00048 #include "llcontrol.h"
00049 #include "llcriticaldamp.h"
00050 #include "lluictrlfactory.h"
00051
00052 #include "lltabcontainervertical.h"
00053
00054 #include "llglheaders.h"
00055
00056 const F32 SCROLL_STEP_TIME = 0.4f;
00057 const F32 SCROLL_DELAY_TIME = 0.5f;
00058 const S32 TAB_PADDING = 15;
00059 const S32 TABCNTR_TAB_MIN_WIDTH = 60;
00060 const S32 TABCNTR_TAB_MAX_WIDTH = 150;
00061 const S32 TABCNTR_TAB_PARTIAL_WIDTH = 12;
00062 const S32 TABCNTR_TAB_HEIGHT = 16;
00063 const S32 TABCNTR_ARROW_BTN_SIZE = 16;
00064 const S32 TABCNTR_BUTTON_PANEL_OVERLAP = 1;
00065 const S32 TABCNTR_TAB_H_PAD = 4;
00066
00067
00068 LLTabContainerCommon::LLTabContainerCommon(
00069 const LLString& name, const LLRect& rect,
00070 TabPosition pos,
00071 void(*close_callback)(void*), void* callback_userdata,
00072 BOOL bordered )
00073 :
00074 LLPanel(name, rect, bordered),
00075 mCurrentTabIdx(-1),
00076 mTabsHidden(FALSE),
00077 mScrolled(FALSE),
00078 mScrollPos(0),
00079 mScrollPosPixels(0),
00080 mMaxScrollPos(0),
00081 mCloseCallback( close_callback ),
00082 mCallbackUserdata( callback_userdata ),
00083 mTitleBox(NULL),
00084 mTopBorderHeight(LLPANEL_BORDER_WIDTH),
00085 mTabPosition(pos),
00086 mLockedTabCount(0)
00087 {
00088 setMouseOpaque(FALSE);
00089 mDragAndDropDelayTimer.stop();
00090 }
00091
00092
00093 LLTabContainerCommon::LLTabContainerCommon(
00094 const LLString& name,
00095 const LLString& rect_control,
00096 TabPosition pos,
00097 void(*close_callback)(void*), void* callback_userdata,
00098 BOOL bordered )
00099 :
00100 LLPanel(name, rect_control, bordered),
00101 mCurrentTabIdx(-1),
00102 mTabsHidden(FALSE),
00103 mScrolled(FALSE),
00104 mScrollPos(0),
00105 mScrollPosPixels(0),
00106 mMaxScrollPos(0),
00107 mCloseCallback( close_callback ),
00108 mCallbackUserdata( callback_userdata ),
00109 mTitleBox(NULL),
00110 mTopBorderHeight(LLPANEL_BORDER_WIDTH),
00111 mTabPosition(pos),
00112 mLockedTabCount(0)
00113 {
00114 setMouseOpaque(FALSE);
00115 mDragAndDropDelayTimer.stop();
00116 }
00117
00118
00119 LLTabContainerCommon::~LLTabContainerCommon()
00120 {
00121 std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
00122 }
00123
00124 LLView* LLTabContainerCommon::getChildByName(const LLString& name, BOOL recurse) const
00125 {
00126 tuple_list_t::const_iterator itor;
00127 for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
00128 {
00129 LLPanel *panel = (*itor)->mTabPanel;
00130 if (panel->getName() == name)
00131 {
00132 return panel;
00133 }
00134 }
00135 if (recurse)
00136 {
00137 for (itor = mTabList.begin(); itor != mTabList.end(); ++itor)
00138 {
00139 LLPanel *panel = (*itor)->mTabPanel;
00140 LLView *child = panel->getChildByName(name, recurse);
00141 if (child)
00142 {
00143 return child;
00144 }
00145 }
00146 }
00147 return LLView::getChildByName(name, recurse);
00148 }
00149
00150 void LLTabContainerCommon::addPlaceholder(LLPanel* child, const LLString& label)
00151 {
00152 addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
00153 }
00154
00155 void LLTabContainerCommon::lockTabs(S32 num_tabs)
00156 {
00157
00158
00159 mLockedTabCount = num_tabs > 0 ? num_tabs : getTabCount();
00160 }
00161
00162 void LLTabContainerCommon::removeTabPanel(LLPanel* child)
00163 {
00164 BOOL has_focus = gFocusMgr.childHasKeyboardFocus(this);
00165
00166
00167 for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
00168 {
00169 LLTabTuple* tuple = *iter;
00170 if( tuple->mTabPanel == child )
00171 {
00172 removeChild( tuple->mButton );
00173 delete tuple->mButton;
00174
00175 removeChild( tuple->mTabPanel );
00176
00177
00178 mTabList.erase( iter );
00179 delete tuple;
00180
00181 break;
00182 }
00183 }
00184
00185
00186 mLockedTabCount = llmin(getTabCount(), mLockedTabCount);
00187
00188 if (mCurrentTabIdx >= (S32)mTabList.size())
00189 {
00190 mCurrentTabIdx = mTabList.size()-1;
00191 }
00192 selectTab(mCurrentTabIdx);
00193 if (has_focus)
00194 {
00195 LLPanel* panelp = getPanelByIndex(mCurrentTabIdx);
00196 if (panelp)
00197 {
00198 panelp->setFocus(TRUE);
00199 }
00200 }
00201
00202 updateMaxScrollPos();
00203 }
00204
00205 void LLTabContainerCommon::deleteAllTabs()
00206 {
00207
00208 for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
00209 {
00210 LLTabTuple* tuple = *iter;
00211
00212 removeChild( tuple->mButton );
00213 delete tuple->mButton;
00214
00215 removeChild( tuple->mTabPanel );
00216
00217 }
00218
00219
00220 std::for_each(mTabList.begin(), mTabList.end(), DeletePointer());
00221 mTabList.clear();
00222
00223
00224 mCurrentTabIdx = -1;
00225 }
00226
00227
00228 LLPanel* LLTabContainerCommon::getCurrentPanel()
00229 {
00230 if (mCurrentTabIdx < 0 || mCurrentTabIdx >= (S32) mTabList.size()) return NULL;
00231
00232 return mTabList[mCurrentTabIdx]->mTabPanel;
00233 }
00234
00235 LLTabContainerCommon::LLTabTuple* LLTabContainerCommon::getTabByPanel(LLPanel* child)
00236 {
00237 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
00238 {
00239 LLTabTuple* tuple = *iter;
00240 if( tuple->mTabPanel == child )
00241 {
00242 return tuple;
00243 }
00244 }
00245 return NULL;
00246 }
00247
00248 void LLTabContainerCommon::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*, bool))
00249 {
00250 LLTabTuple* tuplep = getTabByPanel(tab);
00251 if (tuplep)
00252 {
00253 tuplep->mOnChangeCallback = on_tab_clicked;
00254 }
00255 }
00256
00257 void LLTabContainerCommon::setTabUserData(LLPanel* tab, void* userdata)
00258 {
00259 LLTabTuple* tuplep = getTabByPanel(tab);
00260 if (tuplep)
00261 {
00262 tuplep->mUserData = userdata;
00263 }
00264 }
00265
00266 S32 LLTabContainerCommon::getCurrentPanelIndex()
00267 {
00268 return mCurrentTabIdx;
00269 }
00270
00271 S32 LLTabContainerCommon::getTabCount()
00272 {
00273 return mTabList.size();
00274 }
00275
00276 LLPanel* LLTabContainerCommon::getPanelByIndex(S32 index)
00277 {
00278 if (index >= 0 && index < (S32)mTabList.size())
00279 {
00280 return mTabList[index]->mTabPanel;
00281 }
00282 return NULL;
00283 }
00284
00285 S32 LLTabContainerCommon::getIndexForPanel(LLPanel* panel)
00286 {
00287 for (S32 index = 0; index < (S32)mTabList.size(); index++)
00288 {
00289 if (mTabList[index]->mTabPanel == panel)
00290 {
00291 return index;
00292 }
00293 }
00294 return -1;
00295 }
00296
00297 S32 LLTabContainerCommon::getPanelIndexByTitle(const LLString& title)
00298 {
00299 for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
00300 {
00301 if (title == mTabList[index]->mButton->getLabelSelected())
00302 {
00303 return index;
00304 }
00305 }
00306 return -1;
00307 }
00308
00309 LLPanel *LLTabContainerCommon::getPanelByName(const LLString& name)
00310 {
00311 for (S32 index = 0 ; index < (S32)mTabList.size(); index++)
00312 {
00313 LLPanel *panel = mTabList[index]->mTabPanel;
00314 if (name == panel->getName())
00315 {
00316 return panel;
00317 }
00318 }
00319 return NULL;
00320 }
00321
00322
00323 void LLTabContainerCommon::scrollNext()
00324 {
00325
00326 if( mScrollPos < mMaxScrollPos )
00327 {
00328 mScrollPos++;
00329 }
00330 }
00331
00332 void LLTabContainerCommon::scrollPrev()
00333 {
00334
00335 if( mScrollPos > 0 )
00336 {
00337 mScrollPos--;
00338 }
00339 }
00340
00341 void LLTabContainerCommon::enableTabButton(S32 which, BOOL enable)
00342 {
00343 if (which >= 0 && which < (S32)mTabList.size())
00344 {
00345 mTabList[which]->mButton->setEnabled(enable);
00346 }
00347 }
00348
00349 BOOL LLTabContainerCommon::selectTabPanel(LLPanel* child)
00350 {
00351 S32 idx = 0;
00352 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
00353 {
00354 LLTabTuple* tuple = *iter;
00355 if( tuple->mTabPanel == child )
00356 {
00357 return selectTab( idx );
00358 }
00359 idx++;
00360 }
00361 return FALSE;
00362 }
00363
00364 BOOL LLTabContainerCommon::selectTabByName(const LLString& name)
00365 {
00366 LLPanel* panel = getPanelByName(name);
00367 if (!panel)
00368 {
00369 llwarns << "LLTabContainerCommon::selectTabByName("
00370 << name << ") failed" << llendl;
00371 return FALSE;
00372 }
00373
00374 BOOL result = selectTabPanel(panel);
00375 return result;
00376 }
00377
00378
00379 void LLTabContainerCommon::selectFirstTab()
00380 {
00381 selectTab( 0 );
00382 }
00383
00384
00385 void LLTabContainerCommon::selectLastTab()
00386 {
00387 selectTab( mTabList.size()-1 );
00388 }
00389
00390
00391 void LLTabContainerCommon::selectNextTab()
00392 {
00393 BOOL tab_has_focus = FALSE;
00394 if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
00395 {
00396 tab_has_focus = TRUE;
00397 }
00398 S32 idx = mCurrentTabIdx+1;
00399 if (idx >= (S32)mTabList.size())
00400 idx = 0;
00401 while (!selectTab(idx) && idx != mCurrentTabIdx)
00402 {
00403 idx = (idx + 1 ) % (S32)mTabList.size();
00404 }
00405
00406 if (tab_has_focus)
00407 {
00408 mTabList[idx]->mButton->setFocus(TRUE);
00409 }
00410 }
00411
00412 void LLTabContainerCommon::selectPrevTab()
00413 {
00414 BOOL tab_has_focus = FALSE;
00415 if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
00416 {
00417 tab_has_focus = TRUE;
00418 }
00419 S32 idx = mCurrentTabIdx-1;
00420 if (idx < 0)
00421 idx = mTabList.size()-1;
00422 while (!selectTab(idx) && idx != mCurrentTabIdx)
00423 {
00424 idx = idx - 1;
00425 if (idx < 0)
00426 idx = mTabList.size()-1;
00427 }
00428 if (tab_has_focus)
00429 {
00430 mTabList[idx]->mButton->setFocus(TRUE);
00431 }
00432 }
00433
00434
00435 void LLTabContainerCommon::reshape(S32 width, S32 height, BOOL called_from_parent)
00436 {
00437 LLPanel::reshape( width, height, called_from_parent );
00438 updateMaxScrollPos();
00439 }
00440
00441
00442 void LLTabContainerCommon::onTabBtn( void* userdata )
00443 {
00444 LLTabTuple* tuple = (LLTabTuple*) userdata;
00445 LLTabContainerCommon* self = tuple->mTabContainer;
00446 self->selectTabPanel( tuple->mTabPanel );
00447
00448 if( tuple->mOnChangeCallback )
00449 {
00450 tuple->mOnChangeCallback( tuple->mUserData, true );
00451 }
00452
00453 tuple->mTabPanel->setFocus(TRUE);
00454 }
00455
00456
00457 void LLTabContainerCommon::onCloseBtn( void* userdata )
00458 {
00459 LLTabContainer* self = (LLTabContainer*) userdata;
00460 if( self->mCloseCallback )
00461 {
00462 self->mCloseCallback( self->mCallbackUserdata );
00463 }
00464 }
00465
00466
00467 void LLTabContainerCommon::onNextBtn( void* userdata )
00468 {
00469
00470 LLTabContainer* self = (LLTabContainer*) userdata;
00471 if (!self->mScrolled)
00472 {
00473 self->scrollNext();
00474 }
00475 self->mScrolled = FALSE;
00476 }
00477
00478
00479 void LLTabContainerCommon::onNextBtnHeld( void* userdata )
00480 {
00481 LLTabContainer* self = (LLTabContainer*) userdata;
00482 if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
00483 {
00484 self->mScrollTimer.reset();
00485 self->scrollNext();
00486 self->mScrolled = TRUE;
00487 }
00488 }
00489
00490
00491 void LLTabContainerCommon::onPrevBtn( void* userdata )
00492 {
00493 LLTabContainer* self = (LLTabContainer*) userdata;
00494 if (!self->mScrolled)
00495 {
00496 self->scrollPrev();
00497 }
00498 self->mScrolled = FALSE;
00499 }
00500
00501
00502 void LLTabContainerCommon::onJumpFirstBtn( void* userdata )
00503 {
00504 LLTabContainer* self = (LLTabContainer*) userdata;
00505
00506 self->mScrollPos = 0;
00507
00508 }
00509
00510
00511 void LLTabContainerCommon::onJumpLastBtn( void* userdata )
00512 {
00513 LLTabContainer* self = (LLTabContainer*) userdata;
00514
00515 self->mScrollPos = self->mMaxScrollPos;
00516 }
00517
00518
00519
00520 void LLTabContainerCommon::onPrevBtnHeld( void* userdata )
00521 {
00522 LLTabContainer* self = (LLTabContainer*) userdata;
00523 if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
00524 {
00525 self->mScrollTimer.reset();
00526 self->scrollPrev();
00527 self->mScrolled = TRUE;
00528 }
00529 }
00530
00531 BOOL LLTabContainerCommon::getTabPanelFlashing(LLPanel *child)
00532 {
00533 LLTabTuple* tuple = getTabByPanel(child);
00534 if( tuple )
00535 {
00536 return tuple->mButton->getFlashing();
00537 }
00538 return FALSE;
00539 }
00540
00541 void LLTabContainerCommon::setTabPanelFlashing(LLPanel* child, BOOL state )
00542 {
00543 LLTabTuple* tuple = getTabByPanel(child);
00544 if( tuple )
00545 {
00546 tuple->mButton->setFlashing( state );
00547 }
00548 }
00549
00550 void LLTabContainerCommon::setTabImage(LLPanel* child, std::string img_name, const LLColor4& color)
00551 {
00552 LLTabTuple* tuple = getTabByPanel(child);
00553 if( tuple )
00554 {
00555 tuple->mButton->setImageOverlay(img_name, LLFontGL::RIGHT, color);
00556 }
00557 }
00558
00559 void LLTabContainerCommon::setTitle(const LLString& title)
00560 {
00561 if (mTitleBox)
00562 {
00563 mTitleBox->setText( title );
00564 }
00565 }
00566
00567 const LLString LLTabContainerCommon::getPanelTitle(S32 index)
00568 {
00569 if (index >= 0 && index < (S32)mTabList.size())
00570 {
00571 LLButton* tab_button = mTabList[index]->mButton;
00572 return tab_button->getLabelSelected();
00573 }
00574 return LLString::null;
00575 }
00576
00577 void LLTabContainerCommon::setTopBorderHeight(S32 height)
00578 {
00579 mTopBorderHeight = height;
00580 }
00581
00582
00583 void LLTabContainerCommon::setCurrentTabName(const LLString& name)
00584 {
00585
00586 if (mCurrentTabIdx < 0) return;
00587
00588 mTabList[mCurrentTabIdx]->mButton->setLabelSelected(name);
00589 mTabList[mCurrentTabIdx]->mButton->setLabelUnselected(name);
00590 }
00591
00592 LLView* LLTabContainerCommon::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00593 {
00594 LLString name("tab_container");
00595 node->getAttributeString("name", name);
00596
00597
00598 bool is_vertical = false;
00599 LLTabContainer::TabPosition tab_position = LLTabContainer::TOP;
00600 if (node->hasAttribute("tab_position"))
00601 {
00602 LLString tab_position_string;
00603 node->getAttributeString("tab_position", tab_position_string);
00604 LLString::toLower(tab_position_string);
00605
00606 if ("top" == tab_position_string)
00607 {
00608 tab_position = LLTabContainer::TOP;
00609 is_vertical = false;
00610 }
00611 else if ("bottom" == tab_position_string)
00612 {
00613 tab_position = LLTabContainer::BOTTOM;
00614 is_vertical = false;
00615 }
00616 else if ("left" == tab_position_string)
00617 {
00618 is_vertical = true;
00619 }
00620 }
00621 BOOL border = FALSE;
00622 node->getAttributeBOOL("border", border);
00623
00624
00625 LLTabContainerCommon* tab_container = NULL;
00626
00627 if (is_vertical)
00628 {
00629
00630 U32 tab_width = TABCNTRV_TAB_WIDTH;
00631 if (node->hasAttribute("tab_width"))
00632 {
00633 node->getAttributeU32("tab_width", tab_width);
00634 }
00635
00636 tab_container = new LLTabContainerVertical(name,
00637 LLRect::null,
00638 NULL,
00639 NULL,
00640 tab_width,
00641 border);
00642
00643 }
00644 else
00645 {
00646
00647 LLString title(LLString::null);
00648 if (node->hasAttribute("title"))
00649 {
00650 node->getAttributeString("title", title);
00651 }
00652
00653 tab_container = new LLTabContainer(name,
00654 LLRect::null,
00655 tab_position,
00656 NULL,
00657 NULL,
00658 title,
00659 border);
00660
00661 if(node->hasAttribute("tab_min_width"))
00662 {
00663 S32 minTabWidth=0;
00664 node->getAttributeS32("tab_min_width",minTabWidth);
00665 ((LLTabContainer*)tab_container)->setMinTabWidth(minTabWidth);
00666 }
00667 if(node->hasAttribute("tab_max_width"))
00668 {
00669 S32 maxTabWidth=0;
00670 node->getAttributeS32("tab_max_width",maxTabWidth);
00671 ((LLTabContainer*)tab_container)->setMaxTabWidth(maxTabWidth);
00672 }
00673 }
00674
00675 node->getAttributeBOOL("hide_tabs", tab_container->mTabsHidden);
00676
00677 tab_container->setPanelParameters(node, parent);
00678
00679 if (LLFloater::getFloaterHost())
00680 {
00681 LLFloater::getFloaterHost()->setTabContainer(tab_container);
00682 }
00683
00684
00685
00686
00687 LLXMLNodePtr child;
00688 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
00689 {
00690 LLView *control = factory->createCtrlWidget(tab_container, child);
00691 if (control && control->isPanel())
00692 {
00693 LLPanel* panelp = (LLPanel*)control;
00694 LLString label;
00695 child->getAttributeString("label", label);
00696 if (label.empty())
00697 {
00698 label = panelp->getLabel();
00699 }
00700 BOOL placeholder = FALSE;
00701 child->getAttributeBOOL("placeholder", placeholder);
00702 tab_container->addTabPanel(panelp, label.c_str(), false,
00703 NULL, NULL, 0, placeholder);
00704 }
00705 }
00706
00707 tab_container->selectFirstTab();
00708
00709 tab_container->postBuild();
00710
00711 tab_container->initButtons();
00712
00713 return tab_container;
00714 }
00715
00716 void LLTabContainerCommon::insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point)
00717 {
00718 switch(insertion_point)
00719 {
00720 case START:
00721
00722 mTabList.insert(mTabList.begin() + mLockedTabCount, tuple);
00723 break;
00724 case RIGHT_OF_CURRENT:
00725
00726 {
00727 tuple_list_t::iterator current_iter = mTabList.begin() + llmax(mLockedTabCount, mCurrentTabIdx + 1);
00728 mTabList.insert(current_iter, tuple);
00729 }
00730 break;
00731 case END:
00732 default:
00733 mTabList.push_back( tuple );
00734 }
00735 }
00736
00737
00738 LLTabContainer::LLTabContainer(
00739 const LLString& name, const LLRect& rect, TabPosition pos,
00740 void(*close_callback)(void*), void* callback_userdata,
00741 const LLString& title, BOOL bordered )
00742 :
00743 LLTabContainerCommon(name, rect, pos, close_callback, callback_userdata, bordered),
00744 mLeftArrowBtn(NULL),
00745 mJumpLeftArrowBtn(NULL),
00746 mRightArrowBtn(NULL),
00747 mJumpRightArrowBtn(NULL),
00748 mRightTabBtnOffset(0),
00749 mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
00750 mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
00751 mTotalTabWidth(0)
00752 {
00753 initButtons( );
00754 }
00755
00756 LLTabContainer::LLTabContainer(
00757 const LLString& name, const LLString& rect_control, TabPosition pos,
00758 void(*close_callback)(void*), void* callback_userdata,
00759 const LLString& title, BOOL bordered )
00760 :
00761 LLTabContainerCommon(name, rect_control, pos, close_callback, callback_userdata, bordered),
00762 mLeftArrowBtn(NULL),
00763 mJumpLeftArrowBtn(NULL),
00764 mRightArrowBtn(NULL),
00765 mJumpRightArrowBtn(NULL),
00766 mRightTabBtnOffset(0),
00767 mMinTabWidth(TABCNTR_TAB_MIN_WIDTH),
00768 mMaxTabWidth(TABCNTR_TAB_MAX_WIDTH),
00769 mTotalTabWidth(0)
00770 {
00771 initButtons( );
00772 }
00773
00774 void LLTabContainer::initButtons()
00775 {
00776
00777 if (mRect.getHeight() == 0 || mLeftArrowBtn)
00778 {
00779 return;
00780 }
00781
00782 LLString out_id;
00783 LLString in_id;
00784
00785 S32 arrow_fudge = 1;
00786
00787
00788 if (mTabPosition == BOTTOM)
00789 {
00790 mRightTabBtnOffset = RESIZE_HANDLE_WIDTH;
00791 }
00792
00793
00794 S32 btn_top = (mTabPosition == TOP ) ? mRect.getHeight() - mTopBorderHeight : TABCNTR_ARROW_BTN_SIZE + 1;
00795
00796 LLRect left_arrow_btn_rect;
00797 left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1+TABCNTR_ARROW_BTN_SIZE, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
00798
00799 LLRect jump_left_arrow_btn_rect;
00800 jump_left_arrow_btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH+1, btn_top + arrow_fudge, TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
00801
00802 S32 right_pad = TABCNTR_ARROW_BTN_SIZE + LLPANEL_BORDER_WIDTH + 1;
00803
00804 LLRect right_arrow_btn_rect;
00805 right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad - TABCNTR_ARROW_BTN_SIZE,
00806 btn_top + arrow_fudge,
00807 TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
00808
00809
00810 LLRect jump_right_arrow_btn_rect;
00811 jump_right_arrow_btn_rect.setLeftTopAndSize( mRect.getWidth() - mRightTabBtnOffset - right_pad,
00812 btn_top + arrow_fudge,
00813 TABCNTR_ARROW_BTN_SIZE, TABCNTR_ARROW_BTN_SIZE );
00814
00815 out_id = "UIImgBtnJumpLeftOutUUID";
00816 in_id = "UIImgBtnJumpLeftInUUID";
00817 mJumpLeftArrowBtn = new LLButton(
00818 "Jump Left Arrow", jump_left_arrow_btn_rect,
00819 out_id, in_id, "",
00820 &LLTabContainer::onJumpFirstBtn, this, LLFontGL::sSansSerif );
00821 mJumpLeftArrowBtn->setFollowsLeft();
00822 mJumpLeftArrowBtn->setSaveToXML(false);
00823 mJumpLeftArrowBtn->setTabStop(FALSE);
00824 addChild(mJumpLeftArrowBtn);
00825
00826 out_id = "UIImgBtnScrollLeftOutUUID";
00827 in_id = "UIImgBtnScrollLeftInUUID";
00828 mLeftArrowBtn = new LLButton(
00829 "Left Arrow", left_arrow_btn_rect,
00830 out_id, in_id, "",
00831 &LLTabContainer::onPrevBtn, this, LLFontGL::sSansSerif );
00832 mLeftArrowBtn->setHeldDownCallback(onPrevBtnHeld);
00833 mLeftArrowBtn->setFollowsLeft();
00834 mLeftArrowBtn->setSaveToXML(false);
00835 mLeftArrowBtn->setTabStop(FALSE);
00836 addChild(mLeftArrowBtn);
00837
00838 out_id = "UIImgBtnJumpRightOutUUID";
00839 in_id = "UIImgBtnJumpRightInUUID";
00840 mJumpRightArrowBtn = new LLButton(
00841 "Jump Right Arrow", jump_right_arrow_btn_rect,
00842 out_id, in_id, "",
00843 &LLTabContainer::onJumpLastBtn, this,
00844 LLFontGL::sSansSerif);
00845 mJumpRightArrowBtn->setFollowsRight();
00846 mJumpRightArrowBtn->setSaveToXML(false);
00847 mJumpRightArrowBtn->setTabStop(FALSE);
00848 addChild(mJumpRightArrowBtn);
00849
00850 out_id = "UIImgBtnScrollRightOutUUID";
00851 in_id = "UIImgBtnScrollRightInUUID";
00852 mRightArrowBtn = new LLButton(
00853 "Right Arrow", right_arrow_btn_rect,
00854 out_id, in_id, "",
00855 &LLTabContainer::onNextBtn, this,
00856 LLFontGL::sSansSerif);
00857 mRightArrowBtn->setFollowsRight();
00858 mRightArrowBtn->setHeldDownCallback(onNextBtnHeld);
00859 mRightArrowBtn->setSaveToXML(false);
00860 mRightArrowBtn->setTabStop(FALSE);
00861 addChild(mRightArrowBtn);
00862
00863
00864 if( mTabPosition == TOP )
00865 {
00866 mRightArrowBtn->setFollowsTop();
00867 mLeftArrowBtn->setFollowsTop();
00868 mJumpLeftArrowBtn->setFollowsTop();
00869 mJumpRightArrowBtn->setFollowsTop();
00870 }
00871 else
00872 {
00873 mRightArrowBtn->setFollowsBottom();
00874 mLeftArrowBtn->setFollowsBottom();
00875 mJumpLeftArrowBtn->setFollowsBottom();
00876 mJumpRightArrowBtn->setFollowsBottom();
00877 }
00878
00879
00880 mDefaultTabGroup = 1;
00881 }
00882
00883 LLTabContainer::~LLTabContainer()
00884 {
00885 }
00886
00887 void LLTabContainer::addTabPanel(LLPanel* child,
00888 const LLString& label,
00889 BOOL select,
00890 void (*on_tab_clicked)(void*, bool),
00891 void* userdata,
00892 S32 indent,
00893 BOOL placeholder,
00894 eInsertionPoint insertion_point)
00895 {
00896 if (child->getParent() == this)
00897 {
00898
00899 return;
00900 }
00901 const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
00902
00903
00904 child->setLabel(label);
00905 LLString trimmed_label = label;
00906 LLString::trim(trimmed_label);
00907
00908 S32 button_width = llclamp(font->getWidth(trimmed_label) + TAB_PADDING, mMinTabWidth, mMaxTabWidth);
00909
00910
00911 S32 tab_panel_top;
00912 S32 tab_panel_bottom;
00913 if( LLTabContainer::TOP == mTabPosition )
00914 {
00915 tab_panel_top = mRect.getHeight() - mTopBorderHeight - (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP);
00916 tab_panel_bottom = LLPANEL_BORDER_WIDTH;
00917 }
00918 else
00919 {
00920 tab_panel_top = mRect.getHeight() - mTopBorderHeight;
00921 tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP);
00922 }
00923
00924 LLRect tab_panel_rect(
00925 LLPANEL_BORDER_WIDTH,
00926 tab_panel_top,
00927 mRect.getWidth()-LLPANEL_BORDER_WIDTH,
00928 tab_panel_bottom );
00929
00930 child->setFollowsAll();
00931 child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom);
00932 child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
00933 child->setBackgroundVisible( FALSE );
00934
00935
00936 child->setVisible( FALSE );
00937
00938 mTotalTabWidth += button_width;
00939
00940
00941 LLRect btn_rect;
00942 LLString tab_img;
00943 LLString tab_selected_img;
00944 S32 tab_fudge = 1;
00945
00946 if( LLTabContainer::TOP == mTabPosition )
00947 {
00948 btn_rect.setLeftTopAndSize( 0, mRect.getHeight() - mTopBorderHeight + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
00949 tab_img = "UIImgBtnTabTopOutUUID";
00950 tab_selected_img = "UIImgBtnTabTopInUUID";
00951 }
00952 else
00953 {
00954 btn_rect.setOriginAndSize( 0, 0 + tab_fudge, button_width, TABCNTR_TAB_HEIGHT );
00955 tab_img = "UIImgBtnTabBottomOutUUID";
00956 tab_selected_img = "UIImgBtnTabBottomInUUID";
00957 }
00958
00959 if (placeholder)
00960 {
00961
00962 btn_rect.translate(0, -LLBUTTON_V_PAD-2);
00963 LLString box_label = trimmed_label;
00964 LLTextBox* text = new LLTextBox(box_label, btn_rect, box_label, font);
00965 addChild( text, 0 );
00966
00967 LLButton* btn = new LLButton("", LLRect(0,0,0,0));
00968 LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, text );
00969 addChild( btn, 0 );
00970 addChild( child, 1 );
00971 insertTuple(tuple, insertion_point);
00972 }
00973 else
00974 {
00975 LLString tooltip = trimmed_label;
00976 tooltip += "\nAlt-Left arrow for previous tab";
00977 tooltip += "\nAlt-Right arrow for next tab";
00978
00979 LLButton* btn = new LLButton(
00980 LLString(child->getName()) + " tab",
00981 btn_rect,
00982 tab_img, tab_selected_img, "",
00983 &LLTabContainer::onTabBtn, NULL,
00984 font,
00985 trimmed_label, trimmed_label );
00986 btn->setSaveToXML(false);
00987 btn->setVisible( FALSE );
00988 btn->setToolTip( tooltip );
00989 btn->setScaleImage(TRUE);
00990 btn->setFixedBorder(14, 14);
00991
00992
00993 btn->setLeftHPad( 4 );
00994 btn->setRightHPad( 2 );
00995 btn->setHAlign(LLFontGL::LEFT);
00996 btn->setTabStop(FALSE);
00997 if (indent)
00998 {
00999 btn->setLeftHPad(indent);
01000 }
01001
01002 if( mTabPosition == TOP )
01003 {
01004 btn->setFollowsTop();
01005 }
01006 else
01007 {
01008 btn->setFollowsBottom();
01009 }
01010
01011 LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata );
01012 btn->setCallbackUserData( tuple );
01013 addChild( btn, 0 );
01014 addChild( child, 1 );
01015 insertTuple(tuple, insertion_point);
01016 }
01017
01018 updateMaxScrollPos();
01019
01020 if( select )
01021 {
01022 selectLastTab();
01023 }
01024 }
01025
01026 void LLTabContainer::removeTabPanel(LLPanel* child)
01027 {
01028
01029 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01030 {
01031 LLTabTuple* tuple = *iter;
01032 if( tuple->mTabPanel == child )
01033 {
01034 mTotalTabWidth -= tuple->mButton->getRect().getWidth();
01035 break;
01036 }
01037 }
01038
01039 LLTabContainerCommon::removeTabPanel(child);
01040 }
01041
01042 void LLTabContainer::setPanelTitle(S32 index, const LLString& title)
01043 {
01044 if (index >= 0 && index < (S32)mTabList.size())
01045 {
01046 LLTabTuple* tuple = mTabList[index];
01047 LLButton* tab_button = tuple->mButton;
01048 const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
01049 mTotalTabWidth -= tab_button->getRect().getWidth();
01050 tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
01051 mTotalTabWidth += tab_button->getRect().getWidth();
01052 tab_button->setLabelSelected(title);
01053 tab_button->setLabelUnselected(title);
01054 }
01055 updateMaxScrollPos();
01056 }
01057
01058
01059 void LLTabContainer::updateMaxScrollPos()
01060 {
01061 S32 tab_space = 0;
01062 S32 available_space = 0;
01063 tab_space = mTotalTabWidth;
01064 available_space = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_TAB_H_PAD);
01065
01066 if( tab_space > available_space )
01067 {
01068 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
01069
01070 available_width_with_arrows -= TABCNTR_TAB_PARTIAL_WIDTH;
01071
01072 S32 running_tab_width = 0;
01073 mMaxScrollPos = mTabList.size();
01074 for(tuple_list_t::reverse_iterator tab_it = mTabList.rbegin(); tab_it != mTabList.rend(); ++tab_it)
01075 {
01076 running_tab_width += (*tab_it)->mButton->getRect().getWidth();
01077 if (running_tab_width > available_width_with_arrows)
01078 {
01079 break;
01080 }
01081 mMaxScrollPos--;
01082 }
01083
01084 mMaxScrollPos = llmin(mMaxScrollPos, (S32)mTabList.size() - 1);
01085 }
01086 else
01087 {
01088 mMaxScrollPos = 0;
01089 mScrollPos = 0;
01090 }
01091 if (mScrollPos > mMaxScrollPos)
01092 {
01093 mScrollPos = mMaxScrollPos;
01094 }
01095 }
01096
01097 void LLTabContainer::commitHoveredButton(S32 x, S32 y)
01098 {
01099 if (hasMouseCapture())
01100 {
01101 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01102 {
01103 LLTabTuple* tuple = *iter;
01104 tuple->mButton->setVisible( TRUE );
01105 S32 local_x = x - tuple->mButton->getRect().mLeft;
01106 S32 local_y = y - tuple->mButton->getRect().mBottom;
01107 if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
01108 {
01109 tuple->mButton->onCommit();
01110 }
01111 }
01112 }
01113 }
01114
01115 void LLTabContainer::setMinTabWidth(S32 width)
01116 {
01117 mMinTabWidth = width;
01118 }
01119
01120 void LLTabContainer::setMaxTabWidth(S32 width)
01121 {
01122 mMaxTabWidth = width;
01123 }
01124
01125 S32 LLTabContainer::getMinTabWidth() const
01126 {
01127 return mMinTabWidth;
01128 }
01129
01130 S32 LLTabContainer::getMaxTabWidth() const
01131 {
01132 return mMaxTabWidth;
01133 }
01134
01135 BOOL LLTabContainer::selectTab(S32 which)
01136 {
01137 if (which >= (S32)mTabList.size()) return FALSE;
01138 if (which < 0) return FALSE;
01139
01140
01141
01142
01143
01144
01145 LLTabTuple* selected_tuple = mTabList[which];
01146 if (!selected_tuple)
01147 {
01148 return FALSE;
01149 }
01150
01151 if (mTabList[which]->mButton->getEnabled())
01152 {
01153 mCurrentTabIdx = which;
01154
01155 S32 i = 0;
01156 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01157 {
01158 LLTabTuple* tuple = *iter;
01159 BOOL is_selected = ( tuple == selected_tuple );
01160 tuple->mTabPanel->setVisible( is_selected );
01161
01162 tuple->mButton->setToggleState( is_selected );
01163
01164 tuple->mButton->setTabStop( is_selected );
01165
01166 if( is_selected && mMaxScrollPos > 0)
01167 {
01168
01169 if( i < mScrollPos )
01170 {
01171 mScrollPos = i;
01172 }
01173 else
01174 {
01175 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
01176 S32 running_tab_width = tuple->mButton->getRect().getWidth();
01177 S32 j = i - 1;
01178 S32 min_scroll_pos = i;
01179 if (running_tab_width < available_width_with_arrows)
01180 {
01181 while (j >= 0)
01182 {
01183 LLTabTuple* other_tuple = mTabList[j];
01184 running_tab_width += other_tuple->mButton->getRect().getWidth();
01185 if (running_tab_width > available_width_with_arrows)
01186 {
01187 break;
01188 }
01189 j--;
01190 }
01191 min_scroll_pos = j + 1;
01192 }
01193 mScrollPos = llclamp(mScrollPos, min_scroll_pos, i);
01194 mScrollPos = llmin(mScrollPos, mMaxScrollPos);
01195 }
01196 }
01197 i++;
01198 }
01199 if( selected_tuple->mOnChangeCallback )
01200 {
01201 selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false );
01202 }
01203 return TRUE;
01204 }
01205 else
01206 {
01207 return FALSE;
01208 }
01209 }
01210
01211 void LLTabContainer::draw()
01212 {
01213 S32 target_pixel_scroll = 0;
01214 S32 cur_scroll_pos = mScrollPos;
01215 if (cur_scroll_pos > 0)
01216 {
01217 S32 available_width_with_arrows = mRect.getWidth() - mRightTabBtnOffset - 2 * (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
01218 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01219 {
01220 if (cur_scroll_pos == 0)
01221 {
01222 break;
01223 }
01224 target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
01225 cur_scroll_pos--;
01226 }
01227
01228
01229 target_pixel_scroll -= TABCNTR_TAB_PARTIAL_WIDTH;
01230
01231 target_pixel_scroll = llmin(mTotalTabWidth - available_width_with_arrows, target_pixel_scroll);
01232 }
01233
01234 mScrollPosPixels = (S32)lerp((F32)mScrollPosPixels, (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f));
01235 if( getVisible() )
01236 {
01237 BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
01238 mJumpLeftArrowBtn->setVisible( has_scroll_arrows );
01239 mJumpRightArrowBtn->setVisible( has_scroll_arrows );
01240 mLeftArrowBtn->setVisible( has_scroll_arrows );
01241 mRightArrowBtn->setVisible( has_scroll_arrows );
01242
01243
01244 S32 left = LLPANEL_BORDER_WIDTH + (has_scroll_arrows ? (TABCNTR_ARROW_BTN_SIZE * 2) : TABCNTR_TAB_H_PAD);
01245 left -= mScrollPosPixels;
01246
01247
01248 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01249 {
01250 LLTabTuple* tuple = *iter;
01251 tuple->mButton->setVisible( FALSE );
01252 }
01253
01254 LLPanel::draw();
01255
01256
01257 if (!mTabsHidden)
01258 {
01259
01260 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01261 {
01262 LLTabTuple* tuple = *iter;
01263 tuple->mButton->setVisible( TRUE );
01264 }
01265
01266
01267 LLRect clip_rect = getLocalRect();
01268 if (has_scroll_arrows)
01269 {
01270
01271 clip_rect.mLeft = mLeftArrowBtn->getRect().mRight;
01272 clip_rect.mRight = mRightArrowBtn->getRect().mLeft;
01273 }
01274 LLLocalClipRect clip(clip_rect);
01275
01276 S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos;
01277 S32 idx = 0;
01278 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01279 {
01280 LLTabTuple* tuple = *iter;
01281
01282 tuple->mButton->translate( left - tuple->mButton->getRect().mLeft, 0 );
01283 left += tuple->mButton->getRect().getWidth();
01284
01285 if( idx < mScrollPos )
01286 {
01287 if( tuple->mButton->getFlashing() )
01288 {
01289 mLeftArrowBtn->setFlashing( TRUE );
01290 }
01291 }
01292 else
01293 if( max_scroll_visible < idx )
01294 {
01295 if( tuple->mButton->getFlashing() )
01296 {
01297 mRightArrowBtn->setFlashing( TRUE );
01298 }
01299 }
01300
01301 LLUI::pushMatrix();
01302 {
01303 LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
01304 tuple->mButton->draw();
01305 }
01306 LLUI::popMatrix();
01307
01308 idx++;
01309 }
01310 }
01311
01312 mLeftArrowBtn->setFlashing(FALSE);
01313 mRightArrowBtn->setFlashing(FALSE);
01314 }
01315 }
01316
01317
01318 void LLTabContainer::setRightTabBtnOffset(S32 offset)
01319 {
01320 mRightArrowBtn->translate( -offset - mRightTabBtnOffset, 0 );
01321 mRightTabBtnOffset = offset;
01322 updateMaxScrollPos();
01323 }
01324
01325 BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
01326 {
01327 BOOL handled = FALSE;
01328 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
01329
01330 if (has_scroll_arrows)
01331 {
01332 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
01333 {
01334 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
01335 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
01336 handled = mJumpLeftArrowBtn->handleMouseDown(local_x, local_y, mask);
01337 }
01338 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
01339 {
01340 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
01341 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
01342 handled = mJumpRightArrowBtn->handleMouseDown(local_x, local_y, mask);
01343 }
01344 if (mLeftArrowBtn->getRect().pointInRect(x, y))
01345 {
01346 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
01347 S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
01348 handled = mLeftArrowBtn->handleMouseDown(local_x, local_y, mask);
01349 }
01350 else if (mRightArrowBtn->getRect().pointInRect(x, y))
01351 {
01352 S32 local_x = x - mRightArrowBtn->getRect().mLeft;
01353 S32 local_y = y - mRightArrowBtn->getRect().mBottom;
01354 handled = mRightArrowBtn->handleMouseDown(local_x, local_y, mask);
01355 }
01356 }
01357 if (!handled)
01358 {
01359 handled = LLPanel::handleMouseDown( x, y, mask );
01360 }
01361
01362 if (mTabList.size() > 0)
01363 {
01364 LLTabTuple* firsttuple = mTabList[0];
01365 LLRect tab_rect(has_scroll_arrows ? mLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft,
01366 firsttuple->mButton->getRect().mTop,
01367 has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mJumpRightArrowBtn->getRect().mRight,
01368 firsttuple->mButton->getRect().mBottom );
01369 if( tab_rect.pointInRect( x, y ) )
01370 {
01371 LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton;
01372 gFocusMgr.setMouseCapture(this);
01373 gFocusMgr.setKeyboardFocus(tab_button, NULL);
01374 }
01375 }
01376 return handled;
01377 }
01378
01379 BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
01380 {
01381 BOOL handled = FALSE;
01382 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
01383
01384 if (has_scroll_arrows)
01385 {
01386 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
01387 {
01388 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
01389 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
01390 handled = mJumpLeftArrowBtn->handleHover(local_x, local_y, mask);
01391 }
01392 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
01393 {
01394 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
01395 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
01396 handled = mJumpRightArrowBtn->handleHover(local_x, local_y, mask);
01397 }
01398 if (mLeftArrowBtn->getRect().pointInRect(x, y))
01399 {
01400 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
01401 S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
01402 handled = mLeftArrowBtn->handleHover(local_x, local_y, mask);
01403 }
01404 else if (mRightArrowBtn->getRect().pointInRect(x, y))
01405 {
01406 S32 local_x = x - mRightArrowBtn->getRect().mLeft;
01407 S32 local_y = y - mRightArrowBtn->getRect().mBottom;
01408 handled = mRightArrowBtn->handleHover(local_x, local_y, mask);
01409 }
01410 }
01411 if (!handled)
01412 {
01413 handled = LLPanel::handleHover(x, y, mask);
01414 }
01415
01416 commitHoveredButton(x, y);
01417 return handled;
01418 }
01419
01420 BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
01421 {
01422 BOOL handled = FALSE;
01423 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
01424
01425 if (has_scroll_arrows)
01426 {
01427 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
01428 {
01429 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
01430 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
01431 handled = mJumpLeftArrowBtn->handleMouseUp(local_x, local_y, mask);
01432 }
01433 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
01434 {
01435 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
01436 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
01437 handled = mJumpRightArrowBtn->handleMouseUp(local_x, local_y, mask);
01438 }
01439 if (mLeftArrowBtn->getRect().pointInRect(x, y))
01440 {
01441 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
01442 S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
01443 handled = mLeftArrowBtn->handleMouseUp(local_x, local_y, mask);
01444 }
01445 else if (mRightArrowBtn->getRect().pointInRect(x, y))
01446 {
01447 S32 local_x = x - mRightArrowBtn->getRect().mLeft;
01448 S32 local_y = y - mRightArrowBtn->getRect().mBottom;
01449 handled = mRightArrowBtn->handleMouseUp(local_x, local_y, mask);
01450 }
01451 }
01452 if (!handled)
01453 {
01454 handled = LLPanel::handleMouseUp( x, y, mask );
01455 }
01456
01457 commitHoveredButton(x, y);
01458 LLPanel* cur_panel = getCurrentPanel();
01459 if (hasMouseCapture())
01460 {
01461 if (cur_panel)
01462 {
01463 if (!cur_panel->focusFirstItem(FALSE))
01464 {
01465
01466
01467 mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE);
01468 }
01469 }
01470 gFocusMgr.setMouseCapture(NULL);
01471 }
01472 return handled;
01473 }
01474
01475 BOOL LLTabContainer::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect )
01476 {
01477 BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
01478 if (!handled && mTabList.size() > 0 && getVisible() && pointInView( x, y ) )
01479 {
01480 LLTabTuple* firsttuple = mTabList[0];
01481
01482 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
01483 LLRect clip(
01484 has_scroll_arrows ? mJumpLeftArrowBtn->getRect().mRight : mJumpLeftArrowBtn->getRect().mLeft,
01485 firsttuple->mButton->getRect().mTop,
01486 has_scroll_arrows ? mRightArrowBtn->getRect().mLeft : mRightArrowBtn->getRect().mRight,
01487 0 );
01488 if( clip.pointInRect( x, y ) )
01489 {
01490 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01491 {
01492 LLTabTuple* tuple = *iter;
01493 tuple->mButton->setVisible( TRUE );
01494 S32 local_x = x - tuple->mButton->getRect().mLeft;
01495 S32 local_y = y - tuple->mButton->getRect().mBottom;
01496 handled = tuple->mButton->handleToolTip( local_x, local_y, msg, sticky_rect );
01497 if( handled )
01498 {
01499 break;
01500 }
01501 }
01502 }
01503
01504 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01505 {
01506 LLTabTuple* tuple = *iter;
01507 tuple->mButton->setVisible( FALSE );
01508 }
01509 }
01510 return handled;
01511 }
01512
01513 BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
01514 {
01515 if (!getEnabled()) return FALSE;
01516
01517 if (!gFocusMgr.childHasKeyboardFocus(this)) return FALSE;
01518
01519 BOOL handled = FALSE;
01520 if (key == KEY_LEFT && mask == MASK_ALT)
01521 {
01522 selectPrevTab();
01523 handled = TRUE;
01524 }
01525 else if (key == KEY_RIGHT && mask == MASK_ALT)
01526 {
01527 selectNextTab();
01528 handled = TRUE;
01529 }
01530
01531 if (handled)
01532 {
01533 if (getCurrentPanel())
01534 {
01535 getCurrentPanel()->setFocus(TRUE);
01536 }
01537 }
01538
01539 if (!gFocusMgr.childHasKeyboardFocus(getCurrentPanel()))
01540 {
01541
01542
01543 switch(key)
01544 {
01545 case KEY_UP:
01546 if (getTabPosition() == BOTTOM && getCurrentPanel())
01547 {
01548 getCurrentPanel()->setFocus(TRUE);
01549 }
01550 handled = TRUE;
01551 break;
01552 case KEY_DOWN:
01553 if (getTabPosition() == TOP && getCurrentPanel())
01554 {
01555 getCurrentPanel()->setFocus(TRUE);
01556 }
01557 handled = TRUE;
01558 break;
01559 case KEY_LEFT:
01560 selectPrevTab();
01561 handled = TRUE;
01562 break;
01563 case KEY_RIGHT:
01564 selectNextTab();
01565 handled = TRUE;
01566 break;
01567 default:
01568 break;
01569 }
01570 }
01571 return handled;
01572 }
01573
01574
01575 LLXMLNodePtr LLTabContainer::getXML(bool save_children) const
01576 {
01577 LLXMLNodePtr node = LLTabContainerCommon::getXML();
01578
01579 node->createChild("tab_position", TRUE)->setStringValue((mTabPosition == TOP ? "top" : "bottom"));
01580
01581 return node;
01582 }
01583
01584 BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, LLString &tooltip)
01585 {
01586 BOOL has_scroll_arrows = (mMaxScrollPos > 0);
01587
01588 if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME )
01589 {
01590
01591 if (has_scroll_arrows)
01592 {
01593 if (mJumpLeftArrowBtn->getRect().pointInRect(x, y))
01594 {
01595 S32 local_x = x - mJumpLeftArrowBtn->getRect().mLeft;
01596 S32 local_y = y - mJumpLeftArrowBtn->getRect().mBottom;
01597 mJumpLeftArrowBtn->handleHover(local_x, local_y, mask);
01598 }
01599 if (mJumpRightArrowBtn->getRect().pointInRect(x, y))
01600 {
01601 S32 local_x = x - mJumpRightArrowBtn->getRect().mLeft;
01602 S32 local_y = y - mJumpRightArrowBtn->getRect().mBottom;
01603 mJumpRightArrowBtn->handleHover(local_x, local_y, mask);
01604 }
01605 if (mLeftArrowBtn->getRect().pointInRect(x, y))
01606 {
01607 S32 local_x = x - mLeftArrowBtn->getRect().mLeft;
01608 S32 local_y = y - mLeftArrowBtn->getRect().mBottom;
01609 mLeftArrowBtn->handleHover(local_x, local_y, mask);
01610 }
01611 else if (mRightArrowBtn->getRect().pointInRect(x, y))
01612 {
01613 S32 local_x = x - mRightArrowBtn->getRect().mLeft;
01614 S32 local_y = y - mRightArrowBtn->getRect().mBottom;
01615 mRightArrowBtn->handleHover(local_x, local_y, mask);
01616 }
01617 }
01618
01619 for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
01620 {
01621 LLTabTuple* tuple = *iter;
01622 tuple->mButton->setVisible( TRUE );
01623 S32 local_x = x - tuple->mButton->getRect().mLeft;
01624 S32 local_y = y - tuple->mButton->getRect().mBottom;
01625 if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
01626 {
01627 tuple->mButton->onCommit();
01628 mDragAndDropDelayTimer.stop();
01629 }
01630 }
01631 }
01632
01633 return LLView::handleDragAndDrop(x, y, mask, drop, type, cargo_data, accept, tooltip);
01634 }
01635
01636 void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
01637 {
01638 LLTabTuple* tuple = getTabByPanel(child);
01639 if( tuple )
01640 {
01641 tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
01642
01643 const LLFontGL* fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL );
01644
01645 mTotalTabWidth -= tuple->mButton->getRect().getWidth();
01646
01647 S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
01648 tuple->mButton->getImageOverlay()->getWidth(0) :
01649 0;
01650
01651 tuple->mPadding = image_overlay_width;
01652
01653 tuple->mButton->setRightHPad(tuple->mPadding + LLBUTTON_H_PAD);
01654 tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
01655 tuple->mButton->getRect().getHeight());
01656
01657 mTotalTabWidth += tuple->mButton->getRect().getWidth();
01658
01659
01660 updateMaxScrollPos();
01661 }
01662 }