aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llbutton.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llui/llbutton.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp1031
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
49S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI
50S32 LLBUTTON_H_PAD = 0;
51S32 LLBUTTON_V_PAD = 0;
52S32 BTN_HEIGHT_SMALL= 0;
53S32 BTN_HEIGHT = 0;
54
55S32 BTN_GRID = 12;
56S32 BORDER_SIZE = 1;
57
58// static
59LLFrameTimer LLButton::sFlashingTimer;
60
61LLButton::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
106LLButton::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
190void 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
216LLButton::~LLButton()
217{
218 if( this == gFocusMgr.getMouseCapture() )
219 {
220 gFocusMgr.setMouseCapture( NULL, NULL );
221 }
222}
223
224// virtual
225EWidgetType LLButton::getWidgetType() const
226{
227 return WIDGET_TYPE_BUTTON;
228}
229
230// virtual
231LLString 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
238void 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
271BOOL 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
285BOOL 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
303BOOL 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
329BOOL 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
365BOOL 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
406void 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
659void 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
684void LLButton::setClickedCallback(void (*cb)(void*), void* userdata)
685{
686 mClickedCallback = cb;
687 if (userdata)
688 {
689 mCallbackUserData = userdata;
690 }
691}
692
693
694void 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
704void LLButton::setValue(const LLSD& value )
705{
706 mToggleState = value.asBoolean();
707}
708
709LLSD LLButton::getValue() const
710{
711 return mToggleState;
712}
713
714void LLButton::setLabel( const LLString& label )
715{
716 setLabelUnselected(label);
717 setLabelSelected(label);
718}
719
720//virtual
721BOOL LLButton::setLabelArg( const LLString& key, const LLString& text )
722{
723 mUnselectedLabel.setArg(key, text);
724 mSelectedLabel.setArg(key, text);
725 return TRUE;
726}
727
728void LLButton::setLabelUnselected( const LLString& label )
729{
730 mUnselectedLabel = label;
731}
732
733void LLButton::setLabelSelected( const LLString& label )
734{
735 mSelectedLabel = label;
736}
737
738void LLButton::setDisabledLabel( const LLString& label )
739{
740 mDisabledLabel = label;
741}
742
743void LLButton::setDisabledSelectedLabel( const LLString& label )
744{
745 mDisabledSelectedLabel = label;
746}
747
748void LLButton::setImageUnselectedID( const LLUUID &image_id )
749{
750 mImageUnselectedName = "";
751 mImageUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
752}
753
754void LLButton::setImages( const LLString &image_name, const LLString &selected_name )
755{
756 setImageUnselected(image_name);
757 setImageSelected(selected_name);
758
759}
760
761void LLButton::setImageSelectedID( const LLUUID &image_id )
762{
763 mImageSelectedName = "";
764 mImageSelected = LLUI::sImageProvider->getUIImageByID(image_id);
765}
766
767void LLButton::setImageColor(const LLColor4& c)
768{
769 mImageColor = c;
770}
771
772
773void 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
781void 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
789void 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
797void LLButton::setImageHoverSelectedID( const LLUUID& image_id )
798{
799 mImageHoverSelectedName = "";
800 mImageHoverSelected = LLUI::sImageProvider->getUIImageByID(image_id);
801}
802
803void 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
810void LLButton::setImageHoverUnselectedID( const LLUUID& image_id )
811{
812 mImageHoverUnselectedName = "";
813 mImageHoverUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
814}
815
816void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name )
817{
818 setImageHoverUnselected(image_name);
819 setImageHoverSelected(selected_name);
820}
821
822// static
823void LLButton::onMouseCaptureLost( LLMouseHandler* old_captor )
824{
825 LLButton* self = (LLButton*) old_captor;
826 self->mMouseDownTimer.stop();
827}
828
829//-------------------------------------------------------------------------
830// LLSquareButton
831//-------------------------------------------------------------------------
832LLSquareButton::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//-------------------------------------------------------------------------
860S32 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
875void LLButton::setImageUnselected(const LLString &image_name)
876{
877 setImageUnselectedID(LLUI::findAssetUUIDByName(image_name));
878 mImageUnselectedName = image_name;
879}
880
881void LLButton::setImageSelected(const LLString &image_name)
882{
883 setImageSelectedID(LLUI::findAssetUUIDByName(image_name));
884 mImageSelectedName = image_name;
885}
886
887void LLButton::setImageHoverSelected(const LLString &image_name)
888{
889 setImageHoverSelectedID(LLUI::findAssetUUIDByName(image_name));
890 mImageHoverSelectedName = image_name;
891}
892
893void LLButton::setImageHoverUnselected(const LLString &image_name)
894{
895 setImageHoverUnselectedID(LLUI::findAssetUUIDByName(image_name));
896 mImageHoverUnselectedName = image_name;
897}
898
899void LLButton::setImageDisabled(const LLString &image_name)
900{
901 setImageDisabledID(LLUI::findAssetUUIDByName(image_name));
902 mImageDisabledName = image_name;
903}
904
905void LLButton::setImageDisabledSelected(const LLString &image_name)
906{
907 setImageDisabledSelectedID(LLUI::findAssetUUIDByName(image_name));
908 mImageDisabledSelectedName = image_name;
909}
910
911void 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
927LLXMLNodePtr 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
951LLView* 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