llaccordionctrl.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:18k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llaccordionctrl.cpp
  3.  * @brief Accordion panel  implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llaccordionctrl.h"
  34. #include "llaccordionctrltab.h"
  35. #include "lluictrlfactory.h" // builds floaters from XML
  36. #include "llwindow.h"
  37. #include "llfocusmgr.h"
  38. #include "lllocalcliprect.h"
  39. #include "boost/bind.hpp"
  40. static const S32 DRAGGER_BAR_MARGIN = 4;
  41. static const S32 DRAGGER_BAR_HEIGHT = 5;
  42. static const S32 BORDER_MARGIN = 2;
  43. static const S32 PARENT_BORDER_MARGIN = 5;
  44. static const S32 panel_delta = DRAGGER_BAR_MARGIN;  // Distanse between two panels 
  45. static const S32 HORIZONTAL_MULTIPLE = 8;
  46. static const S32 VERTICAL_MULTIPLE = 16;
  47. static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
  48. static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
  49. static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
  50. // LLAccordionCtrl =================================================================|
  51. static LLDefaultChildRegistry::Register<LLAccordionCtrl> t2("accordion");
  52. LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
  53.  , mFitParent(params.fit_parent)
  54.  , mAutoScrolling( false )
  55.  , mAutoScrollRate( 0.f )
  56. {
  57.   mSingleExpansion = params.single_expansion;
  58. if(mFitParent && !mSingleExpansion)
  59. {
  60. llinfos << "fit_parent works best when combined with single_expansion" << llendl;
  61. }
  62. }
  63. LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
  64.  , mAutoScrolling( false )
  65.  , mAutoScrollRate( 0.f )
  66. {
  67. mSingleExpansion = false;
  68. mFitParent = false;
  69. LLUICtrlFactory::getInstance()->buildPanel(this, "accordion_parent.xml");
  70. }
  71. //---------------------------------------------------------------------------------
  72. void LLAccordionCtrl::draw()
  73. {
  74. if (mAutoScrolling)
  75. {
  76. // add acceleration to autoscroll
  77. mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE);
  78. }
  79. else
  80. {
  81. // reset to minimum for next time
  82. mAutoScrollRate = MIN_AUTO_SCROLL_RATE;
  83. }
  84. // clear this flag to be set on next call to autoScroll
  85. mAutoScrolling = false;
  86. LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
  87. LLLocalClipRect clip(local_rect);
  88. LLPanel::draw();
  89. }
  90. //---------------------------------------------------------------------------------
  91. BOOL LLAccordionCtrl::postBuild()
  92. {
  93. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  94. LLRect scroll_rect;
  95. scroll_rect.setOriginAndSize( 
  96. getRect().getWidth() - scrollbar_size,
  97. 1,
  98. scrollbar_size,
  99. getRect().getHeight() - 1);
  100. LLScrollbar::Params sbparams;
  101. sbparams.name("scrollable vertical");
  102. sbparams.rect(scroll_rect);
  103. sbparams.orientation(LLScrollbar::VERTICAL);
  104. sbparams.doc_size(mInnerRect.getHeight());
  105. sbparams.doc_pos(0);
  106. sbparams.page_size(mInnerRect.getHeight());
  107. sbparams.step_size(VERTICAL_MULTIPLE);
  108. sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
  109. sbparams.change_callback(boost::bind(&LLAccordionCtrl::onScrollPosChangeCallback, this, _1, _2));
  110. mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
  111. LLView::addChild( mScrollbar );
  112. mScrollbar->setVisible( false );
  113. mScrollbar->setFollowsRight();
  114. mScrollbar->setFollowsTop();
  115. mScrollbar->setFollowsBottom();
  116. //if it was created from xml...
  117. std::vector<LLUICtrl*> accordion_tabs;
  118. for(child_list_const_iter_t it = getChildList()->begin(); 
  119. getChildList()->end() != it; ++it)
  120. {
  121. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*it);
  122. if(accordion_tab == NULL)
  123. continue;
  124. if(std::find(mAccordionTabs.begin(),mAccordionTabs.end(),accordion_tab) == mAccordionTabs.end())
  125. {
  126. accordion_tabs.push_back(accordion_tab);
  127. }
  128. }
  129. for(std::vector<LLUICtrl*>::reverse_iterator it = accordion_tabs.rbegin();it!=accordion_tabs.rend();++it)
  130. addCollapsibleCtrl(*it);
  131. arrange ();
  132. if(mSingleExpansion)
  133. {
  134. if(!mAccordionTabs[0]->getDisplayChildren())
  135. mAccordionTabs[0]->setDisplayChildren(true);
  136. for(size_t i=1;i<mAccordionTabs.size();++i)
  137. {
  138. if(mAccordionTabs[i]->getDisplayChildren())
  139. mAccordionTabs[i]->setDisplayChildren(false);
  140. }
  141. }
  142. return TRUE;
  143. }
  144. //---------------------------------------------------------------------------------
  145. LLAccordionCtrl::~LLAccordionCtrl()
  146. {
  147.   mAccordionTabs.clear();
  148. }
  149. //---------------------------------------------------------------------------------
  150. void LLAccordionCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
  151. {
  152. // adjust our rectangle
  153. LLRect rcLocal = getRect();
  154. rcLocal.mRight = rcLocal.mLeft + width;
  155. rcLocal.mTop = rcLocal.mBottom + height;
  156. setRect(rcLocal);
  157. arrange();
  158. }
  159. //---------------------------------------------------------------------------------
  160. BOOL LLAccordionCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
  161. {
  162. return LLPanel::handleRightMouseDown(x, y, mask);
  163. }
  164. //---------------------------------------------------------------------------------
  165. void LLAccordionCtrl::shiftAccordionTabs(S16 panel_num, S32 delta)
  166. {
  167. for(size_t i = panel_num; i < mAccordionTabs.size(); i++ )
  168. {
  169. ctrlShiftVertical(mAccordionTabs[i],delta);
  170. }
  171. }
  172. //---------------------------------------------------------------------------------
  173. void LLAccordionCtrl::onCollapseCtrlCloseOpen(S16 panel_num) 
  174. {
  175. if(mSingleExpansion)
  176. {
  177. for(size_t i=0;i<mAccordionTabs.size();++i)
  178. {
  179. if(i==panel_num)
  180. continue;
  181. if(mAccordionTabs[i]->getDisplayChildren())
  182. mAccordionTabs[i]->setDisplayChildren(false);
  183. }
  184. }
  185. arrange();
  186. }
  187. void LLAccordionCtrl::show_hide_scrollbar(S32 width, S32 height)
  188. {
  189. calcRecuiredHeight();
  190. if(getRecuiredHeight() > height )
  191. showScrollbar(width,height);
  192. else
  193. hideScrollbar(width,height);
  194. }
  195. void LLAccordionCtrl::showScrollbar(S32 width, S32 height)
  196. {
  197. bool was_visible = mScrollbar->getVisible();
  198. mScrollbar->setVisible(true);
  199. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  200. ctrlSetLeftTopAndSize(mScrollbar
  201. ,width-scrollbar_size - PARENT_BORDER_MARGIN/2
  202. ,height-PARENT_BORDER_MARGIN
  203. ,scrollbar_size
  204. ,height-2*PARENT_BORDER_MARGIN);
  205. mScrollbar->setPageSize(height);
  206. mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
  207. if(was_visible)
  208. {
  209. S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
  210. mScrollbar->setDocPos(scroll_pos);
  211. }
  212. }
  213. void LLAccordionCtrl::hideScrollbar( S32 width, S32 height )
  214. {
  215. if(mScrollbar->getVisible() == false)
  216. return;
  217. mScrollbar->setVisible(false);
  218. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  219. S32 panel_width = width - 2*BORDER_MARGIN;
  220. //reshape all accordeons and shift all draggers
  221. for(size_t i=0;i<mAccordionTabs.size();++i)
  222. {
  223. LLRect panel_rect = mAccordionTabs[i]->getRect();
  224. ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_rect.mTop,panel_width,panel_rect.getHeight());
  225. }
  226. mScrollbar->setDocPos(0);
  227. if(mAccordionTabs.size()>0)
  228. {
  229. S32 panel_top = height - BORDER_MARGIN;   // Top coordinate of the first panel
  230. S32 diff = panel_top - mAccordionTabs[0]->getRect().mTop;
  231. shiftAccordionTabs(0,diff);
  232. }
  233. }
  234. //---------------------------------------------------------------------------------
  235. S32 LLAccordionCtrl::calcRecuiredHeight()
  236. {
  237. S32 rec_height = 0;
  238. std::vector<LLAccordionCtrlTab*>::iterator panel;
  239. for(panel=mAccordionTabs.begin(); panel!=mAccordionTabs.end(); ++panel)
  240. {
  241. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(*panel);
  242. if(accordion_tab && accordion_tab->getVisible())
  243. {
  244. rec_height += accordion_tab->getRect().getHeight();
  245. }
  246. }
  247. mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
  248. return mInnerRect.getHeight();
  249. }
  250. //---------------------------------------------------------------------------------
  251. void LLAccordionCtrl::ctrlSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
  252. {
  253. if(!panel)
  254. return;
  255. LLRect panel_rect = panel->getRect();
  256. panel_rect.setLeftTopAndSize( left, top, width, height);
  257. panel->reshape( width, height, 1);
  258. panel->setRect(panel_rect);
  259. }
  260. void LLAccordionCtrl::ctrlShiftVertical(LLView* panel,S32 delta)
  261. {
  262. if(!panel)
  263. return;
  264. panel->translate(0,delta);
  265. }
  266. //---------------------------------------------------------------------------------
  267. void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)
  268. {
  269. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(view);
  270. if(!accordion_tab)
  271. return;
  272. if(std::find(getChildList()->begin(),getChildList()->end(),accordion_tab) == getChildList()->end())
  273. addChild(accordion_tab);
  274. mAccordionTabs.push_back(accordion_tab);
  275. accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) );
  276. }
  277. void LLAccordionCtrl::arrange()
  278. {
  279. if( mAccordionTabs.size() == 0)
  280. {
  281. //We do not arrange if we do not have what should be arranged
  282. return;
  283. }
  284. //Calculate params
  285. S32 panel_left = BORDER_MARGIN;   // Margin from left side of Splitter
  286. S32 panel_top = getRect().getHeight() - BORDER_MARGIN;   // Top coordinate of the first panel
  287. S32 panel_width = getRect().getWidth() - 4;   // Top coordinate of the first panel
  288. if(mAccordionTabs.size() == 1)
  289. {
  290. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[0]);
  291. LLRect panel_rect = accordion_tab->getRect();
  292. S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN;
  293. ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);
  294. show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
  295. return;
  296. }
  297. for(size_t i = 0; i < mAccordionTabs.size(); i++ )
  298. {
  299. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
  300. if(accordion_tab->getVisible() == false) //skip hidden accordion tabs
  301. continue;
  302. if(!accordion_tab->isExpanded() )
  303. {
  304. ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, accordion_tab->getRect().getHeight());
  305. panel_top-=mAccordionTabs[i]->getRect().getHeight();
  306. }
  307. else
  308. {
  309. S32 panel_height = accordion_tab->getRect().getHeight();
  310. if(mFitParent)
  311. {
  312. // all expanded tabs will have equal height
  313. panel_height = calcExpandedTabHeight(i, panel_top);
  314. ctrlSetLeftTopAndSize(accordion_tab, panel_left, panel_top, panel_width, panel_height);
  315. // try to make accordion tab fit accordion view height.
  316. // Accordion View should implement getRequiredRect() and provide valid height
  317. S32 optimal_height = accordion_tab->getAccordionView()->getRequiredRect().getHeight();
  318. optimal_height += accordion_tab->getHeaderHeight() + 2 * BORDER_MARGIN;
  319. if(optimal_height < panel_height)
  320. {
  321. panel_height = optimal_height;
  322. }
  323. // minimum tab height is equal to header height
  324. if(mAccordionTabs[i]->getHeaderHeight() > panel_height)
  325. {
  326. panel_height = mAccordionTabs[i]->getHeaderHeight();
  327. }
  328. }
  329. ctrlSetLeftTopAndSize(mAccordionTabs[i], panel_left, panel_top, panel_width, panel_height);
  330. panel_top-=panel_height;
  331. }
  332. }
  333. show_hide_scrollbar(getRect().getWidth(),getRect().getHeight());
  334. updateLayout(getRect().getWidth(),getRect().getHeight());
  335. }
  336. //---------------------------------------------------------------------------------
  337. BOOL LLAccordionCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks )
  338. {
  339. if(LLPanel::handleScrollWheel(x,y,clicks))
  340. return TRUE;
  341. if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
  342. return TRUE;
  343. return false;
  344. }
  345. BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask)
  346. {
  347. if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
  348. return TRUE;
  349. return LLPanel::handleKeyHere(key,mask);
  350. }
  351. BOOL LLAccordionCtrl::handleDragAndDrop (S32 x, S32 y, MASK mask,
  352.  BOOL drop,
  353.  EDragAndDropType cargo_type,
  354.  void* cargo_data,
  355.  EAcceptance* accept,
  356.  std::string& tooltip_msg)
  357. {
  358. // Scroll folder view if needed.  Never accepts a drag or drop.
  359. *accept = ACCEPT_NO;
  360. BOOL handled = autoScroll(x, y);
  361. if( !handled )
  362. {
  363. handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
  364. cargo_data, accept, tooltip_msg) != NULL;
  365. }
  366. return TRUE;
  367. }
  368. BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y)
  369. {
  370. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  371. bool scrolling = false;
  372. if( mScrollbar->getVisible() )
  373. {
  374. LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 );
  375. LLRect screen_local_extents;
  376. // clip rect against root view
  377. screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents);
  378. rect_local.intersectWith(screen_local_extents);
  379. // autoscroll region should take up no more than one third of visible scroller area
  380. S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10);
  381. S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32());
  382. LLRect bottom_scroll_rect = screen_local_extents;
  383. bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height;
  384. if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()) )
  385. {
  386. mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed );
  387. mAutoScrolling = true;
  388. scrolling = true;
  389. }
  390. LLRect top_scroll_rect = screen_local_extents;
  391. top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height;
  392. if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() > 0) )
  393. {
  394. mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed );
  395. mAutoScrolling = true;
  396. scrolling = true;
  397. }
  398. }
  399. return scrolling;
  400. }
  401. void LLAccordionCtrl::updateLayout (S32 width, S32 height)
  402. {
  403. S32 panel_top = height - BORDER_MARGIN ;
  404. if(mScrollbar->getVisible())
  405. panel_top+=mScrollbar->getDocPos();
  406. S32 panel_width = width - 2*BORDER_MARGIN;
  407. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  408. if(mScrollbar->getVisible())
  409. panel_width-=scrollbar_size;
  410. //set sizes for first panels and dragbars
  411. for(size_t i=0;i<mAccordionTabs.size();++i)
  412. {
  413. if(!mAccordionTabs[i]->getVisible())
  414. continue;
  415. LLRect panel_rect = mAccordionTabs[i]->getRect();
  416. ctrlSetLeftTopAndSize(mAccordionTabs[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
  417. panel_top-=panel_rect.getHeight();
  418. }
  419. }
  420. void LLAccordionCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
  421. {
  422. updateLayout(getRect().getWidth(),getRect().getHeight());
  423. }
  424. void LLAccordionCtrl::onOpen (const LLSD& key)
  425. {
  426. for(size_t i=0;i<mAccordionTabs.size();++i)
  427. {
  428. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
  429. LLPanel* panel = dynamic_cast<LLPanel*>(accordion_tab->getAccordionView());
  430. if(panel!=NULL)
  431. {
  432. panel->onOpen(key);
  433. }
  434. }
  435. }
  436. S32 LLAccordionCtrl::notifyParent(const LLSD& info)
  437. {
  438. if(info.has("action"))
  439. {
  440. std::string str_action = info["action"];
  441. if(str_action == "size_changes")
  442. {
  443. //
  444. arrange();
  445. return 1;
  446. }
  447. else if(str_action == "select_next")
  448. {
  449. for(size_t i=0;i<mAccordionTabs.size();++i)
  450. {
  451. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
  452. if(accordion_tab->hasFocus())
  453. {
  454. while(++i<mAccordionTabs.size())
  455. {
  456. if(mAccordionTabs[i]->getVisible())
  457. break;
  458. }
  459. if(i<mAccordionTabs.size())
  460. {
  461. accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
  462. accordion_tab->notify(LLSD().with("action","select_first"));
  463. return 1;
  464. }
  465. break;
  466. }
  467. }
  468. return 0;
  469. }
  470. else if(str_action == "select_prev")
  471. {
  472. for(size_t i=0;i<mAccordionTabs.size();++i)
  473. {
  474. LLAccordionCtrlTab* accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
  475. if(accordion_tab->hasFocus() && i>0)
  476. {
  477. while(i>0)
  478. {
  479. if(mAccordionTabs[--i]->getVisible())
  480. break;
  481. }
  482. accordion_tab = dynamic_cast<LLAccordionCtrlTab*>(mAccordionTabs[i]);
  483. accordion_tab->notify(LLSD().with("action","select_last"));
  484. return 1;
  485. }
  486. }
  487. return 0;
  488. }
  489. }
  490. else if (info.has("scrollToShowRect"))
  491. {
  492. LLRect screen_rc, local_rc;
  493. screen_rc.setValue(info["scrollToShowRect"]);
  494. screenRectToLocal(screen_rc, &local_rc);
  495. // Translate to parent coordinatess to check if we are in visible rectangle
  496. local_rc.translate( getRect().mLeft, getRect().mBottom );
  497. if ( !getRect().contains (local_rc) )
  498. {
  499. // Back to local coords and calculate position for scroller
  500. S32 bottom = mScrollbar->getDocPos() - local_rc.mBottom + getRect().mBottom;
  501. S32 top = mScrollbar->getDocPos() - local_rc.mTop + getRect().mTop;
  502. S32 scroll_pos = llclamp(mScrollbar->getDocPos(),
  503.  bottom, // min vertical scroll
  504.  top); // max vertical scroll 
  505. mScrollbar->setDocPos( scroll_pos );
  506. }
  507. return 1;
  508. }
  509. return LLPanel::notifyParent(info);
  510. }
  511. void LLAccordionCtrl::reset ()
  512. {
  513. if(mScrollbar)
  514. mScrollbar->setDocPos(0);
  515. }
  516. S32 LLAccordionCtrl::calcExpandedTabHeight(S32 tab_index /* = 0 */, S32 available_height /* = 0 */)
  517. {
  518. if(tab_index < 0)
  519. {
  520. return available_height;
  521. }
  522. S32 collapsed_tabs_height = 0;
  523. S32 num_expanded = 0;
  524. for(size_t n = tab_index; n < mAccordionTabs.size(); ++n)
  525. {
  526. if(!mAccordionTabs[n]->isExpanded())
  527. {
  528. collapsed_tabs_height += mAccordionTabs[n]->getHeaderHeight();
  529. }
  530. else
  531. {
  532. ++num_expanded;
  533. }
  534. }
  535. if(0 == num_expanded)
  536. {
  537. return available_height;
  538. }
  539. S32 expanded_tab_height = available_height - collapsed_tabs_height - BORDER_MARGIN; // top BORDER_MARGIN is added in arrange(), here we add bottom BORDER_MARGIN
  540. expanded_tab_height /= num_expanded;
  541. return expanded_tab_height;
  542. }