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

游戏引擎

开发平台:

C++ Builder

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