llscrollbar.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. /**
  2. * @file llscrollbar.cpp
  3. * @brief Scrollbar UI widget
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, 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 "llscrollbar.h"
  34. #include "llbutton.h"
  35. #include "llcontrol.h"
  36. #include "llcriticaldamp.h"
  37. #include "llkeyboard.h"
  38. #include "llrender.h"
  39. #include "lltimer.h"
  40. #include "llwindow.h"
  41. #include "llcolor3.h"
  42. LLScrollbar::LLScrollbar(const std::string& name, LLRect rect,
  43. LLScrollbar::ORIENTATION orientation,
  44. S32 doc_size, S32 doc_pos, S32 page_size,
  45. void (*change_callback)(S32, LLScrollbar*, void*),
  46. void* callback_user_data, S32 step_size)
  47. : LLUICtrl(name, rect, true, NULL, NULL),
  48. mChangeCallback(change_callback),
  49. mCallbackUserData(callback_user_data),
  50. mOrientation(orientation),
  51. mDocSize(doc_size),
  52. mDocPos(doc_pos),
  53. mPageSize(page_size),
  54. mStepSize(step_size),
  55. mDocChanged(false),
  56. mDragStartX(0),
  57. mDragStartY(0),
  58. mHoverGlowStrength(0.15f),
  59. mCurGlowStrength(0.f),
  60. mTrackColor(LLUI::sScrollbarTrackColor),
  61. mThumbColor(LLUI::sScrollbarThumbColor),
  62. mHighlightColor(LLUI::sDefaultHighlightLight),
  63. mShadowColor(LLUI::sDefaultShadowLight),
  64. mOnScrollEndCallback(NULL),
  65. mOnScrollEndData(NULL)
  66. {
  67. setTabStop(false);
  68. updateThumbRect();
  69. // Page up and page down buttons
  70. LLRect line_up_rect;
  71. std::string line_up_img;
  72. std::string line_up_selected_img;
  73. std::string line_down_img;
  74. std::string line_down_selected_img;
  75. LLRect line_down_rect;
  76. if (LLScrollbar::VERTICAL == mOrientation)
  77. {
  78. line_up_rect.setLeftTopAndSize(0, getRect().getHeight(),
  79. SCROLLBAR_SIZE, SCROLLBAR_SIZE);
  80. line_up_img = "UIImgBtnScrollUpOutUUID";
  81. line_up_selected_img = "UIImgBtnScrollUpInUUID";
  82. line_down_rect.setOriginAndSize(0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE);
  83. line_down_img = "UIImgBtnScrollDownOutUUID";
  84. line_down_selected_img = "UIImgBtnScrollDownInUUID";
  85. }
  86. else
  87. {
  88. // Horizontal
  89. line_up_rect.setOriginAndSize(0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE);
  90. line_up_img = "UIImgBtnScrollLeftOutUUID";
  91. line_up_selected_img = "UIImgBtnScrollLeftInUUID";
  92. line_down_rect.setOriginAndSize(getRect().getWidth() - SCROLLBAR_SIZE,
  93. 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE);
  94. line_down_img = "UIImgBtnScrollRightOutUUID";
  95. line_down_selected_img = "UIImgBtnScrollRightInUUID";
  96. }
  97. LLButton* line_up_btn = new LLButton("Line Up", line_up_rect, line_up_img,
  98. line_up_selected_img, NULL,
  99. &LLScrollbar::onLineUpBtnPressed,
  100. this, LLFontGL::getFontSansSerif());
  101. if (LLScrollbar::VERTICAL == mOrientation)
  102. {
  103. line_up_btn->setFollowsRight();
  104. line_up_btn->setFollowsTop();
  105. }
  106. else
  107. {
  108. // horizontal
  109. line_up_btn->setFollowsLeft();
  110. line_up_btn->setFollowsBottom();
  111. }
  112. line_up_btn->setHeldDownCallback(&LLScrollbar::onLineUpBtnPressed);
  113. line_up_btn->setTabStop(false);
  114. line_up_btn->setScaleImage(true);
  115. addChild(line_up_btn);
  116. LLButton* line_down_btn =
  117. new LLButton("Line Down", line_down_rect, line_down_img,
  118. line_down_selected_img, NULL,
  119. &LLScrollbar::onLineDownBtnPressed, this,
  120. LLFontGL::getFontSansSerif());
  121. line_down_btn->setFollowsRight();
  122. line_down_btn->setFollowsBottom();
  123. line_down_btn->setHeldDownCallback(&LLScrollbar::onLineDownBtnPressed);
  124. line_down_btn->setTabStop(false);
  125. line_down_btn->setScaleImage(true);
  126. addChild(line_down_btn);
  127. }
  128. LLScrollbar::~LLScrollbar()
  129. {
  130. // Children buttons killed by parent class
  131. }
  132. void LLScrollbar::setDocParams(S32 size, S32 pos)
  133. {
  134. mDocSize = size;
  135. setDocPos(pos);
  136. mDocChanged = true;
  137. updateThumbRect();
  138. }
  139. void LLScrollbar::setDocPos(S32 pos, bool update_thumb)
  140. {
  141. pos = llclamp(pos, 0, getDocPosMax());
  142. if (pos != mDocPos)
  143. {
  144. mDocPos = pos;
  145. mDocChanged = true;
  146. if (mChangeCallback)
  147. {
  148. mChangeCallback(mDocPos, this, mCallbackUserData);
  149. }
  150. if (update_thumb)
  151. {
  152. updateThumbRect();
  153. }
  154. }
  155. }
  156. void LLScrollbar::setDocSize(S32 size)
  157. {
  158. if (size != mDocSize)
  159. {
  160. mDocSize = size;
  161. setDocPos(mDocPos);
  162. mDocChanged = true;
  163. updateThumbRect();
  164. }
  165. }
  166. void LLScrollbar::setPageSize(S32 page_size)
  167. {
  168. if (page_size != mPageSize)
  169. {
  170. mPageSize = page_size;
  171. setDocPos(mDocPos);
  172. mDocChanged = true;
  173. updateThumbRect();
  174. }
  175. }
  176. void LLScrollbar::updateThumbRect()
  177. {
  178. constexpr S32 THUMB_MIN_LENGTH = 16;
  179. S32 window_length =
  180. mOrientation == LLScrollbar::HORIZONTAL ? getRect().getWidth()
  181. : getRect().getHeight();
  182. S32 thumb_bg_length = llmax(0, window_length - 2 * SCROLLBAR_SIZE);
  183. S32 visible_lines = llmin(mDocSize, mPageSize);
  184. S32 thumb_length =
  185. mDocSize ? llmin(llmax(visible_lines * thumb_bg_length / mDocSize,
  186. THUMB_MIN_LENGTH),
  187. thumb_bg_length)
  188. : thumb_bg_length;
  189. S32 variable_lines = mDocSize - visible_lines;
  190. if (mOrientation == LLScrollbar::VERTICAL)
  191. {
  192. S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE;
  193. S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH;
  194. S32 thumb_start =
  195. variable_lines ? llmin(llmax(thumb_start_max - mDocPos *
  196. (thumb_bg_length - thumb_length) /
  197. variable_lines, thumb_start_min),
  198. thumb_start_max)
  199. : thumb_start_max;
  200. mThumbRect.mLeft = 0;
  201. mThumbRect.mTop = thumb_start;
  202. mThumbRect.mRight = SCROLLBAR_SIZE;
  203. mThumbRect.mBottom = thumb_start - thumb_length;
  204. }
  205. else
  206. {
  207. // Horizontal
  208. S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length;
  209. S32 thumb_start_min = SCROLLBAR_SIZE;
  210. S32 thumb_start =
  211. variable_lines ? llmin(llmax(thumb_start_min + mDocPos *
  212. (thumb_bg_length - thumb_length) /
  213. variable_lines, thumb_start_min),
  214. thumb_start_max)
  215. : thumb_start_min;
  216. mThumbRect.mLeft = thumb_start;
  217. mThumbRect.mTop = SCROLLBAR_SIZE;
  218. mThumbRect.mRight = thumb_start + thumb_length;
  219. mThumbRect.mBottom = 0;
  220. }
  221. if (mOnScrollEndCallback && mOnScrollEndData && mDocPos == getDocPosMax())
  222. {
  223. mOnScrollEndCallback(mOnScrollEndData);
  224. }
  225. }
  226. bool LLScrollbar::handleMouseDown(S32 x, S32 y, MASK mask)
  227. {
  228. // Check children first
  229. if (LLView::childrenHandleMouseDown(x, y, mask) == NULL)
  230. {
  231. if (mThumbRect.pointInRect(x, y))
  232. {
  233. // Start dragging the thumb. No handler needed for focus lost since
  234. // this clas has no state that depends on it.
  235. gFocusMgr.setMouseCapture(this);
  236. mDragStartX = x;
  237. mDragStartY = y;
  238. mOrigRect.mTop = mThumbRect.mTop;
  239. mOrigRect.mBottom = mThumbRect.mBottom;
  240. mOrigRect.mLeft = mThumbRect.mLeft;
  241. mOrigRect.mRight = mThumbRect.mRight;
  242. mLastDelta = 0;
  243. }
  244. else
  245. {
  246. if ((LLScrollbar::VERTICAL == mOrientation &&
  247. mThumbRect.mTop < y) ||
  248. (LLScrollbar::HORIZONTAL == mOrientation &&
  249. x < mThumbRect.mLeft))
  250. {
  251. // Page up
  252. pageUp(0);
  253. }
  254. else
  255. if ((LLScrollbar::VERTICAL == mOrientation &&
  256. y < mThumbRect.mBottom) ||
  257. (LLScrollbar::HORIZONTAL == mOrientation &&
  258. mThumbRect.mRight < x))
  259. {
  260. // Page down
  261. pageDown(0);
  262. }
  263. }
  264. }
  265. return true;
  266. }
  267. bool LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
  268. {
  269. // Note: we do not bother sending the event to the children (the arrow
  270. // buttons) because they will capture the mouse whenever they need hover
  271. // events.
  272. bool handled = false;
  273. if (hasMouseCapture())
  274. {
  275. S32 height = getRect().getHeight();
  276. S32 width = getRect().getWidth();
  277. if (VERTICAL == mOrientation)
  278. {
  279. S32 delta_pixels = y - mDragStartY;
  280. if (mOrigRect.mBottom + delta_pixels < SCROLLBAR_SIZE)
  281. {
  282. delta_pixels = SCROLLBAR_SIZE - mOrigRect.mBottom - 1;
  283. }
  284. else if (mOrigRect.mTop + delta_pixels > height - SCROLLBAR_SIZE)
  285. {
  286. delta_pixels = height - SCROLLBAR_SIZE - mOrigRect.mTop + 1;
  287. }
  288. mThumbRect.mTop = mOrigRect.mTop + delta_pixels;
  289. mThumbRect.mBottom = mOrigRect.mBottom + delta_pixels;
  290. S32 thumb_length = mThumbRect.getHeight();
  291. S32 thumb_track_length = height - 2 * SCROLLBAR_SIZE;
  292. if (delta_pixels != mLastDelta || mDocChanged)
  293. {
  294. // Note: delta_pixels increases as you go up. mDocPos increases
  295. // down (line 0 is at the top of the page).
  296. S32 usable_track_length = thumb_track_length - thumb_length;
  297. if (0 < usable_track_length)
  298. {
  299. S32 variable_lines = getDocPosMax();
  300. S32 pos = mThumbRect.mTop;
  301. F32 ratio = F32(pos - SCROLLBAR_SIZE - thumb_length) /
  302. usable_track_length;
  303. S32 new_pos = llclamp(S32(variable_lines - ratio *
  304. variable_lines + 0.5f),
  305. 0, variable_lines);
  306. // Note: we do not call updateThumbRect() here. Instead we
  307. // let the thumb and the document go slightly out of sync
  308. // (less than a line's worth) to make the thumb feel
  309. // responsive.
  310. changeLine(new_pos - mDocPos, false);
  311. }
  312. }
  313. mLastDelta = delta_pixels;
  314. }
  315. else // Horizontal
  316. {
  317. S32 delta_pixels = x - mDragStartX;
  318. if (mOrigRect.mLeft + delta_pixels < SCROLLBAR_SIZE)
  319. {
  320. delta_pixels = SCROLLBAR_SIZE - mOrigRect.mLeft - 1;
  321. }
  322. else if (mOrigRect.mRight + delta_pixels > width - SCROLLBAR_SIZE)
  323. {
  324. delta_pixels = width - SCROLLBAR_SIZE - mOrigRect.mRight + 1;
  325. }
  326. mThumbRect.mLeft = mOrigRect.mLeft + delta_pixels;
  327. mThumbRect.mRight = mOrigRect.mRight + delta_pixels;
  328. S32 thumb_length = mThumbRect.getWidth();
  329. S32 thumb_track_length = width - 2 * SCROLLBAR_SIZE;
  330. if (delta_pixels != mLastDelta || mDocChanged)
  331. {
  332. // Note: delta_pixels increases as you go up. mDocPos increases
  333. // down (line 0 is at the top of the page).
  334. S32 usable_track_length = thumb_track_length - thumb_length;
  335. if (0 < usable_track_length)
  336. {
  337. S32 variable_lines = getDocPosMax();
  338. S32 pos = mThumbRect.mLeft;
  339. F32 ratio = F32(pos - SCROLLBAR_SIZE) / usable_track_length;
  340. S32 new_pos = llclamp(S32(ratio * variable_lines + 0.5f),
  341. 0, variable_lines);
  342. // Note: we do not call updateThumbRect() here. Instead we
  343. // let the thumb and the document go slightly out of sync
  344. // (less than a line's worth) to make the thumb feel
  345. // responsive.
  346. changeLine(new_pos - mDocPos, false);
  347. }
  348. }
  349. mLastDelta = delta_pixels;
  350. }
  351. gWindowp->setCursor(UI_CURSOR_ARROW);
  352. LL_DEBUGS("UserInput") << "hover handled by " << getName()
  353. << " (active)" << LL_ENDL;
  354. handled = true;
  355. }
  356. else
  357. {
  358. handled = childrenHandleMouseUp(x, y, mask) != NULL;
  359. }
  360. // Opaque
  361. if (!handled)
  362. {
  363. gWindowp->setCursor(UI_CURSOR_ARROW);
  364. LL_DEBUGS("UserInput") << "hover handled by " << getName()
  365. << " (inactive)" << LL_ENDL;
  366. handled = true;
  367. }
  368. mDocChanged = false;
  369. return handled;
  370. }
  371. bool LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
  372. {
  373. changeLine(clicks * mStepSize, true);
  374. return true;
  375. }
  376. bool LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
  377. EDragAndDropType cargo_type,
  378. void *cargo_data, EAcceptance *accept,
  379. std::string &tooltip_msg)
  380. {
  381. #if 0 // Enable this to get drag and drop to control scrollbars
  382. if (!drop)
  383. {
  384. // TODO: refactor this
  385. S32 variable_lines = getDocPosMax();
  386. S32 pos = VERTICAL == mOrientation ? y : x;
  387. S32 thumb_length =
  388. VERTICAL == mOrientation ? mThumbRect.getHeight()
  389. : mThumbRect.getWidth();
  390. S32 thumb_track_length =
  391. VERTICAL == mOrientation ? getRect().getHeight() - 2 * SCROLLBAR_SIZE
  392. : getRect().getWidth() - 2 * SCROLLBAR_SIZE;
  393. S32 usable_track_length = thumb_track_length - thumb_length;
  394. F32 ratio =
  395. VERTICAL == mOrientation ? F32(pos - SCROLLBAR_SIZE -
  396. thumb_length) / usable_track_length
  397. : F32(pos - SCROLLBAR_SIZE) /
  398. usable_track_length;
  399. S32 new_pos =
  400. VERTICAL == mOrientation ? llclamp(S32(variable_lines -
  401. ratio * variable_lines +
  402. 0.5f), 0, variable_lines)
  403. : llclamp(S32(ratio * variable_lines +
  404. 0.5f),
  405. 0, variable_lines);
  406. changeLine(new_pos - mDocPos, true);
  407. }
  408. return true;
  409. #else
  410. return false;
  411. #endif
  412. }
  413. bool LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask)
  414. {
  415. bool handled = false;
  416. if (hasMouseCapture())
  417. {
  418. gFocusMgr.setMouseCapture(NULL);
  419. handled = true;
  420. }
  421. else
  422. {
  423. // Opaque, so don't just check children
  424. handled = LLView::handleMouseUp(x, y, mask);
  425. }
  426. return handled;
  427. }
  428. void LLScrollbar::reshape(S32 width, S32 height, bool called_from_parent)
  429. {
  430. if (width == getRect().getWidth() && height == getRect().getHeight())
  431. {
  432. return;
  433. }
  434. LLView::reshape(width, height, called_from_parent);
  435. LLButton* up_button = getChild<LLButton>("Line Up");
  436. LLButton* down_button = getChild<LLButton>("Line Down");
  437. if (mOrientation == VERTICAL)
  438. {
  439. up_button->reshape(up_button->getRect().getWidth(),
  440. llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE));
  441. down_button->reshape(down_button->getRect().getWidth(),
  442. llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE));
  443. up_button->setOrigin(up_button->getRect().mLeft,
  444. getRect().getHeight() - up_button->getRect().getHeight());
  445. }
  446. else
  447. {
  448. up_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE),
  449. up_button->getRect().getHeight());
  450. down_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE),
  451. down_button->getRect().getHeight());
  452. down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(),
  453. down_button->getRect().mBottom);
  454. }
  455. updateThumbRect();
  456. }
  457. void LLScrollbar::draw()
  458. {
  459. if (!getRect().isValid())
  460. {
  461. return;
  462. }
  463. S32 local_mouse_x;
  464. S32 local_mouse_y;
  465. LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
  466. bool other_captor = gFocusMgr.getMouseCapture() &&
  467. gFocusMgr.getMouseCapture() != this;
  468. bool hovered = getEnabled() && !other_captor &&
  469. (hasMouseCapture() ||
  470. mThumbRect.pointInRect(local_mouse_x, local_mouse_y));
  471. if (hovered)
  472. {
  473. mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength,
  474. LLCriticalDamp::getInterpolant(0.05f));
  475. }
  476. else
  477. {
  478. mCurGlowStrength = lerp(mCurGlowStrength, 0.f,
  479. LLCriticalDamp::getInterpolant(0.05f));
  480. }
  481. // Background
  482. if (mOrientation == HORIZONTAL)
  483. {
  484. LLUIImage::sRoundedSquare->drawSolid(SCROLLBAR_SIZE, 0,
  485. getRect().getWidth() -
  486. 2 * SCROLLBAR_SIZE,
  487. getRect().getHeight(),
  488. mTrackColor);
  489. }
  490. else
  491. {
  492. LLUIImage::sRoundedSquare->drawSolid(0, SCROLLBAR_SIZE,
  493. getRect().getWidth(),
  494. getRect().getHeight() -
  495. 2 * SCROLLBAR_SIZE,
  496. mTrackColor);
  497. }
  498. // Thumb
  499. LLRect outline_rect = mThumbRect;
  500. outline_rect.stretch(2);
  501. if (gFocusMgr.getKeyboardFocus() == this)
  502. {
  503. LLUIImage::sRoundedSquare->draw(outline_rect,
  504. gFocusMgr.getFocusColor());
  505. }
  506. LLUIImage::sRoundedSquare->draw(mThumbRect, mThumbColor);
  507. if (mCurGlowStrength > 0.01f)
  508. {
  509. gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
  510. LLUIImage::sRoundedSquare->drawSolid(mThumbRect,
  511. LLColor4(1.f, 1.f, 1.f,
  512. mCurGlowStrength));
  513. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  514. }
  515. bool was_scrolled_to_bottom = getDocPos() == getDocPosMax();
  516. if (mOnScrollEndCallback && was_scrolled_to_bottom)
  517. {
  518. mOnScrollEndCallback(mOnScrollEndData);
  519. }
  520. // Draw children
  521. LLView::draw();
  522. }
  523. void LLScrollbar::changeLine(S32 delta, bool update_thumb)
  524. {
  525. setDocPos(mDocPos + delta, update_thumb);
  526. }
  527. void LLScrollbar::setValue(const LLSD& value)
  528. {
  529. setDocPos((S32) value.asInteger());
  530. }
  531. bool LLScrollbar::handleKeyHere(KEY key, MASK mask)
  532. {
  533. bool handled = false;
  534. switch (key)
  535. {
  536. case KEY_HOME:
  537. setDocPos(0);
  538. handled = true;
  539. break;
  540. case KEY_END:
  541. setDocPos(getDocPosMax());
  542. handled = true;
  543. break;
  544. case KEY_DOWN:
  545. setDocPos(getDocPos() + mStepSize);
  546. handled = true;
  547. break;
  548. case KEY_UP:
  549. setDocPos(getDocPos() - mStepSize);
  550. handled = true;
  551. break;
  552. case KEY_PAGE_DOWN:
  553. pageDown(1);
  554. break;
  555. case KEY_PAGE_UP:
  556. pageUp(1);
  557. break;
  558. }
  559. return handled;
  560. }
  561. void LLScrollbar::pageUp(S32 overlap)
  562. {
  563. if (mDocSize > mPageSize)
  564. {
  565. changeLine(-(mPageSize - overlap), true);
  566. }
  567. }
  568. void LLScrollbar::pageDown(S32 overlap)
  569. {
  570. if (mDocSize > mPageSize)
  571. {
  572. changeLine(mPageSize - overlap, true);
  573. }
  574. }
  575. //static
  576. void LLScrollbar::onLineUpBtnPressed(void* userdata)
  577. {
  578. LLScrollbar* self = (LLScrollbar*)userdata;
  579. self->changeLine(- self->mStepSize, true);
  580. }
  581. //static
  582. void LLScrollbar::onLineDownBtnPressed(void* userdata)
  583. {
  584. LLScrollbar* self = (LLScrollbar*)userdata;
  585. self->changeLine(self->mStepSize, true);
  586. }