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/llbutton.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 'linden/indra/llui/llbutton.cpp')
-rw-r--r-- | linden/indra/llui/llbutton.cpp | 1031 |
1 files changed, 1031 insertions, 0 deletions
diff --git a/linden/indra/llui/llbutton.cpp b/linden/indra/llui/llbutton.cpp new file mode 100644 index 0000000..736bc59 --- /dev/null +++ b/linden/indra/llui/llbutton.cpp | |||
@@ -0,0 +1,1031 @@ | |||
1 | /** | ||
2 | * @file llbutton.cpp | ||
3 | * @brief LLButton base class | ||
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 "llbutton.h" | ||
31 | |||
32 | // Linden library includes | ||
33 | #include "v4color.h" | ||
34 | #include "llstring.h" | ||
35 | |||
36 | // Project includes | ||
37 | #include "llkeyboard.h" | ||
38 | #include "llgl.h" | ||
39 | #include "llui.h" | ||
40 | #include "lluiconstants.h" | ||
41 | //#include "llcallbacklist.h" | ||
42 | #include "llresmgr.h" | ||
43 | #include "llcriticaldamp.h" | ||
44 | #include "llglheaders.h" | ||
45 | #include "llfocusmgr.h" | ||
46 | #include "llwindow.h" | ||
47 | |||
48 | // globals loaded from settings.xml | ||
49 | S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI | ||
50 | S32 LLBUTTON_H_PAD = 0; | ||
51 | S32 LLBUTTON_V_PAD = 0; | ||
52 | S32 BTN_HEIGHT_SMALL= 0; | ||
53 | S32 BTN_HEIGHT = 0; | ||
54 | |||
55 | S32 BTN_GRID = 12; | ||
56 | S32 BORDER_SIZE = 1; | ||
57 | |||
58 | // static | ||
59 | LLFrameTimer LLButton::sFlashingTimer; | ||
60 | |||
61 | LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& control_name, void (*click_callback)(void*), void *callback_data) | ||
62 | : LLUICtrl(name, rect, TRUE, NULL, NULL), | ||
63 | mClickedCallback( click_callback ), | ||
64 | mMouseDownCallback( NULL ), | ||
65 | mMouseUpCallback( NULL ), | ||
66 | mHeldDownCallback( NULL ), | ||
67 | mGLFont( NULL ), | ||
68 | mHeldDownDelay( 0.5f ), // seconds until held-down callback is called | ||
69 | mImageUnselected( NULL ), | ||
70 | mImageSelected( NULL ), | ||
71 | mImageHoverSelected( NULL ), | ||
72 | mImageHoverUnselected( NULL ), | ||
73 | mImageDisabled( NULL ), | ||
74 | mImageDisabledSelected( NULL ), | ||
75 | mToggleState( FALSE ), | ||
76 | mScaleImage( TRUE ), | ||
77 | mDropShadowedText( TRUE ), | ||
78 | mBorderEnabled( FALSE ), | ||
79 | mFlashing( FALSE ), | ||
80 | mHAlign( LLFontGL::HCENTER ), | ||
81 | mLeftHPad( LLBUTTON_H_PAD ), | ||
82 | mRightHPad( LLBUTTON_H_PAD ), | ||
83 | mFixedWidth( 16 ), | ||
84 | mFixedHeight( 16 ), | ||
85 | mHoverGlowStrength(0.15f), | ||
86 | mCurGlowStrength(0.f), | ||
87 | mNeedsHighlight(FALSE), | ||
88 | mCommitOnReturn(TRUE), | ||
89 | mImagep( NULL ) | ||
90 | { | ||
91 | mUnselectedLabel = name; | ||
92 | mSelectedLabel = name; | ||
93 | |||
94 | setImageUnselected("button_enabled_32x128.tga"); | ||
95 | setImageSelected("button_enabled_selected_32x128.tga"); | ||
96 | setImageDisabled("button_disabled_32x128.tga"); | ||
97 | setImageDisabledSelected("button_disabled_32x128.tga"); | ||
98 | |||
99 | mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); | ||
100 | mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); | ||
101 | |||
102 | init(click_callback, callback_data, NULL, control_name); | ||
103 | } | ||
104 | |||
105 | |||
106 | LLButton::LLButton(const LLString& name, const LLRect& rect, | ||
107 | const LLString &unselected_image_name, | ||
108 | const LLString &selected_image_name, | ||
109 | const LLString& control_name, | ||
110 | void (*click_callback)(void*), | ||
111 | void *callback_data, | ||
112 | const LLFontGL *font, | ||
113 | const LLString& unselected_label, | ||
114 | const LLString& selected_label ) | ||
115 | : LLUICtrl(name, rect, TRUE, NULL, NULL), | ||
116 | mClickedCallback( click_callback ), | ||
117 | mMouseDownCallback( NULL ), | ||
118 | mMouseUpCallback( NULL ), | ||
119 | mHeldDownCallback( NULL ), | ||
120 | mGLFont( NULL ), | ||
121 | mHeldDownDelay( 0.5f ), // seconds until held-down callback is called | ||
122 | mImageUnselected( NULL ), | ||
123 | mImageSelected( NULL ), | ||
124 | mImageHoverSelected( NULL ), | ||
125 | mImageHoverUnselected( NULL ), | ||
126 | mImageDisabled( NULL ), | ||
127 | mImageDisabledSelected( NULL ), | ||
128 | mToggleState( FALSE ), | ||
129 | mScaleImage( TRUE ), | ||
130 | mDropShadowedText( TRUE ), | ||
131 | mBorderEnabled( FALSE ), | ||
132 | mFlashing( FALSE ), | ||
133 | mHAlign( LLFontGL::HCENTER ), | ||
134 | mLeftHPad( LLBUTTON_H_PAD ), | ||
135 | mRightHPad( LLBUTTON_H_PAD ), | ||
136 | mFixedWidth( 16 ), | ||
137 | mFixedHeight( 16 ), | ||
138 | mHoverGlowStrength(0.25f), | ||
139 | mCurGlowStrength(0.f), | ||
140 | mNeedsHighlight(FALSE), | ||
141 | mCommitOnReturn(TRUE), | ||
142 | mImagep( NULL ) | ||
143 | { | ||
144 | mUnselectedLabel = unselected_label; | ||
145 | mSelectedLabel = selected_label; | ||
146 | |||
147 | // by default, disabled color is same as enabled | ||
148 | mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); | ||
149 | mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); | ||
150 | |||
151 | if( unselected_image_name != "" ) | ||
152 | { | ||
153 | setImageUnselected(unselected_image_name); | ||
154 | setImageDisabled(unselected_image_name); | ||
155 | |||
156 | mDisabledImageColor.mV[VALPHA] = 0.5f; | ||
157 | mImageDisabled = mImageUnselected; | ||
158 | mDisabledImageColor.mV[VALPHA] = 0.5f; | ||
159 | // user-specified image - don't use fixed borders unless requested | ||
160 | mFixedWidth = 0; | ||
161 | mFixedHeight = 0; | ||
162 | mScaleImage = FALSE; | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | setImageUnselected("button_enabled_32x128.tga"); | ||
167 | setImageDisabled("button_disabled_32x128.tga"); | ||
168 | } | ||
169 | |||
170 | if( selected_image_name != "" ) | ||
171 | { | ||
172 | setImageSelected(selected_image_name); | ||
173 | setImageDisabledSelected(selected_image_name); | ||
174 | |||
175 | mDisabledImageColor.mV[VALPHA] = 0.5f; | ||
176 | // user-specified image - don't use fixed borders unless requested | ||
177 | mFixedWidth = 0; | ||
178 | mFixedHeight = 0; | ||
179 | mScaleImage = FALSE; | ||
180 | } | ||
181 | else | ||
182 | { | ||
183 | setImageSelected("button_enabled_selected_32x128.tga"); | ||
184 | setImageDisabledSelected("button_disabled_32x128.tga"); | ||
185 | } | ||
186 | |||
187 | init(click_callback, callback_data, font, control_name); | ||
188 | } | ||
189 | |||
190 | void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const LLString& control_name) | ||
191 | { | ||
192 | mGLFont = ( font ? font : LLFontGL::sSansSerif); | ||
193 | |||
194 | // Hack to make sure there is space for at least one character | ||
195 | if (mRect.getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(" ")) | ||
196 | { | ||
197 | // Use old defaults | ||
198 | mLeftHPad = LLBUTTON_ORIG_H_PAD; | ||
199 | mRightHPad = LLBUTTON_ORIG_H_PAD; | ||
200 | } | ||
201 | |||
202 | mCallbackUserData = callback_data; | ||
203 | mMouseDownTimer.stop(); | ||
204 | |||
205 | setControlName(control_name, NULL); | ||
206 | |||
207 | mUnselectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) ); | ||
208 | mSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) ); | ||
209 | mDisabledLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) ); | ||
210 | mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) ); | ||
211 | mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) ); | ||
212 | mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) ); | ||
213 | mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) ); | ||
214 | } | ||
215 | |||
216 | LLButton::~LLButton() | ||
217 | { | ||
218 | if( this == gFocusMgr.getMouseCapture() ) | ||
219 | { | ||
220 | gFocusMgr.setMouseCapture( NULL, NULL ); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | // virtual | ||
225 | EWidgetType LLButton::getWidgetType() const | ||
226 | { | ||
227 | return WIDGET_TYPE_BUTTON; | ||
228 | } | ||
229 | |||
230 | // virtual | ||
231 | LLString LLButton::getWidgetTag() const | ||
232 | { | ||
233 | return LL_BUTTON_TAG; | ||
234 | } | ||
235 | |||
236 | // HACK: Committing a button is the same as instantly clicking it. | ||
237 | // virtual | ||
238 | void LLButton::onCommit() | ||
239 | { | ||
240 | // WARNING: Sometimes clicking a button destroys the floater or | ||
241 | // panel containing it. Therefore we need to call mClickedCallback | ||
242 | // LAST, otherwise this becomes deleted memory. | ||
243 | LLUICtrl::onCommit(); | ||
244 | |||
245 | if (mMouseDownCallback) | ||
246 | { | ||
247 | (*mMouseDownCallback)(mCallbackUserData); | ||
248 | } | ||
249 | |||
250 | if (mMouseUpCallback) | ||
251 | { | ||
252 | (*mMouseUpCallback)(mCallbackUserData); | ||
253 | } | ||
254 | |||
255 | if (mSoundFlags & MOUSE_DOWN) | ||
256 | { | ||
257 | make_ui_sound("UISndClick"); | ||
258 | } | ||
259 | |||
260 | if (mSoundFlags & MOUSE_UP) | ||
261 | { | ||
262 | make_ui_sound("UISndClickRelease"); | ||
263 | } | ||
264 | |||
265 | if (mClickedCallback) | ||
266 | { | ||
267 | (*mClickedCallback)( mCallbackUserData ); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | BOOL LLButton::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent) | ||
272 | { | ||
273 | BOOL handled = FALSE; | ||
274 | if( getVisible() && mEnabled && !called_from_parent && ' ' == uni_char && !gKeyboard->getKeyRepeated(' ')) | ||
275 | { | ||
276 | if (mClickedCallback) | ||
277 | { | ||
278 | (*mClickedCallback)( mCallbackUserData ); | ||
279 | } | ||
280 | handled = TRUE; | ||
281 | } | ||
282 | return handled; | ||
283 | } | ||
284 | |||
285 | BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent ) | ||
286 | { | ||
287 | BOOL handled = FALSE; | ||
288 | if( getVisible() && mEnabled && !called_from_parent ) | ||
289 | { | ||
290 | if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key)) | ||
291 | { | ||
292 | if (mClickedCallback) | ||
293 | { | ||
294 | (*mClickedCallback)( mCallbackUserData ); | ||
295 | } | ||
296 | handled = TRUE; | ||
297 | } | ||
298 | } | ||
299 | return handled; | ||
300 | } | ||
301 | |||
302 | |||
303 | BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) | ||
304 | { | ||
305 | // Route future Mouse messages here preemptively. (Release on mouse up.) | ||
306 | gFocusMgr.setMouseCapture( this, &LLButton::onMouseCaptureLost ); | ||
307 | |||
308 | if (hasTabStop() && !getIsChrome()) | ||
309 | { | ||
310 | setFocus(TRUE); | ||
311 | } | ||
312 | |||
313 | if (mMouseDownCallback) | ||
314 | { | ||
315 | (*mMouseDownCallback)(mCallbackUserData); | ||
316 | } | ||
317 | |||
318 | mMouseDownTimer.start(); | ||
319 | |||
320 | if (mSoundFlags & MOUSE_DOWN) | ||
321 | { | ||
322 | make_ui_sound("UISndClick"); | ||
323 | } | ||
324 | |||
325 | return TRUE; | ||
326 | } | ||
327 | |||
328 | |||
329 | BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) | ||
330 | { | ||
331 | // We only handle the click if the click both started and ended within us | ||
332 | if( this == gFocusMgr.getMouseCapture() ) | ||
333 | { | ||
334 | // Regardless of where mouseup occurs, handle callback | ||
335 | if (mMouseUpCallback) | ||
336 | { | ||
337 | (*mMouseUpCallback)(mCallbackUserData); | ||
338 | } | ||
339 | |||
340 | mMouseDownTimer.stop(); | ||
341 | |||
342 | // Always release the mouse | ||
343 | gFocusMgr.setMouseCapture( NULL, NULL ); | ||
344 | |||
345 | // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. | ||
346 | // If mouseup in the widget, it's been clicked | ||
347 | if (pointInView(x, y)) | ||
348 | { | ||
349 | if (mSoundFlags & MOUSE_UP) | ||
350 | { | ||
351 | make_ui_sound("UISndClickRelease"); | ||
352 | } | ||
353 | |||
354 | if (mClickedCallback) | ||
355 | { | ||
356 | (*mClickedCallback)( mCallbackUserData ); | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | |||
361 | return TRUE; | ||
362 | } | ||
363 | |||
364 | |||
365 | BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) | ||
366 | { | ||
367 | BOOL handled = FALSE; | ||
368 | |||
369 | LLMouseHandler* other_captor = gFocusMgr.getMouseCapture(); | ||
370 | mNeedsHighlight = other_captor == NULL || | ||
371 | other_captor == this || | ||
372 | // this following bit is to support modal dialogs | ||
373 | (other_captor->isView() && hasAncestor((LLView*)other_captor)); | ||
374 | |||
375 | if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback) | ||
376 | { | ||
377 | F32 elapsed = mMouseDownTimer.getElapsedTimeF32(); | ||
378 | if( mHeldDownDelay < elapsed ) | ||
379 | { | ||
380 | mHeldDownCallback( mCallbackUserData ); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | // We only handle the click if the click both started and ended within us | ||
385 | if( this == gFocusMgr.getMouseCapture() ) | ||
386 | { | ||
387 | handled = TRUE; | ||
388 | } | ||
389 | else if( getVisible() ) | ||
390 | { | ||
391 | // Opaque | ||
392 | handled = TRUE; | ||
393 | } | ||
394 | |||
395 | if( handled ) | ||
396 | { | ||
397 | getWindow()->setCursor(UI_CURSOR_ARROW); | ||
398 | lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl; | ||
399 | } | ||
400 | |||
401 | return handled; | ||
402 | } | ||
403 | |||
404 | |||
405 | // virtual | ||
406 | void LLButton::draw() | ||
407 | { | ||
408 | if( getVisible() ) | ||
409 | { | ||
410 | BOOL flash = FALSE; | ||
411 | if( mFlashing ) | ||
412 | { | ||
413 | F32 elapsed = LLButton::sFlashingTimer.getElapsedTimeF32(); | ||
414 | flash = S32(elapsed * 2) & 1; | ||
415 | } | ||
416 | |||
417 | BOOL pressed_by_keyboard = FALSE; | ||
418 | if (hasFocus()) | ||
419 | { | ||
420 | pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN)); | ||
421 | } | ||
422 | |||
423 | // Unselected image assignments | ||
424 | S32 local_mouse_x; | ||
425 | S32 local_mouse_y; | ||
426 | LLCoordWindow cursor_pos_window; | ||
427 | getWindow()->getCursorPosition(&cursor_pos_window); | ||
428 | LLCoordGL cursor_pos_gl; | ||
429 | getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); | ||
430 | cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]); | ||
431 | cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]); | ||
432 | screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y); | ||
433 | |||
434 | BOOL pressed = pressed_by_keyboard || (this == gFocusMgr.getMouseCapture() && pointInView(local_mouse_x, local_mouse_y)); | ||
435 | |||
436 | BOOL display_state = FALSE; | ||
437 | if( pressed ) | ||
438 | { | ||
439 | mImagep = mImageSelected; | ||
440 | // show the resulting state after releasing the mouse button while it is down | ||
441 | display_state = mToggleState ? FALSE : TRUE; | ||
442 | } | ||
443 | else | ||
444 | { | ||
445 | display_state = mToggleState || flash; | ||
446 | } | ||
447 | |||
448 | BOOL use_glow_effect = FALSE; | ||
449 | if ( mNeedsHighlight ) | ||
450 | { | ||
451 | if (display_state) | ||
452 | { | ||
453 | if (mImageHoverSelected) | ||
454 | { | ||
455 | mImagep = mImageHoverSelected; | ||
456 | } | ||
457 | else | ||
458 | { | ||
459 | mImagep = mImageSelected; | ||
460 | use_glow_effect = TRUE; | ||
461 | } | ||
462 | } | ||
463 | else | ||
464 | { | ||
465 | if (mImageHoverUnselected) | ||
466 | { | ||
467 | mImagep = mImageHoverUnselected; | ||
468 | } | ||
469 | else | ||
470 | { | ||
471 | mImagep = mImageUnselected; | ||
472 | use_glow_effect = TRUE; | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | else if ( display_state ) | ||
477 | { | ||
478 | mImagep = mImageSelected; | ||
479 | } | ||
480 | else | ||
481 | { | ||
482 | mImagep = mImageUnselected; | ||
483 | } | ||
484 | |||
485 | // Override if more data is available | ||
486 | // HACK: Use gray checked state to mean either: | ||
487 | // enabled and tentative | ||
488 | // or | ||
489 | // disabled but checked | ||
490 | if (!mImageDisabledSelected.isNull() && ( (mEnabled && mTentative) || (!mEnabled && display_state ) ) ) | ||
491 | { | ||
492 | mImagep = mImageDisabledSelected; | ||
493 | } | ||
494 | else if (!mImageDisabled.isNull() && !mEnabled && !display_state) | ||
495 | { | ||
496 | mImagep = mImageDisabled; | ||
497 | } | ||
498 | |||
499 | if (mNeedsHighlight && !mImagep) | ||
500 | { | ||
501 | use_glow_effect = TRUE; | ||
502 | } | ||
503 | |||
504 | // Figure out appropriate color for the text | ||
505 | LLColor4 label_color; | ||
506 | |||
507 | if ( mEnabled ) | ||
508 | { | ||
509 | if ( !display_state ) | ||
510 | { | ||
511 | label_color = mUnselectedLabelColor; | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | label_color = mSelectedLabelColor; | ||
516 | } | ||
517 | } | ||
518 | else | ||
519 | { | ||
520 | if ( !display_state ) | ||
521 | { | ||
522 | label_color = mDisabledLabelColor; | ||
523 | } | ||
524 | else | ||
525 | { | ||
526 | label_color = mDisabledSelectedLabelColor; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | // Unselected label assignments | ||
531 | LLWString label; | ||
532 | |||
533 | if( display_state ) | ||
534 | { | ||
535 | if( mEnabled || mDisabledSelectedLabel.empty() ) | ||
536 | { | ||
537 | label = mSelectedLabel; | ||
538 | } | ||
539 | else | ||
540 | { | ||
541 | label = mDisabledSelectedLabel; | ||
542 | } | ||
543 | } | ||
544 | else | ||
545 | { | ||
546 | if( mEnabled || mDisabledLabel.empty() ) | ||
547 | { | ||
548 | label = mUnselectedLabel; | ||
549 | } | ||
550 | else | ||
551 | { | ||
552 | label = mDisabledLabel; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | // draw default button border | ||
557 | if (mEnabled && mBorderEnabled && gFocusMgr.getAppHasFocus()) // because we're the default button in a panel | ||
558 | { | ||
559 | drawBorder(LLUI::sColorsGroup->getColor( "ButtonBorderColor" ), BORDER_SIZE); | ||
560 | } | ||
561 | |||
562 | // overlay with keyboard focus border | ||
563 | if (hasFocus()) | ||
564 | { | ||
565 | F32 lerp_amt = gFocusMgr.getFocusFlashAmt(); | ||
566 | drawBorder(gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt))); | ||
567 | } | ||
568 | |||
569 | if (use_glow_effect) | ||
570 | { | ||
571 | mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); | ||
572 | } | ||
573 | else | ||
574 | { | ||
575 | mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f)); | ||
576 | } | ||
577 | |||
578 | // Draw button image, if available. | ||
579 | // Otherwise draw basic rectangular button. | ||
580 | if( mImagep.notNull() && !mScaleImage) | ||
581 | { | ||
582 | gl_draw_image( 0, 0, mImagep, mEnabled ? mImageColor : mDisabledImageColor ); | ||
583 | if (mCurGlowStrength > 0.01f) | ||
584 | { | ||
585 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); | ||
586 | gl_draw_scaled_image_with_border(0, 0, 0, 0, mImagep->getWidth(), mImagep->getHeight(), mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE); | ||
587 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
588 | } | ||
589 | } | ||
590 | else | ||
591 | if ( mImagep.notNull() && mScaleImage) | ||
592 | { | ||
593 | gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(), | ||
594 | mImagep, mEnabled ? mImageColor : mDisabledImageColor ); | ||
595 | if (mCurGlowStrength > 0.01f) | ||
596 | { | ||
597 | glBlendFunc(GL_SRC_ALPHA, GL_ONE); | ||
598 | gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(), | ||
599 | mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE); | ||
600 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
601 | } | ||
602 | } | ||
603 | else | ||
604 | { | ||
605 | // no image | ||
606 | llalerts << "No image for button " << mName << llendl; | ||
607 | // draw it in pink so we can find it | ||
608 | gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE); | ||
609 | } | ||
610 | |||
611 | // Draw label | ||
612 | if( !label.empty() ) | ||
613 | { | ||
614 | S32 drawable_width = mRect.getWidth() - mLeftHPad - mRightHPad; | ||
615 | |||
616 | LLWString::trim(label); | ||
617 | |||
618 | S32 x; | ||
619 | switch( mHAlign ) | ||
620 | { | ||
621 | case LLFontGL::RIGHT: | ||
622 | x = mRect.getWidth() - mRightHPad; | ||
623 | break; | ||
624 | case LLFontGL::HCENTER: | ||
625 | x = mRect.getWidth() / 2; | ||
626 | break; | ||
627 | case LLFontGL::LEFT: | ||
628 | default: | ||
629 | x = mLeftHPad; | ||
630 | break; | ||
631 | } | ||
632 | |||
633 | S32 y_offset = 2 + (mRect.getHeight() - 20)/2; | ||
634 | |||
635 | if (pressed || display_state) | ||
636 | { | ||
637 | y_offset--; | ||
638 | x++; | ||
639 | } | ||
640 | |||
641 | mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), | ||
642 | label_color, | ||
643 | mHAlign, LLFontGL::BOTTOM, | ||
644 | mDropShadowedText ? LLFontGL::DROP_SHADOW : LLFontGL::NORMAL, | ||
645 | U32_MAX, drawable_width, | ||
646 | NULL, FALSE, FALSE); | ||
647 | } | ||
648 | |||
649 | if (sDebugRects | ||
650 | || (LLView::sEditingUI && this == LLView::sEditingUIView)) | ||
651 | { | ||
652 | drawDebugRect(); | ||
653 | } | ||
654 | } | ||
655 | // reset hover status for next frame | ||
656 | mNeedsHighlight = FALSE; | ||
657 | } | ||
658 | |||
659 | void LLButton::drawBorder(const LLColor4& color, S32 size) | ||
660 | { | ||
661 | S32 left = -size; | ||
662 | S32 top = mRect.getHeight() + size; | ||
663 | S32 right = mRect.getWidth() + size; | ||
664 | S32 bottom = -size; | ||
665 | |||
666 | if (mImagep.isNull()) | ||
667 | { | ||
668 | gl_rect_2d(left, top, right, bottom, color, FALSE); | ||
669 | return; | ||
670 | } | ||
671 | |||
672 | if (mScaleImage) | ||
673 | { | ||
674 | gl_draw_scaled_image_with_border(left, bottom, mFixedWidth, mFixedHeight, right-left, top-bottom, | ||
675 | mImagep, color, TRUE ); | ||
676 | } | ||
677 | else | ||
678 | { | ||
679 | gl_draw_scaled_image_with_border(left, bottom, 0, 0, mImagep->getWidth() + size * 2, | ||
680 | mImagep->getHeight() + size * 2, mImagep, color, TRUE ); | ||
681 | } | ||
682 | } | ||
683 | |||
684 | void LLButton::setClickedCallback(void (*cb)(void*), void* userdata) | ||
685 | { | ||
686 | mClickedCallback = cb; | ||
687 | if (userdata) | ||
688 | { | ||
689 | mCallbackUserData = userdata; | ||
690 | } | ||
691 | } | ||
692 | |||
693 | |||
694 | void LLButton::setToggleState(BOOL b) | ||
695 | { | ||
696 | if( b != mToggleState ) | ||
697 | { | ||
698 | mToggleState = b; | ||
699 | LLValueChangedEvent *evt = new LLValueChangedEvent(this, mToggleState); | ||
700 | fireEvent(evt, ""); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | void LLButton::setValue(const LLSD& value ) | ||
705 | { | ||
706 | mToggleState = value.asBoolean(); | ||
707 | } | ||
708 | |||
709 | LLSD LLButton::getValue() const | ||
710 | { | ||
711 | return mToggleState; | ||
712 | } | ||
713 | |||
714 | void LLButton::setLabel( const LLString& label ) | ||
715 | { | ||
716 | setLabelUnselected(label); | ||
717 | setLabelSelected(label); | ||
718 | } | ||
719 | |||
720 | //virtual | ||
721 | BOOL LLButton::setLabelArg( const LLString& key, const LLString& text ) | ||
722 | { | ||
723 | mUnselectedLabel.setArg(key, text); | ||
724 | mSelectedLabel.setArg(key, text); | ||
725 | return TRUE; | ||
726 | } | ||
727 | |||
728 | void LLButton::setLabelUnselected( const LLString& label ) | ||
729 | { | ||
730 | mUnselectedLabel = label; | ||
731 | } | ||
732 | |||
733 | void LLButton::setLabelSelected( const LLString& label ) | ||
734 | { | ||
735 | mSelectedLabel = label; | ||
736 | } | ||
737 | |||
738 | void LLButton::setDisabledLabel( const LLString& label ) | ||
739 | { | ||
740 | mDisabledLabel = label; | ||
741 | } | ||
742 | |||
743 | void LLButton::setDisabledSelectedLabel( const LLString& label ) | ||
744 | { | ||
745 | mDisabledSelectedLabel = label; | ||
746 | } | ||
747 | |||
748 | void LLButton::setImageUnselectedID( const LLUUID &image_id ) | ||
749 | { | ||
750 | mImageUnselectedName = ""; | ||
751 | mImageUnselected = LLUI::sImageProvider->getUIImageByID(image_id); | ||
752 | } | ||
753 | |||
754 | void LLButton::setImages( const LLString &image_name, const LLString &selected_name ) | ||
755 | { | ||
756 | setImageUnselected(image_name); | ||
757 | setImageSelected(selected_name); | ||
758 | |||
759 | } | ||
760 | |||
761 | void LLButton::setImageSelectedID( const LLUUID &image_id ) | ||
762 | { | ||
763 | mImageSelectedName = ""; | ||
764 | mImageSelected = LLUI::sImageProvider->getUIImageByID(image_id); | ||
765 | } | ||
766 | |||
767 | void LLButton::setImageColor(const LLColor4& c) | ||
768 | { | ||
769 | mImageColor = c; | ||
770 | } | ||
771 | |||
772 | |||
773 | void LLButton::setImageDisabledID( const LLUUID &image_id ) | ||
774 | { | ||
775 | mImageDisabledName = ""; | ||
776 | mImageDisabled = LLUI::sImageProvider->getUIImageByID(image_id); | ||
777 | mDisabledImageColor = mImageColor; | ||
778 | mDisabledImageColor.mV[VALPHA] *= 0.5f; | ||
779 | } | ||
780 | |||
781 | void LLButton::setImageDisabledSelectedID( const LLUUID &image_id ) | ||
782 | { | ||
783 | mImageDisabledSelectedName = ""; | ||
784 | mImageDisabledSelected = LLUI::sImageProvider->getUIImageByID(image_id); | ||
785 | mDisabledImageColor = mImageColor; | ||
786 | mDisabledImageColor.mV[VALPHA] *= 0.5f; | ||
787 | } | ||
788 | |||
789 | void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name, const LLColor4& c ) | ||
790 | { | ||
791 | setImageDisabled(image_name); | ||
792 | setImageDisabledSelected(selected_name); | ||
793 | mDisabledImageColor = c; | ||
794 | } | ||
795 | |||
796 | |||
797 | void LLButton::setImageHoverSelectedID( const LLUUID& image_id ) | ||
798 | { | ||
799 | mImageHoverSelectedName = ""; | ||
800 | mImageHoverSelected = LLUI::sImageProvider->getUIImageByID(image_id); | ||
801 | } | ||
802 | |||
803 | void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name) | ||
804 | { | ||
805 | LLColor4 clr = mImageColor; | ||
806 | clr.mV[VALPHA] *= .5f; | ||
807 | setDisabledImages( image_name, selected_name, clr ); | ||
808 | } | ||
809 | |||
810 | void LLButton::setImageHoverUnselectedID( const LLUUID& image_id ) | ||
811 | { | ||
812 | mImageHoverUnselectedName = ""; | ||
813 | mImageHoverUnselected = LLUI::sImageProvider->getUIImageByID(image_id); | ||
814 | } | ||
815 | |||
816 | void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name ) | ||
817 | { | ||
818 | setImageHoverUnselected(image_name); | ||
819 | setImageHoverSelected(selected_name); | ||
820 | } | ||
821 | |||
822 | // static | ||
823 | void LLButton::onMouseCaptureLost( LLMouseHandler* old_captor ) | ||
824 | { | ||
825 | LLButton* self = (LLButton*) old_captor; | ||
826 | self->mMouseDownTimer.stop(); | ||
827 | } | ||
828 | |||
829 | //------------------------------------------------------------------------- | ||
830 | // LLSquareButton | ||
831 | //------------------------------------------------------------------------- | ||
832 | LLSquareButton::LLSquareButton(const LLString& name, const LLRect& rect, | ||
833 | const LLString& label, | ||
834 | const LLFontGL *font, | ||
835 | const LLString& control_name, | ||
836 | void (*click_callback)(void*), | ||
837 | void *callback_data, | ||
838 | const LLString& selected_label ) | ||
839 | : LLButton(name, rect, "","", | ||
840 | control_name, | ||
841 | click_callback, callback_data, | ||
842 | font, | ||
843 | label, | ||
844 | (selected_label.empty() ? label : selected_label) ) | ||
845 | { | ||
846 | setImageUnselected("square_btn_32x128.tga"); | ||
847 | // mImageUnselected = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga"))); | ||
848 | setImageSelected("square_btn_selected_32x128.tga"); | ||
849 | // mImageSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga"))); | ||
850 | setImageDisabled("square_btn_32x128.tga"); | ||
851 | //mDisabledImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga"))); | ||
852 | setImageDisabledSelected("square_btn_selected_32x128.tga"); | ||
853 | //mDisabledSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga"))); | ||
854 | mImageColor = LLUI::sColorsGroup->getColor("ButtonColor"); | ||
855 | } | ||
856 | |||
857 | //------------------------------------------------------------------------- | ||
858 | // Utilities | ||
859 | //------------------------------------------------------------------------- | ||
860 | S32 round_up(S32 grid, S32 value) | ||
861 | { | ||
862 | S32 mod = value % grid; | ||
863 | |||
864 | if (mod > 0) | ||
865 | { | ||
866 | // not even multiple | ||
867 | return value + (grid - mod); | ||
868 | } | ||
869 | else | ||
870 | { | ||
871 | return value; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | void LLButton::setImageUnselected(const LLString &image_name) | ||
876 | { | ||
877 | setImageUnselectedID(LLUI::findAssetUUIDByName(image_name)); | ||
878 | mImageUnselectedName = image_name; | ||
879 | } | ||
880 | |||
881 | void LLButton::setImageSelected(const LLString &image_name) | ||
882 | { | ||
883 | setImageSelectedID(LLUI::findAssetUUIDByName(image_name)); | ||
884 | mImageSelectedName = image_name; | ||
885 | } | ||
886 | |||
887 | void LLButton::setImageHoverSelected(const LLString &image_name) | ||
888 | { | ||
889 | setImageHoverSelectedID(LLUI::findAssetUUIDByName(image_name)); | ||
890 | mImageHoverSelectedName = image_name; | ||
891 | } | ||
892 | |||
893 | void LLButton::setImageHoverUnselected(const LLString &image_name) | ||
894 | { | ||
895 | setImageHoverUnselectedID(LLUI::findAssetUUIDByName(image_name)); | ||
896 | mImageHoverUnselectedName = image_name; | ||
897 | } | ||
898 | |||
899 | void LLButton::setImageDisabled(const LLString &image_name) | ||
900 | { | ||
901 | setImageDisabledID(LLUI::findAssetUUIDByName(image_name)); | ||
902 | mImageDisabledName = image_name; | ||
903 | } | ||
904 | |||
905 | void LLButton::setImageDisabledSelected(const LLString &image_name) | ||
906 | { | ||
907 | setImageDisabledSelectedID(LLUI::findAssetUUIDByName(image_name)); | ||
908 | mImageDisabledSelectedName = image_name; | ||
909 | } | ||
910 | |||
911 | void LLButton::addImageAttributeToXML(LLXMLNodePtr node, | ||
912 | const LLString& image_name, | ||
913 | const LLUUID& image_id, | ||
914 | const LLString& xml_tag_name) const | ||
915 | { | ||
916 | if( !image_name.empty() ) | ||
917 | { | ||
918 | node->createChild(xml_tag_name, TRUE)->setStringValue(image_name); | ||
919 | } | ||
920 | else if( image_id != LLUUID::null ) | ||
921 | { | ||
922 | node->createChild(xml_tag_name + "_id", TRUE)->setUUIDValue(image_id); | ||
923 | } | ||
924 | } | ||
925 | |||
926 | // virtual | ||
927 | LLXMLNodePtr LLButton::getXML(bool save_children) const | ||
928 | { | ||
929 | LLXMLNodePtr node = LLUICtrl::getXML(); | ||
930 | |||
931 | node->createChild("label", TRUE)->setStringValue(getLabelUnselected()); | ||
932 | node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected()); | ||
933 | node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); | ||
934 | node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign)); | ||
935 | node->createChild("border_width", TRUE)->setIntValue(mFixedWidth); | ||
936 | node->createChild("border_height", TRUE)->setIntValue(mFixedHeight); | ||
937 | |||
938 | addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected"); | ||
939 | addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected"); | ||
940 | addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,"image_hover_selected"); | ||
941 | addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,"image_hover_unselected"); | ||
942 | addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,"image_disabled"); | ||
943 | addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,"image_disabled_selected"); | ||
944 | |||
945 | node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage); | ||
946 | |||
947 | return node; | ||
948 | } | ||
949 | |||
950 | // static | ||
951 | LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) | ||
952 | { | ||
953 | LLString name("button"); | ||
954 | node->getAttributeString("name", name); | ||
955 | |||
956 | LLString label = name; | ||
957 | node->getAttributeString("label", label); | ||
958 | |||
959 | LLString label_selected = label; | ||
960 | node->getAttributeString("label_selected", label_selected); | ||
961 | |||
962 | LLFontGL* font = selectFont(node); | ||
963 | |||
964 | LLString image_unselected; | ||
965 | if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected); | ||
966 | |||
967 | LLString image_selected; | ||
968 | if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected); | ||
969 | |||
970 | LLString image_hover_selected; | ||
971 | if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected); | ||
972 | |||
973 | LLString image_hover_unselected; | ||
974 | if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected); | ||
975 | |||
976 | LLString image_disabled_selected; | ||
977 | if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected); | ||
978 | |||
979 | LLString image_disabled; | ||
980 | if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled); | ||
981 | |||
982 | LLButton *button = new LLButton(name, | ||
983 | LLRect(), | ||
984 | image_unselected, | ||
985 | image_selected, | ||
986 | "", | ||
987 | NULL, | ||
988 | parent, | ||
989 | font, | ||
990 | label, | ||
991 | label_selected); | ||
992 | |||
993 | node->getAttributeS32("border_width", button->mFixedWidth); | ||
994 | node->getAttributeS32("border_height", button->mFixedHeight); | ||
995 | |||
996 | if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected); | ||
997 | |||
998 | if(image_hover_unselected != LLString::null) button->setImageHoverUnselected(image_hover_unselected); | ||
999 | |||
1000 | if(image_disabled_selected != LLString::null) button->setImageDisabledSelected(image_disabled_selected ); | ||
1001 | |||
1002 | if(image_disabled != LLString::null) button->setImageDisabled(image_disabled); | ||
1003 | |||
1004 | |||
1005 | if (node->hasAttribute("halign")) | ||
1006 | { | ||
1007 | LLFontGL::HAlign halign = selectFontHAlign(node); | ||
1008 | button->setHAlign(halign); | ||
1009 | } | ||
1010 | |||
1011 | if (node->hasAttribute("scale_image")) | ||
1012 | { | ||
1013 | BOOL needsScale = FALSE; | ||
1014 | node->getAttributeBOOL("scale_image",needsScale); | ||
1015 | button->setScaleImage( needsScale ); | ||
1016 | } | ||
1017 | |||
1018 | if(label.empty()) | ||
1019 | { | ||
1020 | button->setLabelUnselected(node->getTextContents()); | ||
1021 | } | ||
1022 | if (label_selected.empty()) | ||
1023 | { | ||
1024 | button->setLabelSelected(node->getTextContents()); | ||
1025 | } | ||
1026 | |||
1027 | button->initFromXML(node, parent); | ||
1028 | |||
1029 | return button; | ||
1030 | } | ||
1031 | |||