summaryrefslogtreecommitdiff
path: root/indra/llui/llbutton.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/llbutton.cpp')
-rw-r--r--indra/llui/llbutton.cpp1012
1 files changed, 1012 insertions, 0 deletions
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
new file mode 100644
index 0000000000..c02be6bb8d
--- /dev/null
+++ b/indra/llui/llbutton.cpp
@@ -0,0 +1,1012 @@
+/**
+ * @file llbutton.cpp
+ * @brief LLButton base class
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llbutton.h"
+
+// Linden library includes
+#include "v4color.h"
+#include "llstring.h"
+
+// Project includes
+#include "llkeyboard.h"
+#include "llgl.h"
+#include "llui.h"
+#include "lluiconstants.h"
+//#include "llcallbacklist.h"
+#include "llresmgr.h"
+#include "llcriticaldamp.h"
+#include "llglheaders.h"
+#include "llfocusmgr.h"
+#include "llwindow.h"
+
+// globals loaded from settings.xml
+S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI
+S32 LLBUTTON_H_PAD = 0;
+S32 LLBUTTON_V_PAD = 0;
+S32 BTN_HEIGHT_SMALL= 0;
+S32 BTN_HEIGHT = 0;
+
+S32 BTN_GRID = 12;
+S32 BORDER_SIZE = 1;
+
+// static
+LLFrameTimer LLButton::sFlashingTimer;
+
+LLButton::LLButton( const LLString& name, const LLRect& rect, const LLString& control_name, void (*click_callback)(void*), void *callback_data)
+: LLUICtrl(name, rect, TRUE, NULL, NULL),
+ mClickedCallback( click_callback ),
+ mMouseDownCallback( NULL ),
+ mMouseUpCallback( NULL ),
+ mHeldDownCallback( NULL ),
+ mGLFont( NULL ),
+ mHeldDownDelay( 0.5f ), // seconds until held-down callback is called
+ mImageUnselected( NULL ),
+ mImageSelected( NULL ),
+ mImageHoverSelected( NULL ),
+ mImageHoverUnselected( NULL ),
+ mImageDisabled( NULL ),
+ mImageDisabledSelected( NULL ),
+ mToggleState( FALSE ),
+ mScaleImage( TRUE ),
+ mDropShadowedText( TRUE ),
+ mBorderEnabled( FALSE ),
+ mFlashing( FALSE ),
+ mHAlign( LLFontGL::HCENTER ),
+ mLeftHPad( LLBUTTON_H_PAD ),
+ mRightHPad( LLBUTTON_H_PAD ),
+ mFixedWidth( 16 ),
+ mFixedHeight( 16 ),
+ mHoverGlowStrength(0.15f),
+ mCurGlowStrength(0.f),
+ mNeedsHighlight(FALSE),
+ mCommitOnReturn(TRUE),
+ mImagep( NULL )
+{
+ mUnselectedLabel = name;
+ mSelectedLabel = name;
+
+ setImageUnselected("button_enabled_32x128.tga");
+ setImageSelected("button_enabled_selected_32x128.tga");
+ setImageDisabled("button_disabled_32x128.tga");
+ setImageDisabledSelected("button_disabled_32x128.tga");
+
+ mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
+ mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
+
+ init(click_callback, callback_data, NULL, control_name);
+}
+
+
+LLButton::LLButton(const LLString& name, const LLRect& rect,
+ const LLString &unselected_image_name,
+ const LLString &selected_image_name,
+ const LLString& control_name,
+ void (*click_callback)(void*),
+ void *callback_data,
+ const LLFontGL *font,
+ const LLString& unselected_label,
+ const LLString& selected_label )
+: LLUICtrl(name, rect, TRUE, NULL, NULL),
+ mClickedCallback( click_callback ),
+ mMouseDownCallback( NULL ),
+ mMouseUpCallback( NULL ),
+ mHeldDownCallback( NULL ),
+ mGLFont( NULL ),
+ mHeldDownDelay( 0.5f ), // seconds until held-down callback is called
+ mImageUnselected( NULL ),
+ mImageSelected( NULL ),
+ mImageHoverSelected( NULL ),
+ mImageHoverUnselected( NULL ),
+ mImageDisabled( NULL ),
+ mImageDisabledSelected( NULL ),
+ mToggleState( FALSE ),
+ mScaleImage( TRUE ),
+ mDropShadowedText( TRUE ),
+ mBorderEnabled( FALSE ),
+ mFlashing( FALSE ),
+ mHAlign( LLFontGL::HCENTER ),
+ mLeftHPad( LLBUTTON_H_PAD ),
+ mRightHPad( LLBUTTON_H_PAD ),
+ mFixedWidth( 16 ),
+ mFixedHeight( 16 ),
+ mHoverGlowStrength(0.25f),
+ mCurGlowStrength(0.f),
+ mNeedsHighlight(FALSE),
+ mCommitOnReturn(TRUE),
+ mImagep( NULL )
+{
+ mUnselectedLabel = unselected_label;
+ mSelectedLabel = selected_label;
+
+ // by default, disabled color is same as enabled
+ mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
+ mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
+
+ if( unselected_image_name != "" )
+ {
+ setImageUnselected(unselected_image_name);
+ setImageDisabled(unselected_image_name);
+
+ mDisabledImageColor.mV[VALPHA] = 0.5f;
+ mImageDisabled = mImageUnselected;
+ mDisabledImageColor.mV[VALPHA] = 0.5f;
+ // user-specified image - don't use fixed borders unless requested
+ mFixedWidth = 0;
+ mFixedHeight = 0;
+ mScaleImage = FALSE;
+ }
+ else
+ {
+ setImageUnselected("button_enabled_32x128.tga");
+ setImageDisabled("button_disabled_32x128.tga");
+ }
+
+ if( selected_image_name != "" )
+ {
+ setImageSelected(selected_image_name);
+ setImageDisabledSelected(selected_image_name);
+
+ mDisabledImageColor.mV[VALPHA] = 0.5f;
+ // user-specified image - don't use fixed borders unless requested
+ mFixedWidth = 0;
+ mFixedHeight = 0;
+ mScaleImage = FALSE;
+ }
+ else
+ {
+ setImageSelected("button_enabled_selected_32x128.tga");
+ setImageDisabledSelected("button_disabled_32x128.tga");
+ }
+
+ init(click_callback, callback_data, font, control_name);
+}
+
+void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const LLString& control_name)
+{
+ mGLFont = ( font ? font : LLFontGL::sSansSerif);
+
+ // Hack to make sure there is space for at least one character
+ if (mRect.getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(" "))
+ {
+ // Use old defaults
+ mLeftHPad = LLBUTTON_ORIG_H_PAD;
+ mRightHPad = LLBUTTON_ORIG_H_PAD;
+ }
+
+ mCallbackUserData = callback_data;
+ mMouseDownTimer.stop();
+
+ setControlName(control_name, NULL);
+
+ mUnselectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) );
+ mSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) );
+ mDisabledLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) );
+ mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) );
+ mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) );
+ mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) );
+ mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) );
+}
+
+LLButton::~LLButton()
+{
+ if( this == gFocusMgr.getMouseCapture() )
+ {
+ gFocusMgr.setMouseCapture( NULL, NULL );
+ }
+}
+
+// virtual
+EWidgetType LLButton::getWidgetType() const
+{
+ return WIDGET_TYPE_BUTTON;
+}
+
+// virtual
+LLString LLButton::getWidgetTag() const
+{
+ return LL_BUTTON_TAG;
+}
+
+// HACK: Committing a button is the same as instantly clicking it.
+// virtual
+void LLButton::onCommit()
+{
+ // WARNING: Sometimes clicking a button destroys the floater or
+ // panel containing it. Therefore we need to call mClickedCallback
+ // LAST, otherwise this becomes deleted memory.
+ LLUICtrl::onCommit();
+
+ if (mMouseDownCallback)
+ {
+ (*mMouseDownCallback)(mCallbackUserData);
+ }
+
+ if (mMouseUpCallback)
+ {
+ (*mMouseUpCallback)(mCallbackUserData);
+ }
+
+ if (mSoundFlags & MOUSE_DOWN)
+ {
+ make_ui_sound("UISndClick");
+ }
+
+ if (mSoundFlags & MOUSE_UP)
+ {
+ make_ui_sound("UISndClickRelease");
+ }
+
+ if (mClickedCallback)
+ {
+ (*mClickedCallback)( mCallbackUserData );
+ }
+}
+
+BOOL LLButton::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
+{
+ BOOL handled = FALSE;
+ if( getVisible() && mEnabled && !called_from_parent && ' ' == uni_char && !gKeyboard->getKeyRepeated(' '))
+ {
+ if (mClickedCallback)
+ {
+ (*mClickedCallback)( mCallbackUserData );
+ }
+ handled = TRUE;
+ }
+ return handled;
+}
+
+BOOL LLButton::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent )
+{
+ BOOL handled = FALSE;
+ if( getVisible() && mEnabled && !called_from_parent )
+ {
+ if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
+ {
+ if (mClickedCallback)
+ {
+ (*mClickedCallback)( mCallbackUserData );
+ }
+ handled = TRUE;
+ }
+ }
+ return handled;
+}
+
+
+BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ // Route future Mouse messages here preemptively. (Release on mouse up.)
+ gFocusMgr.setMouseCapture( this, &LLButton::onMouseCaptureLost );
+
+ if (hasTabStop() && !getIsChrome())
+ {
+ setFocus(TRUE);
+ }
+
+ if (mMouseDownCallback)
+ {
+ (*mMouseDownCallback)(mCallbackUserData);
+ }
+
+ mMouseDownTimer.start();
+
+ if (mSoundFlags & MOUSE_DOWN)
+ {
+ make_ui_sound("UISndClick");
+ }
+
+ return TRUE;
+}
+
+
+BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ // We only handle the click if the click both started and ended within us
+ if( this == gFocusMgr.getMouseCapture() )
+ {
+ // Regardless of where mouseup occurs, handle callback
+ if (mMouseUpCallback)
+ {
+ (*mMouseUpCallback)(mCallbackUserData);
+ }
+
+ mMouseDownTimer.stop();
+
+ // Always release the mouse
+ gFocusMgr.setMouseCapture( NULL, NULL );
+
+ // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
+ // If mouseup in the widget, it's been clicked
+ if (pointInView(x, y))
+ {
+ if (mSoundFlags & MOUSE_UP)
+ {
+ make_ui_sound("UISndClickRelease");
+ }
+
+ if (mClickedCallback)
+ {
+ (*mClickedCallback)( mCallbackUserData );
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = FALSE;
+
+ LLMouseHandler* other_captor = gFocusMgr.getMouseCapture();
+ mNeedsHighlight = other_captor == NULL ||
+ other_captor == this ||
+ // this following bit is to support modal dialogs
+ (other_captor->isView() && hasAncestor((LLView*)other_captor));
+
+ if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback)
+ {
+ F32 elapsed = mMouseDownTimer.getElapsedTimeF32();
+ if( mHeldDownDelay < elapsed )
+ {
+ mHeldDownCallback( mCallbackUserData );
+ }
+ }
+
+ // We only handle the click if the click both started and ended within us
+ if( this == gFocusMgr.getMouseCapture() )
+ {
+ handled = TRUE;
+ }
+ else if( getVisible() )
+ {
+ // Opaque
+ handled = TRUE;
+ }
+
+ if( handled )
+ {
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
+ }
+
+ return handled;
+}
+
+
+// virtual
+void LLButton::draw()
+{
+ if( getVisible() )
+ {
+ BOOL flash = FALSE;
+ if( mFlashing )
+ {
+ F32 elapsed = LLButton::sFlashingTimer.getElapsedTimeF32();
+ flash = S32(elapsed * 2) & 1;
+ }
+
+ BOOL pressed_by_keyboard = FALSE;
+ if (hasFocus())
+ {
+ pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN));
+ }
+
+ // Unselected image assignments
+ S32 local_mouse_x;
+ S32 local_mouse_y;
+ LLCoordWindow cursor_pos_window;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+ LLCoordGL cursor_pos_gl;
+ getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+ cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]);
+ cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
+ screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
+
+ BOOL pressed = pressed_by_keyboard || (this == gFocusMgr.getMouseCapture() && pointInView(local_mouse_x, local_mouse_y));
+
+ BOOL display_state = FALSE;
+ if( pressed )
+ {
+ mImagep = mImageSelected;
+ // show the resulting state after releasing the mouse button while it is down
+ display_state = mToggleState ? FALSE : TRUE;
+ }
+ else
+ {
+ display_state = mToggleState || flash;
+ }
+
+ BOOL use_glow_effect = FALSE;
+ if ( mNeedsHighlight )
+ {
+ if (display_state)
+ {
+ if (mImageHoverSelected)
+ {
+ mImagep = mImageHoverSelected;
+ }
+ else
+ {
+ mImagep = mImageSelected;
+ use_glow_effect = TRUE;
+ }
+ }
+ else
+ {
+ if (mImageHoverUnselected)
+ {
+ mImagep = mImageHoverUnselected;
+ }
+ else
+ {
+ mImagep = mImageUnselected;
+ use_glow_effect = TRUE;
+ }
+ }
+ }
+ else if ( display_state )
+ {
+ mImagep = mImageSelected;
+ }
+ else
+ {
+ mImagep = mImageUnselected;
+ }
+
+ // Override if more data is available
+ // HACK: Use gray checked state to mean either:
+ // enabled and tentative
+ // or
+ // disabled but checked
+ if (!mImageDisabledSelected.isNull() && ( (mEnabled && mTentative) || (!mEnabled && display_state ) ) )
+ {
+ mImagep = mImageDisabledSelected;
+ }
+ else if (!mImageDisabled.isNull() && !mEnabled && !display_state)
+ {
+ mImagep = mImageDisabled;
+ }
+
+ if (mNeedsHighlight && !mImagep)
+ {
+ use_glow_effect = TRUE;
+ }
+
+ // Figure out appropriate color for the text
+ LLColor4 label_color;
+
+ if ( mEnabled )
+ {
+ if ( !display_state )
+ {
+ label_color = mUnselectedLabelColor;
+ }
+ else
+ {
+ label_color = mSelectedLabelColor;
+ }
+ }
+ else
+ {
+ if ( !display_state )
+ {
+ label_color = mDisabledLabelColor;
+ }
+ else
+ {
+ label_color = mDisabledSelectedLabelColor;
+ }
+ }
+
+ // Unselected label assignments
+ LLWString label;
+
+ if( display_state )
+ {
+ if( mEnabled || mDisabledSelectedLabel.empty() )
+ {
+ label = mSelectedLabel;
+ }
+ else
+ {
+ label = mDisabledSelectedLabel;
+ }
+ }
+ else
+ {
+ if( mEnabled || mDisabledLabel.empty() )
+ {
+ label = mUnselectedLabel;
+ }
+ else
+ {
+ label = mDisabledLabel;
+ }
+ }
+
+ // draw default button border
+ if (mEnabled && mBorderEnabled && gFocusMgr.getAppHasFocus()) // because we're the default button in a panel
+ {
+ drawBorder(LLUI::sColorsGroup->getColor( "ButtonBorderColor" ), BORDER_SIZE);
+ }
+
+ // overlay with keyboard focus border
+ if (hasFocus())
+ {
+ F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
+ drawBorder(gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt)));
+ }
+
+ if (use_glow_effect)
+ {
+ mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f));
+ }
+ else
+ {
+ mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f));
+ }
+
+ // Draw button image, if available.
+ // Otherwise draw basic rectangular button.
+ if( mImagep.notNull() && !mScaleImage)
+ {
+ gl_draw_image( 0, 0, mImagep, mEnabled ? mImageColor : mDisabledImageColor );
+ if (mCurGlowStrength > 0.01f)
+ {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ gl_draw_scaled_image_with_border(0, 0, 0, 0, mImagep->getWidth(), mImagep->getHeight(), mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ else
+ if ( mImagep.notNull() && mScaleImage)
+ {
+ gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(),
+ mImagep, mEnabled ? mImageColor : mDisabledImageColor );
+ if (mCurGlowStrength > 0.01f)
+ {
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ gl_draw_scaled_image_with_border(0, 0, mFixedWidth, mFixedHeight, mRect.getWidth(), mRect.getHeight(),
+ mImagep, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength), TRUE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ }
+ else
+ {
+ // no image
+ llalerts << "No image for button " << mName << llendl;
+ // draw it in pink so we can find it
+ gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE);
+ }
+
+ // Draw label
+ if( !label.empty() )
+ {
+ S32 drawable_width = mRect.getWidth() - mLeftHPad - mRightHPad;
+
+ LLWString::trim(label);
+
+ S32 x;
+ switch( mHAlign )
+ {
+ case LLFontGL::RIGHT:
+ x = mRect.getWidth() - mRightHPad;
+ break;
+ case LLFontGL::HCENTER:
+ x = mRect.getWidth() / 2;
+ break;
+ case LLFontGL::LEFT:
+ default:
+ x = mLeftHPad;
+ break;
+ }
+
+ S32 y_offset = 2 + (mRect.getHeight() - 20)/2;
+
+ if (pressed || display_state)
+ {
+ y_offset--;
+ x++;
+ }
+
+ mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
+ label_color,
+ mHAlign, LLFontGL::BOTTOM,
+ mDropShadowedText ? LLFontGL::DROP_SHADOW : LLFontGL::NORMAL,
+ U32_MAX, drawable_width,
+ NULL, FALSE, FALSE);
+ }
+
+ if (sDebugRects
+ || (LLView::sEditingUI && this == LLView::sEditingUIView))
+ {
+ drawDebugRect();
+ }
+ }
+ // reset hover status for next frame
+ mNeedsHighlight = FALSE;
+}
+
+void LLButton::drawBorder(const LLColor4& color, S32 size)
+{
+ S32 left = -size;
+ S32 top = mRect.getHeight() + size;
+ S32 right = mRect.getWidth() + size;
+ S32 bottom = -size;
+
+ if (mImagep.isNull())
+ {
+ gl_rect_2d(left, top, right, bottom, color, FALSE);
+ return;
+ }
+
+ if (mScaleImage)
+ {
+ gl_draw_scaled_image_with_border(left, bottom, mFixedWidth, mFixedHeight, right-left, top-bottom,
+ mImagep, color, TRUE );
+ }
+ else
+ {
+ gl_draw_scaled_image_with_border(left, bottom, 0, 0, mImagep->getWidth() + size * 2,
+ mImagep->getHeight() + size * 2, mImagep, color, TRUE );
+ }
+}
+
+void LLButton::setClickedCallback(void (*cb)(void*), void* userdata)
+{
+ mClickedCallback = cb;
+ if (userdata)
+ {
+ mCallbackUserData = userdata;
+ }
+}
+
+
+void LLButton::setToggleState(BOOL b)
+{
+ if( b != mToggleState )
+ {
+ mToggleState = b;
+ LLValueChangedEvent *evt = new LLValueChangedEvent(this, mToggleState);
+ fireEvent(evt, "");
+ }
+}
+
+void LLButton::setValue(const LLSD& value )
+{
+ mToggleState = value.asBoolean();
+}
+
+LLSD LLButton::getValue() const
+{
+ return mToggleState;
+}
+
+void LLButton::setLabel( const LLString& label )
+{
+ setLabelUnselected(label);
+ setLabelSelected(label);
+}
+
+//virtual
+BOOL LLButton::setLabelArg( const LLString& key, const LLString& text )
+{
+ mUnselectedLabel.setArg(key, text);
+ mSelectedLabel.setArg(key, text);
+ return TRUE;
+}
+
+void LLButton::setLabelUnselected( const LLString& label )
+{
+ mUnselectedLabel = label;
+}
+
+void LLButton::setLabelSelected( const LLString& label )
+{
+ mSelectedLabel = label;
+}
+
+void LLButton::setDisabledLabel( const LLString& label )
+{
+ mDisabledLabel = label;
+}
+
+void LLButton::setDisabledSelectedLabel( const LLString& label )
+{
+ mDisabledSelectedLabel = label;
+}
+
+void LLButton::setImageUnselectedID( const LLUUID &image_id )
+{
+ mImageUnselectedName = "";
+ mImageUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
+}
+
+void LLButton::setImages( const LLString &image_name, const LLString &selected_name )
+{
+ setImageUnselected(image_name);
+ setImageSelected(selected_name);
+
+}
+
+void LLButton::setImageSelectedID( const LLUUID &image_id )
+{
+ mImageSelectedName = "";
+ mImageSelected = LLUI::sImageProvider->getUIImageByID(image_id);
+}
+
+void LLButton::setImageColor(const LLColor4& c)
+{
+ mImageColor = c;
+}
+
+
+void LLButton::setImageDisabledID( const LLUUID &image_id )
+{
+ mImageDisabledName = "";
+ mImageDisabled = LLUI::sImageProvider->getUIImageByID(image_id);
+ mDisabledImageColor = mImageColor;
+ mDisabledImageColor.mV[VALPHA] *= 0.5f;
+}
+
+void LLButton::setImageDisabledSelectedID( const LLUUID &image_id )
+{
+ mImageDisabledSelectedName = "";
+ mImageDisabledSelected = LLUI::sImageProvider->getUIImageByID(image_id);
+ mDisabledImageColor = mImageColor;
+ mDisabledImageColor.mV[VALPHA] *= 0.5f;
+}
+
+void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name, const LLColor4& c )
+{
+ setImageDisabled(image_name);
+ setImageDisabledSelected(selected_name);
+ mDisabledImageColor = c;
+}
+
+
+void LLButton::setImageHoverSelectedID( const LLUUID& image_id )
+{
+ mImageHoverSelectedName = "";
+ mImageHoverSelected = LLUI::sImageProvider->getUIImageByID(image_id);
+}
+
+void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name)
+{
+ LLColor4 clr = mImageColor;
+ clr.mV[VALPHA] *= .5f;
+ setDisabledImages( image_name, selected_name, clr );
+}
+
+void LLButton::setImageHoverUnselectedID( const LLUUID& image_id )
+{
+ mImageHoverUnselectedName = "";
+ mImageHoverUnselected = LLUI::sImageProvider->getUIImageByID(image_id);
+}
+
+void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name )
+{
+ setImageHoverUnselected(image_name);
+ setImageHoverSelected(selected_name);
+}
+
+// static
+void LLButton::onMouseCaptureLost( LLMouseHandler* old_captor )
+{
+ LLButton* self = (LLButton*) old_captor;
+ self->mMouseDownTimer.stop();
+}
+
+//-------------------------------------------------------------------------
+// LLSquareButton
+//-------------------------------------------------------------------------
+LLSquareButton::LLSquareButton(const LLString& name, const LLRect& rect,
+ const LLString& label,
+ const LLFontGL *font,
+ const LLString& control_name,
+ void (*click_callback)(void*),
+ void *callback_data,
+ const LLString& selected_label )
+: LLButton(name, rect, "","",
+ control_name,
+ click_callback, callback_data,
+ font,
+ label,
+ (selected_label.empty() ? label : selected_label) )
+{
+ setImageUnselected("square_btn_32x128.tga");
+ // mImageUnselected = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga")));
+ setImageSelected("square_btn_selected_32x128.tga");
+ // mImageSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga")));
+ setImageDisabled("square_btn_32x128.tga");
+ //mDisabledImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_32x128.tga")));
+ setImageDisabledSelected("square_btn_selected_32x128.tga");
+ //mDisabledSelectedImage = LLUI::sImageProvider->getUIImageByID(LLUUID(LLUI::sAssetsGroup->getString("square_btn_selected_32x128.tga")));
+ mImageColor = LLUI::sColorsGroup->getColor("ButtonColor");
+}
+
+//-------------------------------------------------------------------------
+// Utilities
+//-------------------------------------------------------------------------
+S32 round_up(S32 grid, S32 value)
+{
+ S32 mod = value % grid;
+
+ if (mod > 0)
+ {
+ // not even multiple
+ return value + (grid - mod);
+ }
+ else
+ {
+ return value;
+ }
+}
+
+void LLButton::setImageUnselected(const LLString &image_name)
+{
+ setImageUnselectedID(LLUI::findAssetUUIDByName(image_name));
+ mImageUnselectedName = image_name;
+}
+
+void LLButton::setImageSelected(const LLString &image_name)
+{
+ setImageSelectedID(LLUI::findAssetUUIDByName(image_name));
+ mImageSelectedName = image_name;
+}
+
+void LLButton::setImageHoverSelected(const LLString &image_name)
+{
+ setImageHoverSelectedID(LLUI::findAssetUUIDByName(image_name));
+ mImageHoverSelectedName = image_name;
+}
+
+void LLButton::setImageHoverUnselected(const LLString &image_name)
+{
+ setImageHoverUnselectedID(LLUI::findAssetUUIDByName(image_name));
+ mImageHoverUnselectedName = image_name;
+}
+
+void LLButton::setImageDisabled(const LLString &image_name)
+{
+ setImageDisabledID(LLUI::findAssetUUIDByName(image_name));
+ mImageDisabledName = image_name;
+}
+
+void LLButton::setImageDisabledSelected(const LLString &image_name)
+{
+ setImageDisabledSelectedID(LLUI::findAssetUUIDByName(image_name));
+ mImageDisabledSelectedName = image_name;
+}
+
+void LLButton::addImageAttributeToXML(LLXMLNodePtr node,
+ const LLString& image_name,
+ const LLUUID& image_id,
+ const LLString& xml_tag_name) const
+{
+ if( !image_name.empty() )
+ {
+ node->createChild(xml_tag_name, TRUE)->setStringValue(image_name);
+ }
+ else if( image_id != LLUUID::null )
+ {
+ node->createChild(xml_tag_name + "_id", TRUE)->setUUIDValue(image_id);
+ }
+}
+
+// virtual
+LLXMLNodePtr LLButton::getXML(bool save_children) const
+{
+ LLXMLNodePtr node = LLUICtrl::getXML();
+
+ node->createChild("label", TRUE)->setStringValue(getLabelUnselected());
+ node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected());
+ node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
+ node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
+ node->createChild("border_width", TRUE)->setIntValue(mFixedWidth);
+ node->createChild("border_height", TRUE)->setIntValue(mFixedHeight);
+
+ addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected");
+ addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected");
+ addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,"image_hover_selected");
+ addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,"image_hover_unselected");
+ addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,"image_disabled");
+ addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,"image_disabled_selected");
+
+ node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage);
+
+ return node;
+}
+
+// static
+LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
+{
+ LLString name("button");
+ node->getAttributeString("name", name);
+
+ LLString label = name;
+ node->getAttributeString("label", label);
+
+ LLString label_selected = label;
+ node->getAttributeString("label_selected", label_selected);
+
+ LLFontGL* font = selectFont(node);
+
+ LLString image_unselected;
+ if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
+
+ LLString image_selected;
+ if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
+
+ LLString image_hover_selected;
+ if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected);
+
+ LLString image_hover_unselected;
+ if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected);
+
+ LLString image_disabled_selected;
+ if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected);
+
+ LLString image_disabled;
+ if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled);
+
+ LLButton *button = new LLButton(name,
+ LLRect(),
+ image_unselected,
+ image_selected,
+ "",
+ NULL,
+ parent,
+ font,
+ label,
+ label_selected);
+
+ node->getAttributeS32("border_width", button->mFixedWidth);
+ node->getAttributeS32("border_height", button->mFixedHeight);
+
+ if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected);
+
+ if(image_hover_unselected != LLString::null) button->setImageHoverUnselected(image_hover_unselected);
+
+ if(image_disabled_selected != LLString::null) button->setImageDisabledSelected(image_disabled_selected );
+
+ if(image_disabled != LLString::null) button->setImageDisabled(image_disabled);
+
+
+ if (node->hasAttribute("halign"))
+ {
+ LLFontGL::HAlign halign = selectFontHAlign(node);
+ button->setHAlign(halign);
+ }
+
+ if (node->hasAttribute("scale_image"))
+ {
+ BOOL needsScale = FALSE;
+ node->getAttributeBOOL("scale_image",needsScale);
+ button->setScaleImage( needsScale );
+ }
+
+ if(label.empty())
+ {
+ button->setLabelUnselected(node->getTextContents());
+ }
+ if (label_selected.empty())
+ {
+ button->setLabelSelected(node->getTextContents());
+ }
+
+ button->initFromXML(node, parent);
+
+ return button;
+}
+