llbutton.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llbutton.h"
00035 
00036 // Linden library includes
00037 #include "v4color.h"
00038 #include "llstring.h"
00039 
00040 // Project includes
00041 #include "llkeyboard.h"
00042 #include "llgl.h"
00043 #include "llui.h"
00044 #include "lluiconstants.h"
00045 //#include "llcallbacklist.h"
00046 #include "llresmgr.h"
00047 #include "llcriticaldamp.h"
00048 #include "llglheaders.h"
00049 #include "llfocusmgr.h"
00050 #include "llwindow.h"
00051 #include "llglimmediate.h"
00052 
00053 static LLRegisterWidget<LLButton> r("button");
00054 
00055 // globals loaded from settings.xml
00056 S32     LLBUTTON_ORIG_H_PAD     = 6; // Pre-zoomable UI
00057 S32     LLBUTTON_H_PAD  = 0;
00058 S32     LLBUTTON_V_PAD  = 0;
00059 S32 BTN_HEIGHT_SMALL= 0;
00060 S32 BTN_HEIGHT          = 0;
00061 
00062 S32 BTN_GRID            = 12;
00063 S32 BORDER_SIZE = 1;
00064 
00065 LLButton::LLButton(     const LLString& name, const LLRect& rect, const LLString& control_name, void (*click_callback)(void*), void *callback_data)
00066 :       LLUICtrl(name, rect, TRUE, NULL, NULL),
00067         mClickedCallback( click_callback ),
00068         mMouseDownCallback( NULL ),
00069         mMouseUpCallback( NULL ),
00070         mHeldDownCallback( NULL ),
00071         mGLFont( NULL ),
00072         mMouseDownFrame( 0 ),
00073         mHeldDownDelay( 0.5f ),                 // seconds until held-down callback is called
00074         mHeldDownFrameDelay( 0 ),
00075         mImageUnselected( NULL ),
00076         mImageSelected( NULL ),
00077         mImageHoverSelected( NULL ),
00078         mImageHoverUnselected( NULL ),
00079         mImageDisabled( NULL ),
00080         mImageDisabledSelected( NULL ),
00081         mToggleState( FALSE ),
00082         mIsToggle( FALSE ),
00083         mScaleImage( TRUE ),
00084         mDropShadowedText( TRUE ),
00085         mBorderEnabled( FALSE ),
00086         mFlashing( FALSE ),
00087         mHAlign( LLFontGL::HCENTER ),
00088         mLeftHPad( LLBUTTON_H_PAD ),
00089         mRightHPad( LLBUTTON_H_PAD ),
00090         mHoverGlowStrength(0.15f),
00091         mCurGlowStrength(0.f),
00092         mNeedsHighlight(FALSE),
00093         mCommitOnReturn(TRUE),
00094         mImagep( NULL )
00095 {
00096         mUnselectedLabel = name;
00097         mSelectedLabel = name;
00098 
00099         setImageUnselected("button_enabled_32x128.tga");
00100         setImageSelected("button_enabled_selected_32x128.tga");
00101         setImageDisabled("button_disabled_32x128.tga");
00102         setImageDisabledSelected("button_disabled_32x128.tga");
00103 
00104         mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
00105         mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
00106 
00107         init(click_callback, callback_data, NULL, control_name);
00108 }
00109 
00110 
00111 LLButton::LLButton(const LLString& name, const LLRect& rect, 
00112                                    const LLString &unselected_image_name, 
00113                                    const LLString &selected_image_name, 
00114                                    const LLString& control_name,
00115                                    void (*click_callback)(void*),
00116                                    void *callback_data,
00117                                    const LLFontGL *font,
00118                                    const LLString& unselected_label, 
00119                                    const LLString& selected_label )
00120 :       LLUICtrl(name, rect, TRUE, NULL, NULL),
00121         mClickedCallback( click_callback ),
00122         mMouseDownCallback( NULL ),
00123         mMouseUpCallback( NULL ),
00124         mHeldDownCallback( NULL ),
00125         mGLFont( NULL ),
00126         mMouseDownFrame( 0 ),
00127         mHeldDownDelay( 0.5f ),                 // seconds until held-down callback is called
00128         mHeldDownFrameDelay( 0 ),
00129         mImageUnselected( NULL ),
00130         mImageSelected( NULL ),
00131         mImageHoverSelected( NULL ),
00132         mImageHoverUnselected( NULL ),
00133         mImageDisabled( NULL ),
00134         mImageDisabledSelected( NULL ),
00135         mToggleState( FALSE ),
00136         mIsToggle( FALSE ),
00137         mScaleImage( TRUE ),
00138         mDropShadowedText( TRUE ),
00139         mBorderEnabled( FALSE ),
00140         mFlashing( FALSE ),
00141         mHAlign( LLFontGL::HCENTER ),
00142         mLeftHPad( LLBUTTON_H_PAD ), 
00143         mRightHPad( LLBUTTON_H_PAD ),
00144         mHoverGlowStrength(0.25f),
00145         mCurGlowStrength(0.f),
00146         mNeedsHighlight(FALSE),
00147         mCommitOnReturn(TRUE),
00148         mImagep( NULL )
00149 {
00150         mUnselectedLabel = unselected_label;
00151         mSelectedLabel = selected_label;
00152 
00153         // by default, disabled color is same as enabled
00154         mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
00155         mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" );
00156 
00157         if( unselected_image_name != "" )
00158         {
00159                 // user-specified image - don't use fixed borders unless requested
00160                 setImageUnselected(unselected_image_name);
00161                 setImageDisabled(unselected_image_name);
00162                 
00163                 mDisabledImageColor.mV[VALPHA] = 0.5f;
00164                 mScaleImage = FALSE;
00165         }
00166         else
00167         {
00168                 setImageUnselected("button_enabled_32x128.tga");
00169                 setImageDisabled("button_disabled_32x128.tga");
00170         }
00171 
00172         if( selected_image_name != "" )
00173         {
00174                 // user-specified image - don't use fixed borders unless requested
00175                 setImageSelected(selected_image_name);
00176                 setImageDisabledSelected(selected_image_name);
00177 
00178                 mDisabledImageColor.mV[VALPHA] = 0.5f;
00179                 mScaleImage = FALSE;
00180         }
00181         else
00182         {
00183                 setImageSelected("button_enabled_selected_32x128.tga");
00184                 setImageDisabledSelected("button_disabled_32x128.tga");
00185         }
00186 
00187         init(click_callback, callback_data, font, control_name);
00188 }
00189 
00190 void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const LLString& control_name)
00191 {
00192         mGLFont = ( font ? font : LLFontGL::sSansSerif);
00193 
00194         // Hack to make sure there is space for at least one character
00195         if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(" "))
00196         {
00197                 // Use old defaults
00198                 mLeftHPad = LLBUTTON_ORIG_H_PAD;
00199                 mRightHPad = LLBUTTON_ORIG_H_PAD;
00200         }
00201         
00202         mCallbackUserData = callback_data;
00203         mMouseDownTimer.stop();
00204 
00205         setControlName(control_name, NULL);
00206 
00207         mUnselectedLabelColor = (                       LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) );
00208         mSelectedLabelColor = (                 LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) );
00209         mDisabledLabelColor = (                 LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) );
00210         mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) );
00211         mHighlightColor = (                             LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) );
00212         mUnselectedBgColor = (                          LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) );
00213         mSelectedBgColor = (                            LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) );
00214 
00215         mImageOverlayAlignment = LLFontGL::HCENTER;
00216         mImageOverlayColor = LLColor4::white;
00217 }
00218 
00219 LLButton::~LLButton()
00220 {
00221         if( hasMouseCapture() )
00222         {
00223                 gFocusMgr.setMouseCapture( NULL );
00224         }
00225 }
00226 
00227 // HACK: Committing a button is the same as instantly clicking it.
00228 // virtual
00229 void LLButton::onCommit()
00230 {
00231         // WARNING: Sometimes clicking a button destroys the floater or
00232         // panel containing it.  Therefore we need to call mClickedCallback
00233         // LAST, otherwise this becomes deleted memory.
00234         LLUICtrl::onCommit();
00235 
00236         if (mMouseDownCallback)
00237         {
00238                 (*mMouseDownCallback)(mCallbackUserData);
00239         }
00240         
00241         if (mMouseUpCallback)
00242         {
00243                 (*mMouseUpCallback)(mCallbackUserData);
00244         }
00245 
00246         if (getSoundFlags() & MOUSE_DOWN)
00247         {
00248                 make_ui_sound("UISndClick");
00249         }
00250 
00251         if (getSoundFlags() & MOUSE_UP)
00252         {
00253                 make_ui_sound("UISndClickRelease");
00254         }
00255 
00256         if (mIsToggle)
00257         {
00258                 toggleState();
00259         }
00260 
00261         // do this last, as it can result in destroying this button
00262         if (mClickedCallback)
00263         {
00264                 (*mClickedCallback)( mCallbackUserData );
00265         }
00266 }
00267 
00268 
00269 
00270 BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
00271 {
00272         BOOL handled = FALSE;
00273         if(' ' == uni_char 
00274                 && !gKeyboard->getKeyRepeated(' '))
00275         {
00276                 if (mIsToggle)
00277                 {
00278                         toggleState();
00279                 }
00280 
00281                 if (mClickedCallback)
00282                 {
00283                         (*mClickedCallback)( mCallbackUserData );
00284                 }
00285                 handled = TRUE;         
00286         }
00287         return handled; 
00288 }
00289 
00290 BOOL LLButton::handleKeyHere(KEY key, MASK mask )
00291 {
00292         BOOL handled = FALSE;
00293         if( mCommitOnReturn && KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
00294         {
00295                 if (mIsToggle)
00296                 {
00297                         toggleState();
00298                 }
00299 
00300                 handled = TRUE;
00301 
00302                 if (mClickedCallback)
00303                 {
00304                         (*mClickedCallback)( mCallbackUserData );
00305                 }
00306         }
00307         return handled;
00308 }
00309 
00310 
00311 BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
00312 {
00313         // Route future Mouse messages here preemptively.  (Release on mouse up.)
00314         gFocusMgr.setMouseCapture( this );
00315 
00316         if (hasTabStop() && !getIsChrome())
00317         {
00318                 setFocus(TRUE);
00319         }
00320 
00321         if (mMouseDownCallback)
00322         {
00323                 (*mMouseDownCallback)(mCallbackUserData);
00324         }
00325 
00326         mMouseDownTimer.start();
00327         mMouseDownFrame = LLFrameTimer::getFrameCount();
00328         
00329         if (getSoundFlags() & MOUSE_DOWN)
00330         {
00331                 make_ui_sound("UISndClick");
00332         }
00333 
00334         return TRUE;
00335 }
00336 
00337 
00338 BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
00339 {
00340         // We only handle the click if the click both started and ended within us
00341         if( hasMouseCapture() )
00342         {
00343                 // Always release the mouse
00344                 gFocusMgr.setMouseCapture( NULL );
00345 
00346                 // Regardless of where mouseup occurs, handle callback
00347                 if (mMouseUpCallback)
00348                 {
00349                         (*mMouseUpCallback)(mCallbackUserData);
00350                 }
00351 
00352                 mMouseDownTimer.stop();
00353                 mMouseDownTimer.reset();
00354 
00355                 // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked.
00356                 // If mouseup in the widget, it's been clicked
00357                 if (pointInView(x, y))
00358                 {
00359                         if (getSoundFlags() & MOUSE_UP)
00360                         {
00361                                 make_ui_sound("UISndClickRelease");
00362                         }
00363 
00364                         if (mIsToggle)
00365                         {
00366                                 toggleState();
00367                         }
00368 
00369                         if (mClickedCallback)
00370                         {
00371                                 (*mClickedCallback)( mCallbackUserData );
00372                         }                       
00373                 }
00374         }
00375 
00376         return TRUE;
00377 }
00378 
00379 
00380 BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
00381 {
00382         LLMouseHandler* other_captor = gFocusMgr.getMouseCapture();
00383         mNeedsHighlight = other_captor == NULL || 
00384                                 other_captor == this ||
00385                                 // this following bit is to support modal dialogs
00386                                 (other_captor->isView() && hasAncestor((LLView*)other_captor));
00387 
00388         if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback)
00389         {
00390                 F32 elapsed = getHeldDownTime();
00391                 if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= LLFrameTimer::getFrameCount() - mMouseDownFrame)
00392                 {
00393                         mHeldDownCallback( mCallbackUserData );         
00394                 }
00395         }
00396 
00397         // We only handle the click if the click both started and ended within us
00398         getWindow()->setCursor(UI_CURSOR_ARROW);
00399         lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << llendl;
00400 
00401         return TRUE;
00402 }
00403 
00404 
00405 // virtual
00406 void LLButton::draw()
00407 {
00408         BOOL flash = FALSE;
00409         if( mFlashing )
00410         {
00411                 F32 elapsed = mFlashingTimer.getElapsedTimeF32();
00412                 S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f);
00413                 // flash on or off?
00414                 flash = (flash_count % 2 == 0) || flash_count > S32((F32)LLUI::sConfigGroup->getS32("ButtonFlashCount") * 2.f);
00415         }
00416 
00417         BOOL pressed_by_keyboard = FALSE;
00418         if (hasFocus())
00419         {
00420                 pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN));
00421         }
00422 
00423         // Unselected image assignments
00424         S32 local_mouse_x;
00425         S32 local_mouse_y;
00426         LLCoordWindow cursor_pos_window;
00427         getWindow()->getCursorPosition(&cursor_pos_window);
00428         LLCoordGL cursor_pos_gl;
00429         getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
00430         cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]);
00431         cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
00432         screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
00433 
00434         BOOL pressed = pressed_by_keyboard 
00435                                         || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) 
00436                                         || mToggleState;
00437         
00438         BOOL use_glow_effect = FALSE;
00439         if ( mNeedsHighlight || flash )
00440         {
00441                 if (pressed)
00442                 {
00443                         if (mImageHoverSelected)
00444                         {
00445                                 mImagep = mImageHoverSelected;
00446                         }
00447                         else
00448                         {
00449                                 mImagep = mImageSelected;
00450                                 use_glow_effect = TRUE;
00451                         }
00452                 }
00453                 else
00454                 {
00455                         if (mImageHoverUnselected)
00456                         {
00457                                 mImagep = mImageHoverUnselected;
00458                         }
00459                         else
00460                         {
00461                                 mImagep = mImageUnselected;
00462                                 use_glow_effect = TRUE;
00463                         }
00464                 }
00465         }
00466         else if ( pressed )
00467         {
00468                 mImagep = mImageSelected;
00469         }
00470         else
00471         {
00472                 mImagep = mImageUnselected;
00473         }
00474 
00475         // Override if more data is available
00476         // HACK: Use gray checked state to mean either:
00477         //   enabled and tentative
00478         // or
00479         //   disabled but checked
00480         if (!mImageDisabledSelected.isNull() 
00481                 && 
00482                         ( (getEnabled() && getTentative()) 
00483                         || (!getEnabled() && pressed ) ) )
00484         {
00485                 mImagep = mImageDisabledSelected;
00486         }
00487         else if (!mImageDisabled.isNull() 
00488                 && !getEnabled() 
00489                 && !pressed)
00490         {
00491                 mImagep = mImageDisabled;
00492         }
00493 
00494         if (mNeedsHighlight && !mImagep)
00495         {
00496                 use_glow_effect = TRUE;
00497         }
00498 
00499         // Figure out appropriate color for the text
00500         LLColor4 label_color;
00501 
00502         // label changes when button state changes, not when pressed
00503         if ( getEnabled() )
00504         {
00505                 if ( mToggleState )
00506                 {
00507                         label_color = mSelectedLabelColor;
00508                 }
00509                 else
00510                 {
00511                         label_color = mUnselectedLabelColor;
00512                 }
00513         }
00514         else
00515         {
00516                 if ( mToggleState )
00517                 {
00518                         label_color = mDisabledSelectedLabelColor;
00519                 }
00520                 else
00521                 {
00522                         label_color = mDisabledLabelColor;
00523                 }
00524         }
00525 
00526         // Unselected label assignments
00527         LLWString label;
00528 
00529         if( mToggleState )
00530         {
00531                 if( getEnabled() || mDisabledSelectedLabel.empty() )
00532                 {
00533                         label = mSelectedLabel;
00534                 }
00535                 else
00536                 {
00537                         label = mDisabledSelectedLabel;
00538                 }
00539         }
00540         else
00541         {
00542                 if( getEnabled() || mDisabledLabel.empty() )
00543                 {
00544                         label = mUnselectedLabel;
00545                 }
00546                 else
00547                 {
00548                         label = mDisabledLabel;
00549                 }
00550         }
00551 
00552         // overlay with keyboard focus border
00553         if (hasFocus())
00554         {
00555                 F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
00556                 drawBorder(gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt)));
00557         }
00558         
00559         if (use_glow_effect)
00560         {
00561                 mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f));
00562         }
00563         else
00564         {
00565                 mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f));
00566         }
00567 
00568         // Draw button image, if available.
00569         // Otherwise draw basic rectangular button.
00570         if (mImagep.notNull())
00571         {
00572                 if ( mScaleImage)
00573                 {
00574                         mImagep->draw(getLocalRect(), getEnabled() ? mImageColor : mDisabledImageColor  );
00575                         if (mCurGlowStrength > 0.01f)
00576                         {
00577                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00578                                 mImagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
00579                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00580                         }
00581                 }
00582                 else
00583                 {
00584                         mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor );
00585                         if (mCurGlowStrength > 0.01f)
00586                         {
00587                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00588                                 mImagep->drawSolid(0, 0, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
00589                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00590                         }
00591                 }
00592         }
00593         else
00594         {
00595                 // no image
00596                 llwarns << "No image for button " << getName() << llendl;
00597                 // draw it in pink so we can find it
00598                 gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE);
00599         }
00600 
00601         // let overlay image and text play well together
00602         S32 text_left = mLeftHPad;
00603         S32 text_right = getRect().getWidth() - mRightHPad;
00604         S32 text_width = getRect().getWidth() - mLeftHPad - mRightHPad;
00605 
00606         // draw overlay image
00607         if (mImageOverlay.notNull())
00608         {
00609                 // get max width and height (discard level 0)
00610                 S32 overlay_width = mImageOverlay->getWidth();
00611                 S32 overlay_height = mImageOverlay->getHeight();
00612 
00613                 F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f);
00614                 overlay_width = llround((F32)overlay_width * scale_factor);
00615                 overlay_height = llround((F32)overlay_height * scale_factor);
00616 
00617                 S32 center_x = getLocalRect().getCenterX();
00618                 S32 center_y = getLocalRect().getCenterY();
00619 
00620                 //FUGLY HACK FOR "DEPRESSED" BUTTONS
00621                 if (pressed)
00622                 {
00623                         center_y--;
00624                         center_x++;
00625                 }
00626 
00627                 // fade out overlay images on disabled buttons
00628                 LLColor4 overlay_color = mImageOverlayColor;
00629                 if (!getEnabled())
00630                 {
00631                         overlay_color.mV[VALPHA] = 0.5f;
00632                 }
00633 
00634                 switch(mImageOverlayAlignment)
00635                 {
00636                 case LLFontGL::LEFT:
00637                         text_left += overlay_width + 1;
00638                         text_width -= overlay_width + 1;
00639                         mImageOverlay->draw(
00640                                 mLeftHPad, 
00641                                 center_y - (overlay_height / 2), 
00642                                 overlay_width, 
00643                                 overlay_height, 
00644                                 overlay_color);
00645                         break;
00646                 case LLFontGL::HCENTER:
00647                         mImageOverlay->draw(
00648                                 center_x - (overlay_width / 2), 
00649                                 center_y - (overlay_height / 2), 
00650                                 overlay_width, 
00651                                 overlay_height, 
00652                                 overlay_color);
00653                         break;
00654                 case LLFontGL::RIGHT:
00655                         text_right -= overlay_width + 1;                                
00656                         text_width -= overlay_width + 1;
00657                         mImageOverlay->draw(
00658                                 getRect().getWidth() - mRightHPad - overlay_width, 
00659                                 center_y - (overlay_height / 2), 
00660                                 overlay_width, 
00661                                 overlay_height, 
00662                                 overlay_color);
00663                         break;
00664                 default:
00665                         // draw nothing
00666                         break;
00667                 }
00668         }
00669 
00670         // Draw label
00671         if( !label.empty() )
00672         {
00673                 LLWString::trim(label);
00674 
00675                 S32 x;
00676                 switch( mHAlign )
00677                 {
00678                 case LLFontGL::RIGHT:
00679                         x = text_right;
00680                         break;
00681                 case LLFontGL::HCENTER:
00682                         x = getRect().getWidth() / 2;
00683                         break;
00684                 case LLFontGL::LEFT:
00685                 default:
00686                         x = text_left;
00687                         break;
00688                 }
00689 
00690                 S32 y_offset = 2 + (getRect().getHeight() - 20)/2;
00691         
00692                 if (pressed)
00693                 {
00694                         y_offset--;
00695                         x++;
00696                 }
00697 
00698                 mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), 
00699                         label_color,
00700                         mHAlign, LLFontGL::BOTTOM,
00701                         mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL,
00702                         U32_MAX, text_width,
00703                         NULL, FALSE, FALSE);
00704         }
00705 
00706         if (sDebugRects 
00707                 || (LLView::sEditingUI && this == LLView::sEditingUIView))
00708         {
00709                 drawDebugRect();
00710         }
00711 
00712         // reset hover status for next frame
00713         mNeedsHighlight = FALSE;
00714 }
00715 
00716 void LLButton::drawBorder(const LLColor4& color, S32 size)
00717 {
00718         if (mScaleImage)
00719         {
00720                 mImagep->drawBorder(getLocalRect(), color, size);
00721         }
00722         else
00723         {
00724                 mImagep->drawBorder(0, 0, color, size);
00725         }
00726 }
00727 
00728 void LLButton::setClickedCallback(void (*cb)(void*), void* userdata)
00729 {
00730         mClickedCallback = cb;
00731         if (userdata)
00732         {
00733                 mCallbackUserData = userdata;
00734         }
00735 }
00736 
00737 
00738 void LLButton::setToggleState(BOOL b)
00739 {
00740         if( b != mToggleState )
00741         {
00742                 setControlValue(b); // will fire LLControlVariable callbacks (if any)
00743                 mToggleState = b; // may or may not be redundant
00744         }
00745 }
00746 
00747 void LLButton::setFlashing( BOOL b )    
00748 { 
00749         if (b != mFlashing)
00750         {
00751                 mFlashing = b; 
00752                 mFlashingTimer.reset();
00753         }
00754 }
00755 
00756 
00757 BOOL LLButton::toggleState()                    
00758 { 
00759         setToggleState( !mToggleState ); 
00760         return mToggleState; 
00761 }
00762 
00763 void LLButton::setValue(const LLSD& value )
00764 {
00765         mToggleState = value.asBoolean();
00766 }
00767 
00768 LLSD LLButton::getValue() const
00769 {
00770         return mToggleState == TRUE;
00771 }
00772 
00773 void LLButton::setLabel( const LLStringExplicit& label )
00774 {
00775         setLabelUnselected(label);
00776         setLabelSelected(label);
00777 }
00778 
00779 //virtual
00780 BOOL LLButton::setLabelArg( const LLString& key, const LLStringExplicit& text )
00781 {
00782         mUnselectedLabel.setArg(key, text);
00783         mSelectedLabel.setArg(key, text);
00784         return TRUE;
00785 }
00786 
00787 void LLButton::setLabelUnselected( const LLStringExplicit& label )
00788 {
00789         mUnselectedLabel = label;
00790 }
00791 
00792 void LLButton::setLabelSelected( const LLStringExplicit& label )
00793 {
00794         mSelectedLabel = label;
00795 }
00796 
00797 void LLButton::setDisabledLabel( const LLStringExplicit& label )
00798 {
00799         mDisabledLabel = label;
00800 }
00801 
00802 void LLButton::setDisabledSelectedLabel( const LLStringExplicit& label )
00803 {
00804         mDisabledSelectedLabel = label;
00805 }
00806 
00807 void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
00808 {
00809         mImageUnselected = image;
00810 }
00811 
00812 void LLButton::setImages( const LLString &image_name, const LLString &selected_name )
00813 {
00814         setImageUnselected(image_name);
00815         setImageSelected(selected_name);
00816 
00817 }
00818 
00819 void LLButton::setImageSelected(LLPointer<LLUIImage> image)
00820 {
00821         mImageSelected = image;
00822 }
00823 
00824 void LLButton::setImageColor(const LLColor4& c)         
00825 { 
00826         mImageColor = c; 
00827 }
00828 
00829 void LLButton::setColor(const LLColor4& color)
00830 {
00831         setImageColor(color);
00832 }
00833 
00834 
00835 void LLButton::setImageDisabled(LLPointer<LLUIImage> image)
00836 {
00837         mImageDisabled = image;
00838         mDisabledImageColor = mImageColor;
00839         mDisabledImageColor.mV[VALPHA] *= 0.5f;
00840 }
00841 
00842 void LLButton::setImageDisabledSelected(LLPointer<LLUIImage> image)
00843 {
00844         mImageDisabledSelected = image;
00845         mDisabledImageColor = mImageColor;
00846         mDisabledImageColor.mV[VALPHA] *= 0.5f;
00847 }
00848 
00849 void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name, const LLColor4& c )
00850 {
00851         setImageDisabled(image_name);
00852         setImageDisabledSelected(selected_name);
00853         mDisabledImageColor = c;
00854 }
00855 
00856 void LLButton::setImageHoverSelected(LLPointer<LLUIImage> image)
00857 {
00858         mImageHoverSelected = image;
00859 }
00860 
00861 void LLButton::setDisabledImages( const LLString &image_name, const LLString &selected_name)
00862 {
00863         LLColor4 clr = mImageColor;
00864         clr.mV[VALPHA] *= .5f;
00865         setDisabledImages( image_name, selected_name, clr );
00866 }
00867 
00868 void LLButton::setImageHoverUnselected(LLPointer<LLUIImage> image)
00869 {
00870         mImageHoverUnselected = image;
00871 }
00872 
00873 void LLButton::setHoverImages( const LLString& image_name, const LLString& selected_name )
00874 {
00875         setImageHoverUnselected(image_name);
00876         setImageHoverSelected(selected_name);
00877 }
00878 
00879 void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment, const LLColor4& color)
00880 {
00881         if (image_name.empty())
00882         {
00883                 mImageOverlay = NULL;
00884         }
00885         else
00886         {
00887                 mImageOverlay = LLUI::getUIImage(image_name);
00888                 mImageOverlayAlignment = alignment;
00889                 mImageOverlayColor = color;
00890         }
00891 }
00892 
00893 
00894 void LLButton::onMouseCaptureLost()
00895 {
00896         mMouseDownTimer.stop();
00897         mMouseDownTimer.reset();
00898 }
00899 
00900 //-------------------------------------------------------------------------
00901 // Utilities
00902 //-------------------------------------------------------------------------
00903 S32 round_up(S32 grid, S32 value)
00904 {
00905         S32 mod = value % grid;
00906 
00907         if (mod > 0)
00908         {
00909                 // not even multiple
00910                 return value + (grid - mod);
00911         }
00912         else
00913         {
00914                 return value;
00915         }
00916 }
00917 
00918 void                    LLButton::setImageUnselected(const LLString &image_name)
00919 {       
00920         setImageUnselected(LLUI::getUIImage(image_name));
00921         mImageUnselectedName = image_name;
00922 }
00923 
00924 void                    LLButton::setImageSelected(const LLString &image_name)
00925 {       
00926         setImageSelected(LLUI::getUIImage(image_name));
00927         mImageSelectedName = image_name;
00928 }
00929 
00930 void                    LLButton::setImageHoverSelected(const LLString &image_name)
00931 {
00932         setImageHoverSelected(LLUI::getUIImage(image_name));
00933         mImageHoverSelectedName = image_name;
00934 }
00935 
00936 void                    LLButton::setImageHoverUnselected(const LLString &image_name)
00937 {
00938         setImageHoverUnselected(LLUI::getUIImage(image_name));
00939         mImageHoverUnselectedName = image_name;
00940 }
00941 
00942 void                    LLButton::setImageDisabled(const LLString &image_name)
00943 {
00944         setImageDisabled(LLUI::getUIImage(image_name));
00945         mImageDisabledName = image_name;
00946 }
00947 
00948 void                    LLButton::setImageDisabledSelected(const LLString &image_name)
00949 {
00950         setImageDisabledSelected(LLUI::getUIImage(image_name));
00951         mImageDisabledSelectedName = image_name;
00952 }
00953 
00954 void LLButton::addImageAttributeToXML(LLXMLNodePtr node, 
00955                                                                           const LLString& image_name,
00956                                                                           const LLUUID& image_id,
00957                                                                           const LLString& xml_tag_name) const
00958 {
00959         if( !image_name.empty() )
00960         {
00961                 node->createChild(xml_tag_name, TRUE)->setStringValue(image_name);
00962         }
00963         else if( image_id != LLUUID::null )
00964         {
00965                 node->createChild(xml_tag_name + "_id", TRUE)->setUUIDValue(image_id);
00966         }
00967 }
00968 
00969 // virtual
00970 LLXMLNodePtr LLButton::getXML(bool save_children) const
00971 {
00972         LLXMLNodePtr node = LLUICtrl::getXML();
00973 
00974         node->createChild("label", TRUE)->setStringValue(getLabelUnselected());
00975         node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected());
00976         node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont));
00977         node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign));
00978 
00979         addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,"image_unselected");
00980         addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,"image_selected");
00981         addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,"image_hover_selected");
00982         addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,"image_hover_unselected");
00983         addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,"image_disabled");
00984         addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,"image_disabled_selected");
00985 
00986         node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage);
00987 
00988         return node;
00989 }
00990 
00991 void clicked_help(void* data)
00992 {
00993         LLButton* self = (LLButton*)data;
00994         if (!self) return;
00995         
00996         if (!LLUI::sHtmlHelp)
00997         {
00998                 return;
00999         }
01000         
01001         LLUI::sHtmlHelp->show(self->getHelpURL());
01002 }
01003 
01004 // static
01005 LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
01006 {
01007         LLString name("button");
01008         node->getAttributeString("name", name);
01009 
01010         LLString label = name;
01011         node->getAttributeString("label", label);
01012 
01013         LLString label_selected = label;
01014         node->getAttributeString("label_selected", label_selected);
01015 
01016         LLFontGL* font = selectFont(node);
01017 
01018         LLString        image_unselected;
01019         if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
01020         
01021         LLString        image_selected;
01022         if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
01023         
01024         LLString        image_hover_selected;
01025         if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected);
01026         
01027         LLString        image_hover_unselected;
01028         if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected);
01029         
01030         LLString        image_disabled_selected;
01031         if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected);
01032         
01033         LLString        image_disabled;
01034         if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled);
01035 
01036         LLString        image_overlay;
01037         node->getAttributeString("image_overlay", image_overlay);
01038 
01039         LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER;
01040         LLString image_overlay_alignment_string;
01041         if (node->hasAttribute("image_overlay_alignment"))
01042         {
01043                 node->getAttributeString("image_overlay_alignment", image_overlay_alignment_string);
01044                 image_overlay_alignment = LLFontGL::hAlignFromName(image_overlay_alignment_string);
01045         }
01046 
01047 
01048         LLButton *button = new LLButton(name, 
01049                         LLRect(),
01050                         image_unselected,
01051                         image_selected,
01052                         "", 
01053                         NULL, 
01054                         parent,
01055                         font,
01056                         label,
01057                         label_selected);
01058 
01059         node->getAttributeS32("pad_right", button->mRightHPad);
01060         node->getAttributeS32("pad_left", button->mLeftHPad);
01061 
01062         BOOL is_toggle = button->getIsToggle();
01063         node->getAttributeBOOL("toggle", is_toggle);
01064         button->setIsToggle(is_toggle);
01065 
01066         if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected);
01067         
01068         if(image_hover_unselected != LLString::null) button->setImageHoverUnselected(image_hover_unselected);
01069         
01070         if(image_disabled_selected != LLString::null) button->setImageDisabledSelected(image_disabled_selected );
01071         
01072         if(image_disabled != LLString::null) button->setImageDisabled(image_disabled);
01073         
01074         if(image_overlay != LLString::null) button->setImageOverlay(image_overlay, image_overlay_alignment);
01075 
01076         if (node->hasAttribute("halign"))
01077         {
01078                 LLFontGL::HAlign halign = selectFontHAlign(node);
01079                 button->setHAlign(halign);
01080         }
01081 
01082         if (node->hasAttribute("scale_image"))
01083         {
01084                 BOOL    needsScale = FALSE;
01085                 node->getAttributeBOOL("scale_image",needsScale);
01086                 button->setScaleImage( needsScale );
01087         }
01088 
01089         if(label.empty())
01090         {
01091                 button->setLabelUnselected(node->getTextContents());
01092         }
01093         if (label_selected.empty())
01094         {
01095                 button->setLabelSelected(node->getTextContents());
01096         }
01097                 
01098         if (node->hasAttribute("help_url")) 
01099         {
01100                 LLString        help_url;
01101                 node->getAttributeString("help_url",help_url);
01102                 button->setHelpURLCallback(help_url);
01103         }
01104 
01105         button->initFromXML(node, parent);
01106         
01107         return button;
01108 }
01109 
01110 void LLButton::setHelpURLCallback(const LLString &help_url)
01111 {
01112         mHelpURL = help_url;
01113         setClickedCallback(clicked_help,this);
01114 }

Generated on Fri May 16 08:32:50 2008 for SecondLife by  doxygen 1.5.5