PageRenderTime 44ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/llscrollcontainer.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 714 lines | 534 code | 94 blank | 86 comment | 67 complexity | b9606b990136015315e8b87a8177cfb5 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llscrollcontainer.cpp
  3. * @brief LLScrollContainer base class
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llscrollcontainer.h"
  28. #include "llrender.h"
  29. #include "llcontainerview.h"
  30. #include "lllocalcliprect.h"
  31. // #include "llfolderview.h"
  32. #include "llscrollingpanellist.h"
  33. #include "llscrollbar.h"
  34. #include "llui.h"
  35. #include "llkeyboard.h"
  36. #include "llviewborder.h"
  37. #include "llfocusmgr.h"
  38. #include "llframetimer.h"
  39. #include "lluictrlfactory.h"
  40. #include "llpanel.h"
  41. #include "llfontgl.h"
  42. ///----------------------------------------------------------------------------
  43. /// Local function declarations, constants, enums, and typedefs
  44. ///----------------------------------------------------------------------------
  45. static const S32 HORIZONTAL_MULTIPLE = 8;
  46. static const S32 VERTICAL_MULTIPLE = 16;
  47. static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
  48. ///----------------------------------------------------------------------------
  49. /// Class LLScrollContainer
  50. ///----------------------------------------------------------------------------
  51. static LLDefaultChildRegistry::Register<LLScrollContainer> r("scroll_container");
  52. #include "llscrollingpanellist.h"
  53. #include "llcontainerview.h"
  54. #include "llpanel.h"
  55. static ScrollContainerRegistry::Register<LLScrollingPanelList> r1("scrolling_panel_list");
  56. static ScrollContainerRegistry::Register<LLContainerView> r2("container_view");
  57. static ScrollContainerRegistry::Register<LLPanel> r3("panel", &LLPanel::fromXML);
  58. LLScrollContainer::Params::Params()
  59. : is_opaque("opaque"),
  60. bg_color("color"),
  61. border_visible("border_visible"),
  62. hide_scrollbar("hide_scrollbar"),
  63. min_auto_scroll_rate("min_auto_scroll_rate", 100),
  64. max_auto_scroll_rate("max_auto_scroll_rate", 1000),
  65. reserve_scroll_corner("reserve_scroll_corner", false)
  66. {}
  67. // Default constructor
  68. LLScrollContainer::LLScrollContainer(const LLScrollContainer::Params& p)
  69. : LLUICtrl(p),
  70. mAutoScrolling( FALSE ),
  71. mAutoScrollRate( 0.f ),
  72. mBackgroundColor(p.bg_color()),
  73. mIsOpaque(p.is_opaque),
  74. mHideScrollbar(p.hide_scrollbar),
  75. mReserveScrollCorner(p.reserve_scroll_corner),
  76. mMinAutoScrollRate(p.min_auto_scroll_rate),
  77. mMaxAutoScrollRate(p.max_auto_scroll_rate),
  78. mScrolledView(NULL)
  79. {
  80. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  81. LLRect border_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
  82. LLViewBorder::Params params;
  83. params.name("scroll border");
  84. params.rect(border_rect);
  85. params.visible(p.border_visible);
  86. params.bevel_style(LLViewBorder::BEVEL_IN);
  87. mBorder = LLUICtrlFactory::create<LLViewBorder> (params);
  88. LLView::addChild( mBorder );
  89. mInnerRect.set( 0, getRect().getHeight(), getRect().getWidth(), 0 );
  90. mInnerRect.stretch( -getBorderWidth() );
  91. LLRect vertical_scroll_rect = mInnerRect;
  92. vertical_scroll_rect.mLeft = vertical_scroll_rect.mRight - scrollbar_size;
  93. LLScrollbar::Params sbparams;
  94. sbparams.name("scrollable vertical");
  95. sbparams.rect(vertical_scroll_rect);
  96. sbparams.orientation(LLScrollbar::VERTICAL);
  97. sbparams.doc_size(mInnerRect.getHeight());
  98. sbparams.doc_pos(0);
  99. sbparams.page_size(mInnerRect.getHeight());
  100. sbparams.step_size(VERTICAL_MULTIPLE);
  101. sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
  102. sbparams.visible(false);
  103. sbparams.change_callback(p.scroll_callback);
  104. mScrollbar[VERTICAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams);
  105. LLView::addChild( mScrollbar[VERTICAL] );
  106. LLRect horizontal_scroll_rect = mInnerRect;
  107. horizontal_scroll_rect.mTop = horizontal_scroll_rect.mBottom + scrollbar_size;
  108. sbparams.name("scrollable horizontal");
  109. sbparams.rect(horizontal_scroll_rect);
  110. sbparams.orientation(LLScrollbar::HORIZONTAL);
  111. sbparams.doc_size(mInnerRect.getWidth());
  112. sbparams.doc_pos(0);
  113. sbparams.page_size(mInnerRect.getWidth());
  114. sbparams.step_size(VERTICAL_MULTIPLE);
  115. sbparams.visible(false);
  116. sbparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT);
  117. sbparams.change_callback(p.scroll_callback);
  118. mScrollbar[HORIZONTAL] = LLUICtrlFactory::create<LLScrollbar> (sbparams);
  119. LLView::addChild( mScrollbar[HORIZONTAL] );
  120. }
  121. // Destroys the object
  122. LLScrollContainer::~LLScrollContainer( void )
  123. {
  124. // mScrolledView and mScrollbar are child views, so the LLView
  125. // destructor takes care of memory deallocation.
  126. for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
  127. {
  128. mScrollbar[i] = NULL;
  129. }
  130. mScrolledView = NULL;
  131. }
  132. // internal scrollbar handlers
  133. // virtual
  134. void LLScrollContainer::scrollHorizontal( S32 new_pos )
  135. {
  136. //llinfos << "LLScrollContainer::scrollHorizontal()" << llendl;
  137. if( mScrolledView )
  138. {
  139. LLRect doc_rect = mScrolledView->getRect();
  140. S32 old_pos = -(doc_rect.mLeft - mInnerRect.mLeft);
  141. mScrolledView->translate( -(new_pos - old_pos), 0 );
  142. }
  143. }
  144. // virtual
  145. void LLScrollContainer::scrollVertical( S32 new_pos )
  146. {
  147. // llinfos << "LLScrollContainer::scrollVertical() " << new_pos << llendl;
  148. if( mScrolledView )
  149. {
  150. LLRect doc_rect = mScrolledView->getRect();
  151. S32 old_pos = doc_rect.mTop - mInnerRect.mTop;
  152. mScrolledView->translate( 0, new_pos - old_pos );
  153. }
  154. }
  155. // LLView functionality
  156. void LLScrollContainer::reshape(S32 width, S32 height,
  157. BOOL called_from_parent)
  158. {
  159. LLUICtrl::reshape( width, height, called_from_parent );
  160. mInnerRect = getLocalRect();
  161. mInnerRect.stretch( -getBorderWidth() );
  162. if (mScrolledView)
  163. {
  164. const LLRect& scrolled_rect = mScrolledView->getRect();
  165. S32 visible_width = 0;
  166. S32 visible_height = 0;
  167. BOOL show_v_scrollbar = FALSE;
  168. BOOL show_h_scrollbar = FALSE;
  169. calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
  170. mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() );
  171. mScrollbar[VERTICAL]->setPageSize( visible_height );
  172. mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() );
  173. mScrollbar[HORIZONTAL]->setPageSize( visible_width );
  174. updateScroll();
  175. }
  176. }
  177. BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask)
  178. {
  179. // allow scrolled view to handle keystrokes in case it delegated keyboard focus
  180. // to the scroll container.
  181. // NOTE: this should not recurse indefinitely as handleKeyHere
  182. // should not propagate to parent controls, so mScrolledView should *not*
  183. // call LLScrollContainer::handleKeyHere in turn
  184. if (mScrolledView && mScrolledView->handleKeyHere(key, mask))
  185. {
  186. return TRUE;
  187. }
  188. for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
  189. {
  190. if( mScrollbar[i]->handleKeyHere(key, mask) )
  191. {
  192. updateScroll();
  193. return TRUE;
  194. }
  195. }
  196. return FALSE;
  197. }
  198. BOOL LLScrollContainer::handleUnicodeCharHere(llwchar uni_char)
  199. {
  200. if (mScrolledView && mScrolledView->handleUnicodeCharHere(uni_char))
  201. {
  202. return TRUE;
  203. }
  204. return FALSE;
  205. }
  206. BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
  207. {
  208. // Give event to my child views - they may have scroll bars
  209. // (Bad UI design, but technically possible.)
  210. if (LLUICtrl::handleScrollWheel(x,y,clicks))
  211. return TRUE;
  212. // When the vertical scrollbar is visible, scroll wheel
  213. // only affects vertical scrolling. It's confusing to have
  214. // scroll wheel perform both vertical and horizontal in a
  215. // single container.
  216. LLScrollbar* vertical = mScrollbar[VERTICAL];
  217. if (vertical->getVisible()
  218. && vertical->getEnabled())
  219. {
  220. // Pretend the mouse is over the scrollbar
  221. if (vertical->handleScrollWheel( 0, 0, clicks ) )
  222. {
  223. updateScroll();
  224. }
  225. // Always eat the event
  226. return TRUE;
  227. }
  228. LLScrollbar* horizontal = mScrollbar[HORIZONTAL];
  229. // Test enablement and visibility for consistency with
  230. // LLView::childrenHandleScrollWheel().
  231. if (horizontal->getVisible()
  232. && horizontal->getEnabled()
  233. && horizontal->handleScrollWheel( 0, 0, clicks ) )
  234. {
  235. updateScroll();
  236. return TRUE;
  237. }
  238. return FALSE;
  239. }
  240. BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
  241. BOOL drop,
  242. EDragAndDropType cargo_type,
  243. void* cargo_data,
  244. EAcceptance* accept,
  245. std::string& tooltip_msg)
  246. {
  247. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  248. // Scroll folder view if needed. Never accepts a drag or drop.
  249. *accept = ACCEPT_NO;
  250. BOOL handled = autoScroll(x, y);
  251. if( !handled )
  252. {
  253. handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
  254. cargo_data, accept, tooltip_msg) != NULL;
  255. }
  256. return TRUE;
  257. }
  258. bool LLScrollContainer::autoScroll(S32 x, S32 y)
  259. {
  260. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  261. bool scrolling = false;
  262. if( mScrollbar[HORIZONTAL]->getVisible() || mScrollbar[VERTICAL]->getVisible() )
  263. {
  264. LLRect screen_local_extents;
  265. screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents);
  266. LLRect inner_rect_local( 0, mInnerRect.getHeight(), mInnerRect.getWidth(), 0 );
  267. if( mScrollbar[HORIZONTAL]->getVisible() )
  268. {
  269. inner_rect_local.mBottom += scrollbar_size;
  270. }
  271. if( mScrollbar[VERTICAL]->getVisible() )
  272. {
  273. inner_rect_local.mRight -= scrollbar_size;
  274. }
  275. // clip rect against root view
  276. inner_rect_local.intersectWith(screen_local_extents);
  277. S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32());
  278. // autoscroll region should take up no more than one third of visible scroller area
  279. S32 auto_scroll_region_width = llmin(inner_rect_local.getWidth() / 3, 10);
  280. S32 auto_scroll_region_height = llmin(inner_rect_local.getHeight() / 3, 10);
  281. if( mScrollbar[HORIZONTAL]->getVisible() )
  282. {
  283. LLRect left_scroll_rect = screen_local_extents;
  284. left_scroll_rect.mRight = inner_rect_local.mLeft + auto_scroll_region_width;
  285. if( left_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() > 0) )
  286. {
  287. mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() - auto_scroll_speed );
  288. mAutoScrolling = TRUE;
  289. scrolling = true;
  290. }
  291. LLRect right_scroll_rect = screen_local_extents;
  292. right_scroll_rect.mLeft = inner_rect_local.mRight - auto_scroll_region_width;
  293. if( right_scroll_rect.pointInRect( x, y ) && (mScrollbar[HORIZONTAL]->getDocPos() < mScrollbar[HORIZONTAL]->getDocPosMax()) )
  294. {
  295. mScrollbar[HORIZONTAL]->setDocPos( mScrollbar[HORIZONTAL]->getDocPos() + auto_scroll_speed );
  296. mAutoScrolling = TRUE;
  297. scrolling = true;
  298. }
  299. }
  300. if( mScrollbar[VERTICAL]->getVisible() )
  301. {
  302. LLRect bottom_scroll_rect = screen_local_extents;
  303. bottom_scroll_rect.mTop = inner_rect_local.mBottom + auto_scroll_region_height;
  304. if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() < mScrollbar[VERTICAL]->getDocPosMax()) )
  305. {
  306. mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() + auto_scroll_speed );
  307. mAutoScrolling = TRUE;
  308. scrolling = true;
  309. }
  310. LLRect top_scroll_rect = screen_local_extents;
  311. top_scroll_rect.mBottom = inner_rect_local.mTop - auto_scroll_region_height;
  312. if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar[VERTICAL]->getDocPos() > 0) )
  313. {
  314. mScrollbar[VERTICAL]->setDocPos( mScrollbar[VERTICAL]->getDocPos() - auto_scroll_speed );
  315. mAutoScrolling = TRUE;
  316. scrolling = true;
  317. }
  318. }
  319. }
  320. return scrolling;
  321. }
  322. void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const
  323. {
  324. const LLRect& doc_rect = getScrolledViewRect();
  325. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  326. S32 doc_width = doc_rect.getWidth();
  327. S32 doc_height = doc_rect.getHeight();
  328. S32 border_width = getBorderWidth();
  329. *visible_width = getRect().getWidth() - 2 * border_width;
  330. *visible_height = getRect().getHeight() - 2 * border_width;
  331. *show_v_scrollbar = FALSE;
  332. *show_h_scrollbar = FALSE;
  333. if (!mHideScrollbar)
  334. {
  335. if( *visible_height < doc_height )
  336. {
  337. *show_v_scrollbar = TRUE;
  338. *visible_width -= scrollbar_size;
  339. }
  340. if( *visible_width < doc_width )
  341. {
  342. *show_h_scrollbar = TRUE;
  343. *visible_height -= scrollbar_size;
  344. // Must retest now that visible_height has changed
  345. if( !*show_v_scrollbar && (*visible_height < doc_height) )
  346. {
  347. *show_v_scrollbar = TRUE;
  348. *visible_width -= scrollbar_size;
  349. }
  350. }
  351. }
  352. }
  353. void LLScrollContainer::draw()
  354. {
  355. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  356. if (mAutoScrolling)
  357. {
  358. // add acceleration to autoscroll
  359. mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), mMaxAutoScrollRate);
  360. }
  361. else
  362. {
  363. // reset to minimum for next time
  364. mAutoScrollRate = mMinAutoScrollRate;
  365. }
  366. // clear this flag to be set on next call to autoScroll
  367. mAutoScrolling = FALSE;
  368. // auto-focus when scrollbar active
  369. // this allows us to capture user intent (i.e. stop automatically scrolling the view/etc)
  370. if (!hasFocus()
  371. && (mScrollbar[VERTICAL]->hasMouseCapture() || mScrollbar[HORIZONTAL]->hasMouseCapture()))
  372. {
  373. focusFirstItem();
  374. }
  375. if (getRect().isValid())
  376. {
  377. // Draw background
  378. if( mIsOpaque )
  379. {
  380. F32 alpha = getCurrentTransparency();
  381. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  382. gl_rect_2d(mInnerRect, mBackgroundColor.get() % alpha);
  383. }
  384. // Draw mScrolledViews and update scroll bars.
  385. // get a scissor region ready, and draw the scrolling view. The
  386. // scissor region ensures that we don't draw outside of the bounds
  387. // of the rectangle.
  388. if( mScrolledView )
  389. {
  390. updateScroll();
  391. // Draw the scrolled area.
  392. {
  393. S32 visible_width = 0;
  394. S32 visible_height = 0;
  395. BOOL show_v_scrollbar = FALSE;
  396. BOOL show_h_scrollbar = FALSE;
  397. calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
  398. LLLocalClipRect clip(LLRect(mInnerRect.mLeft,
  399. mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height,
  400. mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0),
  401. mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0)
  402. ));
  403. drawChild(mScrolledView);
  404. }
  405. }
  406. // Highlight border if a child of this container has keyboard focus
  407. if( mBorder->getVisible() )
  408. {
  409. mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus(this) );
  410. }
  411. // Draw all children except mScrolledView
  412. // Note: scrollbars have been adjusted by above drawing code
  413. for (child_list_const_reverse_iter_t child_iter = getChildList()->rbegin();
  414. child_iter != getChildList()->rend(); ++child_iter)
  415. {
  416. LLView *viewp = *child_iter;
  417. if( sDebugRects )
  418. {
  419. sDepth++;
  420. }
  421. if( (viewp != mScrolledView) && viewp->getVisible() )
  422. {
  423. drawChild(viewp);
  424. }
  425. if( sDebugRects )
  426. {
  427. sDepth--;
  428. }
  429. }
  430. }
  431. } // end draw
  432. bool LLScrollContainer::addChild(LLView* view, S32 tab_group)
  433. {
  434. if (!mScrolledView)
  435. {
  436. // Use the first panel or container as the scrollable view (bit of a hack)
  437. mScrolledView = view;
  438. }
  439. bool ret_val = LLView::addChild(view, tab_group);
  440. //bring the scrollbars to the front
  441. sendChildToFront( mScrollbar[HORIZONTAL] );
  442. sendChildToFront( mScrollbar[VERTICAL] );
  443. return ret_val;
  444. }
  445. void LLScrollContainer::updateScroll()
  446. {
  447. if (!mScrolledView)
  448. {
  449. return;
  450. }
  451. static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
  452. LLRect doc_rect = mScrolledView->getRect();
  453. S32 doc_width = doc_rect.getWidth();
  454. S32 doc_height = doc_rect.getHeight();
  455. S32 visible_width = 0;
  456. S32 visible_height = 0;
  457. BOOL show_v_scrollbar = FALSE;
  458. BOOL show_h_scrollbar = FALSE;
  459. calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
  460. S32 border_width = getBorderWidth();
  461. if( show_v_scrollbar )
  462. {
  463. if( doc_rect.mTop < getRect().getHeight() - border_width )
  464. {
  465. mScrolledView->translate( 0, getRect().getHeight() - border_width - doc_rect.mTop );
  466. }
  467. scrollVertical( mScrollbar[VERTICAL]->getDocPos() );
  468. mScrollbar[VERTICAL]->setVisible( TRUE );
  469. S32 v_scrollbar_height = visible_height;
  470. if( !show_h_scrollbar && mReserveScrollCorner )
  471. {
  472. v_scrollbar_height -= scrollbar_size;
  473. }
  474. mScrollbar[VERTICAL]->reshape( scrollbar_size, v_scrollbar_height, TRUE );
  475. // Make room for the horizontal scrollbar (or not)
  476. S32 v_scrollbar_offset = 0;
  477. if( show_h_scrollbar || mReserveScrollCorner )
  478. {
  479. v_scrollbar_offset = scrollbar_size;
  480. }
  481. LLRect r = mScrollbar[VERTICAL]->getRect();
  482. r.translate( 0, mInnerRect.mBottom - r.mBottom + v_scrollbar_offset );
  483. mScrollbar[VERTICAL]->setRect( r );
  484. }
  485. else
  486. {
  487. mScrolledView->translate( 0, getRect().getHeight() - border_width - doc_rect.mTop );
  488. mScrollbar[VERTICAL]->setVisible( FALSE );
  489. mScrollbar[VERTICAL]->setDocPos( 0 );
  490. }
  491. if( show_h_scrollbar )
  492. {
  493. if( doc_rect.mLeft > border_width )
  494. {
  495. mScrolledView->translate( border_width - doc_rect.mLeft, 0 );
  496. mScrollbar[HORIZONTAL]->setDocPos( 0 );
  497. }
  498. else
  499. {
  500. scrollHorizontal( mScrollbar[HORIZONTAL]->getDocPos() );
  501. }
  502. mScrollbar[HORIZONTAL]->setVisible( TRUE );
  503. S32 h_scrollbar_width = visible_width;
  504. if( !show_v_scrollbar && mReserveScrollCorner )
  505. {
  506. h_scrollbar_width -= scrollbar_size;
  507. }
  508. mScrollbar[HORIZONTAL]->reshape( h_scrollbar_width, scrollbar_size, TRUE );
  509. }
  510. else
  511. {
  512. mScrolledView->translate( border_width - doc_rect.mLeft, 0 );
  513. mScrollbar[HORIZONTAL]->setVisible( FALSE );
  514. mScrollbar[HORIZONTAL]->setDocPos( 0 );
  515. }
  516. mScrollbar[HORIZONTAL]->setDocSize( doc_width );
  517. mScrollbar[HORIZONTAL]->setPageSize( visible_width );
  518. mScrollbar[VERTICAL]->setDocSize( doc_height );
  519. mScrollbar[VERTICAL]->setPageSize( visible_height );
  520. } // end updateScroll
  521. void LLScrollContainer::setBorderVisible(BOOL b)
  522. {
  523. mBorder->setVisible( b );
  524. // Recompute inner rect, as border visibility changes it
  525. mInnerRect = getLocalRect();
  526. mInnerRect.stretch( -getBorderWidth() );
  527. }
  528. LLRect LLScrollContainer::getVisibleContentRect()
  529. {
  530. updateScroll();
  531. LLRect visible_rect = getContentWindowRect();
  532. LLRect contents_rect = mScrolledView->getRect();
  533. visible_rect.translate(-contents_rect.mLeft, -contents_rect.mBottom);
  534. return visible_rect;
  535. }
  536. LLRect LLScrollContainer::getContentWindowRect()
  537. {
  538. updateScroll();
  539. LLRect scroller_view_rect;
  540. S32 visible_width = 0;
  541. S32 visible_height = 0;
  542. BOOL show_h_scrollbar = FALSE;
  543. BOOL show_v_scrollbar = FALSE;
  544. calcVisibleSize( &visible_width, &visible_height, &show_h_scrollbar, &show_v_scrollbar );
  545. S32 border_width = getBorderWidth();
  546. scroller_view_rect.setOriginAndSize(border_width,
  547. show_h_scrollbar ? mScrollbar[HORIZONTAL]->getRect().mTop : border_width,
  548. visible_width,
  549. visible_height);
  550. return scroller_view_rect;
  551. }
  552. // rect is in document coordinates, constraint is in display coordinates relative to content window rect
  553. void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLRect& constraint)
  554. {
  555. if (!mScrolledView)
  556. {
  557. llwarns << "LLScrollContainer::scrollToShowRect with no view!" << llendl;
  558. return;
  559. }
  560. LLRect content_window_rect = getContentWindowRect();
  561. // get document rect
  562. LLRect scrolled_rect = mScrolledView->getRect();
  563. // shrink target rect to fit within constraint region, biasing towards top left
  564. LLRect rect_to_constrain = rect;
  565. rect_to_constrain.mBottom = llmax(rect_to_constrain.mBottom, rect_to_constrain.mTop - constraint.getHeight());
  566. rect_to_constrain.mRight = llmin(rect_to_constrain.mRight, rect_to_constrain.mLeft + constraint.getWidth());
  567. // calculate allowable positions for scroller window in document coordinates
  568. LLRect allowable_scroll_rect(rect_to_constrain.mRight - constraint.mRight,
  569. rect_to_constrain.mBottom - constraint.mBottom,
  570. rect_to_constrain.mLeft - constraint.mLeft,
  571. rect_to_constrain.mTop - constraint.mTop);
  572. // translate from allowable region for lower left corner to upper left corner
  573. allowable_scroll_rect.translate(0, content_window_rect.getHeight());
  574. S32 vert_pos = llclamp(mScrollbar[VERTICAL]->getDocPos(),
  575. mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mTop, // min vertical scroll
  576. mScrollbar[VERTICAL]->getDocSize() - allowable_scroll_rect.mBottom); // max vertical scroll
  577. mScrollbar[VERTICAL]->setDocSize( scrolled_rect.getHeight() );
  578. mScrollbar[VERTICAL]->setPageSize( content_window_rect.getHeight() );
  579. mScrollbar[VERTICAL]->setDocPos( vert_pos );
  580. S32 horizontal_pos = llclamp(mScrollbar[HORIZONTAL]->getDocPos(),
  581. allowable_scroll_rect.mLeft,
  582. allowable_scroll_rect.mRight);
  583. mScrollbar[HORIZONTAL]->setDocSize( scrolled_rect.getWidth() );
  584. mScrollbar[HORIZONTAL]->setPageSize( content_window_rect.getWidth() );
  585. mScrollbar[HORIZONTAL]->setDocPos( horizontal_pos );
  586. // propagate scroll to document
  587. updateScroll();
  588. // In case we are in accordion tab notify parent to show selected rectangle
  589. LLRect screen_rc;
  590. localRectToScreen(rect_to_constrain, &screen_rc);
  591. notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
  592. }
  593. void LLScrollContainer::pageUp(S32 overlap)
  594. {
  595. mScrollbar[VERTICAL]->pageUp(overlap);
  596. updateScroll();
  597. }
  598. void LLScrollContainer::pageDown(S32 overlap)
  599. {
  600. mScrollbar[VERTICAL]->pageDown(overlap);
  601. updateScroll();
  602. }
  603. void LLScrollContainer::goToTop()
  604. {
  605. mScrollbar[VERTICAL]->setDocPos(0);
  606. updateScroll();
  607. }
  608. void LLScrollContainer::goToBottom()
  609. {
  610. mScrollbar[VERTICAL]->setDocPos(mScrollbar[VERTICAL]->getDocSize());
  611. updateScroll();
  612. }
  613. S32 LLScrollContainer::getBorderWidth() const
  614. {
  615. if (mBorder->getVisible())
  616. {
  617. return mBorder->getBorderWidth();
  618. }
  619. return 0;
  620. }