diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llui/llscrollbar.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llui/llscrollbar.cpp | 637 |
1 files changed, 637 insertions, 0 deletions
diff --git a/linden/indra/llui/llscrollbar.cpp b/linden/indra/llui/llscrollbar.cpp new file mode 100644 index 0000000..da3e472 --- /dev/null +++ b/linden/indra/llui/llscrollbar.cpp | |||
@@ -0,0 +1,637 @@ | |||
1 | /** | ||
2 | * @file llscrollbar.cpp | ||
3 | * @brief Scrollbar UI widget | ||
4 | * | ||
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "linden_common.h" | ||
29 | |||
30 | #include "llscrollbar.h" | ||
31 | |||
32 | #include "llmath.h" | ||
33 | #include "lltimer.h" | ||
34 | #include "v3color.h" | ||
35 | |||
36 | #include "llbutton.h" | ||
37 | #include "llcriticaldamp.h" | ||
38 | #include "llkeyboard.h" | ||
39 | #include "llui.h" | ||
40 | //#include "llviewerimagelist.h" | ||
41 | #include "llfocusmgr.h" | ||
42 | #include "llwindow.h" | ||
43 | #include "llglheaders.h" | ||
44 | #include "llcontrol.h" | ||
45 | |||
46 | LLScrollbar::LLScrollbar( | ||
47 | const LLString& name, LLRect rect, | ||
48 | LLScrollbar::ORIENTATION orientation, | ||
49 | S32 doc_size, S32 doc_pos, S32 page_size, | ||
50 | void (*change_callback)( S32 new_pos, LLScrollbar* self, void* userdata ), | ||
51 | void* callback_user_data, | ||
52 | S32 step_size) | ||
53 | : LLUICtrl( name, rect, TRUE, NULL, NULL ), | ||
54 | |||
55 | mChangeCallback( change_callback ), | ||
56 | mCallbackUserData( callback_user_data ), | ||
57 | mOrientation( orientation ), | ||
58 | mDocSize( doc_size ), | ||
59 | mDocPos( doc_pos ), | ||
60 | mPageSize( page_size ), | ||
61 | mStepSize( step_size ), | ||
62 | mDocChanged(FALSE), | ||
63 | mDragStartX( 0 ), | ||
64 | mDragStartY( 0 ), | ||
65 | mHoverGlowStrength(0.15f), | ||
66 | mCurGlowStrength(0.f), | ||
67 | mTrackColor( LLUI::sColorsGroup->getColor("ScrollbarTrackColor") ), | ||
68 | mThumbColor ( LLUI::sColorsGroup->getColor("ScrollbarThumbColor") ), | ||
69 | mHighlightColor ( LLUI::sColorsGroup->getColor("DefaultHighlightLight") ), | ||
70 | mShadowColor ( LLUI::sColorsGroup->getColor("DefaultShadowLight") ), | ||
71 | mOnScrollEndCallback( NULL ), | ||
72 | mOnScrollEndData( NULL ) | ||
73 | { | ||
74 | //llassert( 0 <= mDocSize ); | ||
75 | //llassert( 0 <= mDocPos && mDocPos <= mDocSize ); | ||
76 | |||
77 | setTabStop(FALSE); | ||
78 | updateThumbRect(); | ||
79 | |||
80 | // Page up and page down buttons | ||
81 | LLRect line_up_rect; | ||
82 | LLString line_up_img; | ||
83 | LLString line_up_selected_img; | ||
84 | LLString line_down_img; | ||
85 | LLString line_down_selected_img; | ||
86 | |||
87 | LLRect line_down_rect; | ||
88 | |||
89 | if( LLScrollbar::VERTICAL == mOrientation ) | ||
90 | { | ||
91 | line_up_rect.setLeftTopAndSize( 0, mRect.getHeight(), SCROLLBAR_SIZE, SCROLLBAR_SIZE ); | ||
92 | line_up_img="UIImgBtnScrollUpOutUUID"; | ||
93 | line_up_selected_img="UIImgBtnScrollUpInUUID"; | ||
94 | |||
95 | line_down_rect.setOriginAndSize( 0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE ); | ||
96 | line_down_img="UIImgBtnScrollDownOutUUID"; | ||
97 | line_down_selected_img="UIImgBtnScrollDownInUUID"; | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | // Horizontal | ||
102 | line_up_rect.setOriginAndSize( 0, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE ); | ||
103 | line_up_img="UIImgBtnScrollLeftOutUUID"; | ||
104 | line_up_selected_img="UIImgBtnScrollLeftInUUID"; | ||
105 | |||
106 | line_down_rect.setOriginAndSize( mRect.getWidth() - SCROLLBAR_SIZE, 0, SCROLLBAR_SIZE, SCROLLBAR_SIZE ); | ||
107 | line_down_img="UIImgBtnScrollRightOutUUID"; | ||
108 | line_down_selected_img="UIImgBtnScrollRightInUUID"; | ||
109 | } | ||
110 | |||
111 | LLButton* line_up_btn = new LLButton( | ||
112 | "Line Up", line_up_rect, | ||
113 | line_up_img, line_up_selected_img, "", | ||
114 | &LLScrollbar::onLineUpBtnPressed, this, LLFontGL::sSansSerif ); | ||
115 | if( LLScrollbar::VERTICAL == mOrientation ) | ||
116 | { | ||
117 | line_up_btn->setFollowsRight(); | ||
118 | line_up_btn->setFollowsTop(); | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | // horizontal | ||
123 | line_up_btn->setFollowsLeft(); | ||
124 | line_up_btn->setFollowsBottom(); | ||
125 | } | ||
126 | line_up_btn->setHeldDownCallback( &LLScrollbar::onLineUpBtnPressed ); | ||
127 | line_up_btn->setTabStop(FALSE); | ||
128 | addChild(line_up_btn); | ||
129 | |||
130 | LLButton* line_down_btn = new LLButton( | ||
131 | "Line Down", line_down_rect, | ||
132 | line_down_img, line_down_selected_img, "", | ||
133 | &LLScrollbar::onLineDownBtnPressed, this, LLFontGL::sSansSerif ); | ||
134 | line_down_btn->setFollowsRight(); | ||
135 | line_down_btn->setFollowsBottom(); | ||
136 | line_down_btn->setHeldDownCallback( &LLScrollbar::onLineDownBtnPressed ); | ||
137 | line_down_btn->setTabStop(FALSE); | ||
138 | addChild(line_down_btn); | ||
139 | } | ||
140 | |||
141 | |||
142 | LLScrollbar::~LLScrollbar() | ||
143 | { | ||
144 | // Children buttons killed by parent class | ||
145 | } | ||
146 | |||
147 | void LLScrollbar::setDocParams( S32 size, S32 pos ) | ||
148 | { | ||
149 | mDocSize = size; | ||
150 | mDocPos = llclamp( pos, 0, getDocPosMax() ); | ||
151 | mDocChanged = TRUE; | ||
152 | |||
153 | updateThumbRect(); | ||
154 | } | ||
155 | |||
156 | void LLScrollbar::setDocPos(S32 pos) | ||
157 | { | ||
158 | mDocPos = llclamp( pos, 0, getDocPosMax() ); | ||
159 | mDocChanged = TRUE; | ||
160 | |||
161 | updateThumbRect(); | ||
162 | } | ||
163 | |||
164 | void LLScrollbar::setDocSize(S32 size) | ||
165 | { | ||
166 | mDocSize = size; | ||
167 | mDocPos = llclamp( mDocPos, 0, getDocPosMax() ); | ||
168 | mDocChanged = TRUE; | ||
169 | |||
170 | updateThumbRect(); | ||
171 | } | ||
172 | |||
173 | void LLScrollbar::setPageSize( S32 page_size ) | ||
174 | { | ||
175 | mPageSize = page_size; | ||
176 | mDocPos = llclamp( mDocPos, 0, getDocPosMax() ); | ||
177 | mDocChanged = TRUE; | ||
178 | |||
179 | updateThumbRect(); | ||
180 | } | ||
181 | |||
182 | void LLScrollbar::updateThumbRect() | ||
183 | { | ||
184 | // llassert( 0 <= mDocSize ); | ||
185 | // llassert( 0 <= mDocPos && mDocPos <= getDocPosMax() ); | ||
186 | |||
187 | const S32 THUMB_MIN_LENGTH = 16; | ||
188 | |||
189 | S32 window_length = (mOrientation == LLScrollbar::HORIZONTAL) ? mRect.getWidth() : mRect.getHeight(); | ||
190 | S32 thumb_bg_length = window_length - 2 * SCROLLBAR_SIZE; | ||
191 | S32 visible_lines = llmin( mDocSize, mPageSize ); | ||
192 | S32 thumb_length = mDocSize ? llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH ) : thumb_bg_length; | ||
193 | |||
194 | S32 variable_lines = mDocSize - visible_lines; | ||
195 | |||
196 | if( mOrientation == LLScrollbar::VERTICAL ) | ||
197 | { | ||
198 | S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE; | ||
199 | S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH; | ||
200 | S32 thumb_start = variable_lines ? llclamp( thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min, thumb_start_max ) : thumb_start_max; | ||
201 | |||
202 | mThumbRect.mLeft = 0; | ||
203 | mThumbRect.mTop = thumb_start; | ||
204 | mThumbRect.mRight = SCROLLBAR_SIZE; | ||
205 | mThumbRect.mBottom = thumb_start - thumb_length; | ||
206 | } | ||
207 | else | ||
208 | { | ||
209 | // Horizontal | ||
210 | S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length; | ||
211 | S32 thumb_start_min = SCROLLBAR_SIZE; | ||
212 | S32 thumb_start = variable_lines ? llclamp( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min, thumb_start_max ) : thumb_start_min; | ||
213 | |||
214 | mThumbRect.mLeft = thumb_start; | ||
215 | mThumbRect.mTop = SCROLLBAR_SIZE; | ||
216 | mThumbRect.mRight = thumb_start + thumb_length; | ||
217 | mThumbRect.mBottom = 0; | ||
218 | } | ||
219 | |||
220 | if (mOnScrollEndCallback && mOnScrollEndData && (mDocPos == getDocPosMax())) | ||
221 | { | ||
222 | mOnScrollEndCallback(mOnScrollEndData); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | BOOL LLScrollbar::handleMouseDown(S32 x, S32 y, MASK mask) | ||
227 | { | ||
228 | // Check children first | ||
229 | BOOL handled_by_child = LLView::childrenHandleMouseDown(x, y, mask) != NULL; | ||
230 | if( !handled_by_child ) | ||
231 | { | ||
232 | if( mThumbRect.pointInRect(x,y) ) | ||
233 | { | ||
234 | // Start dragging the thumb | ||
235 | // No handler needed for focus lost since this clas has no state that depends on it. | ||
236 | gFocusMgr.setMouseCapture( this, NULL ); | ||
237 | mDragStartX = x; | ||
238 | mDragStartY = y; | ||
239 | mOrigRect.mTop = mThumbRect.mTop; | ||
240 | mOrigRect.mBottom = mThumbRect.mBottom; | ||
241 | mOrigRect.mLeft = mThumbRect.mLeft; | ||
242 | mOrigRect.mRight = mThumbRect.mRight; | ||
243 | mLastDelta = 0; | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | if( | ||
248 | ( (LLScrollbar::VERTICAL == mOrientation) && (mThumbRect.mTop < y) ) || | ||
249 | ( (LLScrollbar::HORIZONTAL == mOrientation) && (x < mThumbRect.mLeft) ) | ||
250 | ) | ||
251 | { | ||
252 | // Page up | ||
253 | pageUp(0); | ||
254 | } | ||
255 | else | ||
256 | if( | ||
257 | ( (LLScrollbar::VERTICAL == mOrientation) && (y < mThumbRect.mBottom) ) || | ||
258 | ( (LLScrollbar::HORIZONTAL == mOrientation) && (mThumbRect.mRight < x) ) | ||
259 | ) | ||
260 | { | ||
261 | // Page down | ||
262 | pageDown(0); | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | return TRUE; | ||
268 | } | ||
269 | |||
270 | |||
271 | BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask) | ||
272 | { | ||
273 | // Note: we don't bother sending the event to the children (the arrow buttons) | ||
274 | // because they'll capture the mouse whenever they need hover events. | ||
275 | |||
276 | BOOL handled = FALSE; | ||
277 | if( gFocusMgr.getMouseCapture() == this ) | ||
278 | { | ||
279 | S32 height = mRect.getHeight(); | ||
280 | S32 width = mRect.getWidth(); | ||
281 | |||
282 | if( VERTICAL == mOrientation ) | ||
283 | { | ||
284 | // S32 old_pos = mThumbRect.mTop; | ||
285 | |||
286 | S32 delta_pixels = y - mDragStartY; | ||
287 | if( mOrigRect.mBottom + delta_pixels < SCROLLBAR_SIZE ) | ||
288 | { | ||
289 | delta_pixels = SCROLLBAR_SIZE - mOrigRect.mBottom - 1; | ||
290 | } | ||
291 | else | ||
292 | if( mOrigRect.mTop + delta_pixels > height - SCROLLBAR_SIZE ) | ||
293 | { | ||
294 | delta_pixels = height - SCROLLBAR_SIZE - mOrigRect.mTop + 1; | ||
295 | } | ||
296 | |||
297 | mThumbRect.mTop = mOrigRect.mTop + delta_pixels; | ||
298 | mThumbRect.mBottom = mOrigRect.mBottom + delta_pixels; | ||
299 | |||
300 | S32 thumb_length = mThumbRect.getHeight(); | ||
301 | S32 thumb_track_length = height - 2 * SCROLLBAR_SIZE; | ||
302 | |||
303 | |||
304 | if( delta_pixels != mLastDelta || mDocChanged) | ||
305 | { | ||
306 | // Note: delta_pixels increases as you go up. mDocPos increases down (line 0 is at the top of the page). | ||
307 | S32 usable_track_length = thumb_track_length - thumb_length; | ||
308 | if( 0 < usable_track_length ) | ||
309 | { | ||
310 | S32 variable_lines = getDocPosMax(); | ||
311 | S32 pos = mThumbRect.mTop; | ||
312 | F32 ratio = F32(pos - SCROLLBAR_SIZE - thumb_length) / usable_track_length; | ||
313 | |||
314 | S32 new_pos = llclamp( S32(variable_lines - ratio * variable_lines + 0.5f), 0, variable_lines ); | ||
315 | // Note: we do not call updateThumbRect() here. Instead we let the thumb and the document go slightly | ||
316 | // out of sync (less than a line's worth) to make the thumb feel responsive. | ||
317 | changeLine( new_pos - mDocPos, FALSE ); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | mLastDelta = delta_pixels; | ||
322 | |||
323 | } | ||
324 | else | ||
325 | { | ||
326 | // Horizontal | ||
327 | // S32 old_pos = mThumbRect.mLeft; | ||
328 | |||
329 | S32 delta_pixels = x - mDragStartX; | ||
330 | |||
331 | if( mOrigRect.mLeft + delta_pixels < SCROLLBAR_SIZE ) | ||
332 | { | ||
333 | delta_pixels = SCROLLBAR_SIZE - mOrigRect.mLeft - 1; | ||
334 | } | ||
335 | else | ||
336 | if( mOrigRect.mRight + delta_pixels > width - SCROLLBAR_SIZE ) | ||
337 | { | ||
338 | delta_pixels = width - SCROLLBAR_SIZE - mOrigRect.mRight + 1; | ||
339 | } | ||
340 | |||
341 | mThumbRect.mLeft = mOrigRect.mLeft + delta_pixels; | ||
342 | mThumbRect.mRight = mOrigRect.mRight + delta_pixels; | ||
343 | |||
344 | S32 thumb_length = mThumbRect.getWidth(); | ||
345 | S32 thumb_track_length = width - 2 * SCROLLBAR_SIZE; | ||
346 | |||
347 | if( delta_pixels != mLastDelta || mDocChanged) | ||
348 | { | ||
349 | // Note: delta_pixels increases as you go up. mDocPos increases down (line 0 is at the top of the page). | ||
350 | S32 usable_track_length = thumb_track_length - thumb_length; | ||
351 | if( 0 < usable_track_length ) | ||
352 | { | ||
353 | S32 variable_lines = getDocPosMax(); | ||
354 | S32 pos = mThumbRect.mLeft; | ||
355 | F32 ratio = F32(pos - SCROLLBAR_SIZE) / usable_track_length; | ||
356 | |||
357 | S32 new_pos = llclamp( S32(ratio * variable_lines + 0.5f), 0, variable_lines); | ||
358 | |||
359 | // Note: we do not call updateThumbRect() here. Instead we let the thumb and the document go slightly | ||
360 | // out of sync (less than a line's worth) to make the thumb feel responsive. | ||
361 | changeLine( new_pos - mDocPos, FALSE ); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | mLastDelta = delta_pixels; | ||
366 | } | ||
367 | |||
368 | getWindow()->setCursor(UI_CURSOR_ARROW); | ||
369 | lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl; | ||
370 | handled = TRUE; | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | handled = childrenHandleMouseUp( x, y, mask ) != NULL; | ||
375 | } | ||
376 | |||
377 | // Opaque | ||
378 | if( !handled ) | ||
379 | { | ||
380 | getWindow()->setCursor(UI_CURSOR_ARROW); | ||
381 | lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl; | ||
382 | handled = TRUE; | ||
383 | } | ||
384 | |||
385 | mDocChanged = FALSE; | ||
386 | return handled; | ||
387 | } | ||
388 | |||
389 | |||
390 | BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks) | ||
391 | { | ||
392 | BOOL handled = FALSE; | ||
393 | if( getVisible() && mRect.localPointInRect( x, y ) ) | ||
394 | { | ||
395 | if( getEnabled() ) | ||
396 | { | ||
397 | changeLine( clicks * mStepSize, TRUE ); | ||
398 | } | ||
399 | handled = TRUE; | ||
400 | } | ||
401 | |||
402 | return handled; | ||
403 | } | ||
404 | |||
405 | BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, | ||
406 | EDragAndDropType cargo_type, void *carge_data, EAcceptance *accept, LLString &tooltip_msg) | ||
407 | { | ||
408 | if (!drop) | ||
409 | { | ||
410 | //TODO: refactor this | ||
411 | S32 variable_lines = getDocPosMax(); | ||
412 | S32 pos = (VERTICAL == mOrientation) ? y : x; | ||
413 | S32 thumb_length = (VERTICAL == mOrientation) ? mThumbRect.getHeight() : mThumbRect.getWidth(); | ||
414 | S32 thumb_track_length = (VERTICAL == mOrientation) ? (mRect.getHeight() - 2 * SCROLLBAR_SIZE) : (mRect.getWidth() - 2 * SCROLLBAR_SIZE); | ||
415 | S32 usable_track_length = thumb_track_length - thumb_length; | ||
416 | F32 ratio = (VERTICAL == mOrientation) ? F32(pos - SCROLLBAR_SIZE - thumb_length) / usable_track_length | ||
417 | : F32(pos - SCROLLBAR_SIZE) / usable_track_length; | ||
418 | S32 new_pos = (VERTICAL == mOrientation) ? llclamp( S32(variable_lines - ratio * variable_lines + 0.5f), 0, variable_lines ) | ||
419 | : llclamp( S32(ratio * variable_lines + 0.5f), 0, variable_lines ); | ||
420 | changeLine( new_pos - mDocPos, TRUE ); | ||
421 | } | ||
422 | return TRUE; | ||
423 | } | ||
424 | |||
425 | BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask) | ||
426 | { | ||
427 | BOOL handled = FALSE; | ||
428 | if( gFocusMgr.getMouseCapture() == this ) | ||
429 | { | ||
430 | gFocusMgr.setMouseCapture( NULL, NULL ); | ||
431 | handled = TRUE; | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | // Opaque, so don't just check children | ||
436 | handled = LLView::handleMouseUp( x, y, mask ); | ||
437 | } | ||
438 | |||
439 | return handled; | ||
440 | } | ||
441 | |||
442 | void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent) | ||
443 | { | ||
444 | LLView::reshape( width, height, called_from_parent ); | ||
445 | updateThumbRect(); | ||
446 | } | ||
447 | |||
448 | |||
449 | void LLScrollbar::draw() | ||
450 | { | ||
451 | if( getVisible() ) | ||
452 | { | ||
453 | S32 local_mouse_x; | ||
454 | S32 local_mouse_y; | ||
455 | LLCoordWindow cursor_pos_window; | ||
456 | getWindow()->getCursorPosition(&cursor_pos_window); | ||
457 | LLCoordGL cursor_pos_gl; | ||
458 | getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); | ||
459 | |||
460 | screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); | ||
461 | BOOL other_captor = gFocusMgr.getMouseCapture() && gFocusMgr.getMouseCapture() != this; | ||
462 | BOOL hovered = mEnabled && !other_captor && (gFocusMgr.getMouseCapture() == this || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); | ||
463 | if (hovered) | ||
464 | { | ||
465 | mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); | ||
466 | } | ||
467 | else | ||
468 | { | ||
469 | mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f)); | ||
470 | } | ||
471 | |||
472 | |||
473 | // Draw background and thumb. | ||
474 | LLUUID rounded_rect_image_id; | ||
475 | rounded_rect_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga")); | ||
476 | LLImageGL* rounded_rect_imagep = LLUI::sImageProvider->getUIImageByID(rounded_rect_image_id); | ||
477 | |||
478 | if (!rounded_rect_imagep) | ||
479 | { | ||
480 | gl_rect_2d(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0, | ||
481 | mOrientation == VERTICAL ? mRect.getHeight() - 2 * SCROLLBAR_SIZE : mRect.getHeight(), | ||
482 | mOrientation == HORIZONTAL ? mRect.getWidth() - 2 * SCROLLBAR_SIZE : mRect.getWidth(), | ||
483 | mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0, mTrackColor, TRUE); | ||
484 | |||
485 | gl_rect_2d(mThumbRect, mThumbColor, TRUE); | ||
486 | |||
487 | } | ||
488 | else | ||
489 | { | ||
490 | // Background | ||
491 | gl_draw_scaled_image_with_border(mOrientation == HORIZONTAL ? SCROLLBAR_SIZE : 0, | ||
492 | mOrientation == VERTICAL ? SCROLLBAR_SIZE : 0, | ||
493 | 16, | ||
494 | 16, | ||
495 | mOrientation == HORIZONTAL ? mRect.getWidth() - 2 * SCROLLBAR_SIZE : mRect.getWidth(), | ||
496 | mOrientation == VERTICAL ? mRect.getHeight() - 2 * SCROLLBAR_SIZE : mRect.getHeight(), | ||
497 | rounded_rect_imagep, | ||
498 | mTrackColor, | ||
499 | TRUE); | ||
500 | |||
501 | // Thumb | ||
502 | LLRect outline_rect = mThumbRect; | ||
503 | outline_rect.stretch(2); | ||
504 | |||
505 | if (gFocusMgr.getKeyboardFocus() == this) | ||
506 | { | ||
507 | gl_draw_scaled_image_with_border(outline_rect.mLeft, outline_rect.mBottom, 16, 16, outline_rect.getWidth(), outline_rect.getHeight(), | ||
508 | rounded_rect_imagep, gFocusMgr.getFocusColor() ); | ||
509 | } | ||
510 | |||
511 | gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(), | ||
512 | rounded_rect_imagep, mThumbColor ); | ||
513 | if (mCurGlowStrength > 0.01f) | ||
514 | { | ||
515 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); | ||
516 | gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(), | ||
517 | rounded_rect_imagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE); | ||
518 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
519 | } | ||
520 | } | ||
521 | |||
522 | BOOL was_scrolled_to_bottom = (getDocPos() == getDocPosMax()); | ||
523 | if (mOnScrollEndCallback && was_scrolled_to_bottom) | ||
524 | { | ||
525 | mOnScrollEndCallback(mOnScrollEndData); | ||
526 | } | ||
527 | // Draw children | ||
528 | LLView::draw(); | ||
529 | } | ||
530 | } | ||
531 | |||
532 | void LLScrollbar::changeLine( S32 delta, BOOL update_thumb ) | ||
533 | { | ||
534 | S32 new_pos = llclamp( mDocPos + delta, 0, getDocPosMax() ); | ||
535 | if( new_pos != mDocPos ) | ||
536 | { | ||
537 | mDocPos = new_pos; | ||
538 | } | ||
539 | |||
540 | if( mChangeCallback ) | ||
541 | { | ||
542 | mChangeCallback( mDocPos, this, mCallbackUserData ); | ||
543 | } | ||
544 | |||
545 | if( update_thumb ) | ||
546 | { | ||
547 | updateThumbRect(); | ||
548 | } | ||
549 | } | ||
550 | |||
551 | void LLScrollbar::setValue(const LLSD& value) | ||
552 | { | ||
553 | setDocPos((S32) value.asInteger()); | ||
554 | } | ||
555 | |||
556 | EWidgetType LLScrollbar::getWidgetType() const | ||
557 | { | ||
558 | return WIDGET_TYPE_SCROLLBAR; | ||
559 | } | ||
560 | |||
561 | LLString LLScrollbar::getWidgetTag() const | ||
562 | { | ||
563 | return LL_SCROLLBAR_TAG; | ||
564 | } | ||
565 | |||
566 | BOOL LLScrollbar::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) | ||
567 | { | ||
568 | BOOL handled = FALSE; | ||
569 | |||
570 | if( getVisible() && mEnabled && !called_from_parent ) | ||
571 | { | ||
572 | switch( key ) | ||
573 | { | ||
574 | case KEY_HOME: | ||
575 | changeLine( -mDocPos, TRUE ); | ||
576 | handled = TRUE; | ||
577 | break; | ||
578 | |||
579 | case KEY_END: | ||
580 | changeLine( getDocPosMax() - mDocPos, TRUE ); | ||
581 | handled = TRUE; | ||
582 | break; | ||
583 | |||
584 | case KEY_DOWN: | ||
585 | changeLine( mStepSize, TRUE ); | ||
586 | handled = TRUE; | ||
587 | break; | ||
588 | |||
589 | case KEY_UP: | ||
590 | changeLine( - mStepSize, TRUE ); | ||
591 | handled = TRUE; | ||
592 | break; | ||
593 | |||
594 | case KEY_PAGE_DOWN: | ||
595 | pageDown(1); | ||
596 | break; | ||
597 | |||
598 | case KEY_PAGE_UP: | ||
599 | pageUp(1); | ||
600 | break; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | return handled; | ||
605 | } | ||
606 | |||
607 | void LLScrollbar::pageUp(S32 overlap) | ||
608 | { | ||
609 | if (mDocSize > mPageSize) | ||
610 | { | ||
611 | changeLine( -(mPageSize - overlap), TRUE ); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | void LLScrollbar::pageDown(S32 overlap) | ||
616 | { | ||
617 | if (mDocSize > mPageSize) | ||
618 | { | ||
619 | changeLine( mPageSize - overlap, TRUE ); | ||
620 | } | ||
621 | } | ||
622 | |||
623 | // static | ||
624 | void LLScrollbar::onLineUpBtnPressed( void* userdata ) | ||
625 | { | ||
626 | LLScrollbar* self = (LLScrollbar*) userdata; | ||
627 | |||
628 | self->changeLine( - self->mStepSize, TRUE ); | ||
629 | } | ||
630 | |||
631 | // static | ||
632 | void LLScrollbar::onLineDownBtnPressed( void* userdata ) | ||
633 | { | ||
634 | LLScrollbar* self = (LLScrollbar*) userdata; | ||
635 | self->changeLine( self->mStepSize, TRUE ); | ||
636 | } | ||
637 | |||