llslider.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llslider.h"
00035 #include "llui.h"
00036 
00037 #include "llgl.h"
00038 #include "llwindow.h"
00039 #include "llfocusmgr.h"
00040 #include "llkeyboard.h"                 // for the MASK constants
00041 #include "llcontrol.h"
00042 #include "llimagegl.h"
00043 
00044 const S32 THUMB_WIDTH = 8;
00045 const S32 TRACK_HEIGHT = 6;
00046 
00047 LLSlider::LLSlider( 
00048         const LLString& name,
00049         const LLRect& rect,
00050         void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
00051         void* callback_userdata,
00052         F32 initial_value,
00053         F32 min_value,
00054         F32 max_value,
00055         F32 increment,
00056         BOOL volume,
00057         const LLString& control_name)
00058         :
00059         LLUICtrl( name, rect, TRUE,     on_commit_callback, callback_userdata, 
00060                 FOLLOWS_LEFT | FOLLOWS_TOP),
00061         mValue( initial_value ),
00062         mInitialValue( initial_value ),
00063         mMinValue( min_value ),
00064         mMaxValue( max_value ),
00065         mIncrement( increment ),
00066         mVolumeSlider( volume ),
00067         mMouseOffset( 0 ),
00068         mDragStartThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
00069         mThumbRect( 0, mRect.getHeight(), THUMB_WIDTH, 0 ),
00070         mTrackColor(            LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ),
00071         mThumbOutlineColor(     LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ),
00072         mThumbCenterColor(      LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ),
00073         mDisabledThumbColor(LLUI::sColorsGroup->getColor( "SliderDisabledThumbColor" ) ),
00074         mMouseDownCallback( NULL ),
00075         mMouseUpCallback( NULL )
00076 {
00077         // properly handle setting the starting thumb rect
00078         // do it this way to handle both the operating-on-settings
00079         // and standalone ways of using this
00080         setControlName(control_name, NULL);
00081         setValue(getValueF32());
00082 }
00083 
00084 EWidgetType LLSlider::getWidgetType() const
00085 {
00086         return WIDGET_TYPE_SLIDER_BAR;
00087 }
00088 
00089 LLString LLSlider::getWidgetTag() const
00090 {
00091         return LL_SLIDER_TAG;
00092 }
00093 
00094 void LLSlider::setValue(F32 value, BOOL from_event)
00095 {
00096         value = llclamp( value, mMinValue, mMaxValue );
00097 
00098         // Round to nearest increment (bias towards rounding down)
00099         value -= mMinValue;
00100         value += mIncrement/2.0001f;
00101         value -= fmod(value, mIncrement);
00102         value += mMinValue;
00103 
00104         if (!from_event && mValue != value)
00105         {
00106                 setControlValue(value);
00107         }
00108 
00109         mValue = value;
00110 
00111         F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
00112 
00113         S32 left_edge = THUMB_WIDTH/2;
00114         S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2);
00115 
00116         S32 x = left_edge + S32( t * (right_edge - left_edge) );
00117         mThumbRect.mLeft = x - (THUMB_WIDTH/2);
00118         mThumbRect.mRight = x + (THUMB_WIDTH/2);
00119 }
00120 
00121 void LLSlider::setValueAndCommit(F32 value)
00122 {
00123         F32 old_value = mValue;
00124         setValue(value);
00125 
00126         if (mValue != old_value)
00127         {
00128                 onCommit();
00129         }
00130 }
00131 
00132 
00133 F32 LLSlider::getValueF32() const
00134 {
00135         return mValue;
00136 }
00137 
00138 BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
00139 {
00140         if( hasMouseCapture() )
00141         {
00142                 S32 left_edge = THUMB_WIDTH/2;
00143                 S32 right_edge = mRect.getWidth() - (THUMB_WIDTH/2);
00144 
00145                 x += mMouseOffset;
00146                 x = llclamp( x, left_edge, right_edge );
00147 
00148                 F32 t = F32(x - left_edge) / (right_edge - left_edge);
00149                 setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
00150 
00151                 getWindow()->setCursor(UI_CURSOR_ARROW);
00152                 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;               
00153         }
00154         else
00155         {
00156                 getWindow()->setCursor(UI_CURSOR_ARROW);
00157                 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;             
00158         }
00159         return TRUE;
00160 }
00161 
00162 BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask)
00163 {
00164         BOOL handled = FALSE;
00165 
00166         if( hasMouseCapture() )
00167         {
00168                 gFocusMgr.setMouseCapture( NULL );
00169 
00170                 if( mMouseUpCallback )
00171                 {
00172                         mMouseUpCallback( this, mCallbackUserData );
00173                 }
00174                 handled = TRUE;
00175                 make_ui_sound("UISndClickRelease");
00176         }
00177         else
00178         {
00179                 handled = TRUE;
00180         }
00181 
00182         return handled;
00183 }
00184 
00185 BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
00186 {
00187         // only do sticky-focus on non-chrome widgets
00188         if (!getIsChrome())
00189         {
00190                 setFocus(TRUE);
00191         }
00192         if( mMouseDownCallback )
00193         {
00194                 mMouseDownCallback( this, mCallbackUserData );
00195         }
00196 
00197         if (MASK_CONTROL & mask) // if CTRL is modifying
00198         {
00199                 setValueAndCommit(mInitialValue);
00200         }
00201         else
00202         {
00203                 // Find the offset of the actual mouse location from the center of the thumb.
00204                 if (mThumbRect.pointInRect(x,y))
00205                 {
00206                         mMouseOffset = (mThumbRect.mLeft + THUMB_WIDTH/2) - x;
00207                 }
00208                 else
00209                 {
00210                         mMouseOffset = 0;
00211                 }
00212 
00213                 // Start dragging the thumb
00214                 // No handler needed for focus lost since this class has no state that depends on it.
00215                 gFocusMgr.setMouseCapture( this );  
00216                 mDragStartThumbRect = mThumbRect;                               
00217         }
00218         make_ui_sound("UISndClick");
00219 
00220         return TRUE;
00221 }
00222 
00223 BOOL    LLSlider::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent)
00224 {
00225         BOOL handled = FALSE;
00226         if( getVisible() && mEnabled && !called_from_parent )
00227         {
00228                 switch(key)
00229                 {
00230                 case KEY_UP:
00231                 case KEY_DOWN:
00232                         // eat up and down keys to be consistent
00233                         handled = TRUE;
00234                         break;
00235                 case KEY_LEFT:
00236                         setValueAndCommit(getValueF32() - getIncrement());
00237                         handled = TRUE;
00238                         break;
00239                 case KEY_RIGHT:
00240                         setValueAndCommit(getValueF32() + getIncrement());
00241                         handled = TRUE;
00242                         break;
00243                 default:
00244                         break;
00245                 }
00246         }
00247         return handled;
00248 }
00249 
00250 void LLSlider::draw()
00251 {
00252         if( getVisible() )
00253         {
00254                 // Draw background and thumb.
00255 
00256                 // drawing solids requires texturing be disabled
00257                 LLGLSNoTexture no_texture;
00258 
00259                 LLRect rect(mDragStartThumbRect);
00260 
00261                 F32 opacity = mEnabled ? 1.f : 0.3f;
00262                 LLColor4 center_color = (mThumbCenterColor % opacity);
00263                 LLColor4 outline_color = (mThumbOutlineColor % opacity);
00264                 LLColor4 track_color = (mTrackColor % opacity);
00265 
00266                 LLImageGL* thumb_imagep = NULL;
00267                 
00268                 // Track
00269                 if (mVolumeSlider)
00270                 {
00271                         LLRect track(0, mRect.getHeight(), mRect.getWidth(), 0);
00272 
00273                         track.mBottom += 3;
00274                         track.mTop -= 1;
00275                         track.mRight -= 1;
00276 
00277                         gl_triangle_2d(track.mLeft, track.mBottom,
00278                                                    track.mRight, track.mBottom,
00279                                                    track.mRight, track.mTop,
00280                                                    center_color,
00281                                                    TRUE);
00282                         gl_triangle_2d(track.mLeft, track.mBottom,
00283                                                    track.mRight, track.mBottom,
00284                                                    track.mRight, track.mTop,
00285                                                    outline_color,
00286                                                    FALSE);
00287                 }
00288                 else
00289                 {
00290                         LLUUID thumb_image_id;
00291                         thumb_image_id.set(LLUI::sAssetsGroup->getString("rounded_square.tga"));
00292                         thumb_imagep = LLUI::sImageProvider->getUIImageByID(thumb_image_id);
00293 
00294                         S32 height_offset = (mRect.getHeight() - TRACK_HEIGHT) / 2;
00295                         LLRect track_rect(0, mRect.getHeight() - height_offset, mRect.getWidth(), height_offset );
00296 
00297                         track_rect.stretch(-1);
00298                         gl_draw_scaled_image_with_border(track_rect.mLeft, track_rect.mBottom, 16, 16, track_rect.getWidth(), track_rect.getHeight(),
00299                                                                                          thumb_imagep, track_color);
00300                 }
00301 
00302                 // Thumb
00303                 if (!thumb_imagep)
00304                 {
00305                         if (mVolumeSlider)
00306                         {
00307                                 if (hasMouseCapture())
00308                                 {
00309                                         LLRect rect(mDragStartThumbRect);
00310                                         gl_rect_2d( rect, outline_color );
00311                                         rect.stretch(-1);
00312                                         gl_rect_2d( rect, mThumbCenterColor % 0.3f );
00313 
00314                                         if (hasFocus())
00315                                         {
00316                                                 LLRect thumb_rect = mThumbRect;
00317                                                 thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
00318                                                 gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
00319                                         }
00320                                         gl_rect_2d( mThumbRect, mThumbOutlineColor );
00321                                 }
00322                                 else
00323                                 { 
00324                                         if (hasFocus())
00325                                         {
00326                                                 LLRect thumb_rect = mThumbRect;
00327                                                 thumb_rect.stretch(llround(lerp(1.f, 3.f, gFocusMgr.getFocusFlashAmt())));
00328                                                 gl_rect_2d(thumb_rect, gFocusMgr.getFocusColor());
00329                                         }
00330                                         LLRect rect(mThumbRect);
00331                                         gl_rect_2d(rect, outline_color);
00332                                         rect.stretch(-1);
00333                                         gl_rect_2d( rect, center_color);
00334                                 }
00335                         }
00336                         else
00337                         {
00338                                 gl_rect_2d(mThumbRect, mThumbCenterColor, TRUE);
00339                                 if (hasMouseCapture())
00340                                 {
00341                                         gl_rect_2d(mDragStartThumbRect, center_color, FALSE);
00342                                 }
00343                         }
00344                 }
00345                 else if( hasMouseCapture() )
00346                 {
00347                         gl_draw_scaled_image_with_border(mDragStartThumbRect.mLeft, mDragStartThumbRect.mBottom, 16, 16, mDragStartThumbRect.getWidth(), mDragStartThumbRect.getHeight(), 
00348                                                                                          thumb_imagep, mThumbCenterColor % 0.3f, TRUE);
00349 
00350                         if (hasFocus())
00351                         {
00352                                 F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
00353                                 LLRect highlight_rect = mThumbRect;
00354                                 highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
00355                                 gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
00356                                                                                                  thumb_imagep, gFocusMgr.getFocusColor());
00357                         }
00358 
00359                         gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(), 
00360                                                                                          thumb_imagep, mThumbOutlineColor, TRUE);
00361 
00362                 }
00363                 else
00364                 { 
00365                         if (hasFocus())
00366                         {
00367                                 F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
00368                                 LLRect highlight_rect = mThumbRect;
00369                                 highlight_rect.stretch(llround(lerp(1.f, 3.f, lerp_amt)));
00370                                 gl_draw_scaled_image_with_border(highlight_rect.mLeft, highlight_rect.mBottom, 16, 16, highlight_rect.getWidth(), highlight_rect.getHeight(),
00371                                                                                                  thumb_imagep, gFocusMgr.getFocusColor());
00372                         }
00373 
00374                         gl_draw_scaled_image_with_border(mThumbRect.mLeft, mThumbRect.mBottom, 16, 16, mThumbRect.getWidth(), mThumbRect.getHeight(), 
00375                                                                                          thumb_imagep, center_color, TRUE);
00376                 }
00377                 LLUICtrl::draw();
00378         }
00379 }
00380 
00381 // virtual
00382 LLXMLNodePtr LLSlider::getXML(bool save_children) const
00383 {
00384         LLXMLNodePtr node = LLUICtrl::getXML();
00385 
00386         node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue());
00387         node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
00388         node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
00389         node->createChild("increment", TRUE)->setFloatValue(getIncrement());
00390         node->createChild("volume", TRUE)->setBoolValue(getVolumeSlider());
00391 
00392         return node;
00393 }
00394 
00395 
00396 //static
00397 LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00398 {
00399         LLString name("slider_bar");
00400         node->getAttributeString("name", name);
00401 
00402         LLRect rect;
00403         createRect(node, rect, parent, LLRect());
00404 
00405         F32 initial_value = 0.f;
00406         node->getAttributeF32("initial_val", initial_value);
00407 
00408         F32 min_value = 0.f;
00409         node->getAttributeF32("min_val", min_value);
00410 
00411         F32 max_value = 1.f; 
00412         node->getAttributeF32("max_val", max_value);
00413 
00414         F32 increment = 0.1f;
00415         node->getAttributeF32("increment", increment);
00416 
00417         BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
00418         node->getAttributeBOOL("volume", volume);
00419 
00420         LLSlider* slider = new LLSlider(name,
00421                                                         rect,
00422                                                         NULL,
00423                                                         NULL,
00424                                                         initial_value,
00425                                                         min_value,
00426                                                         max_value,
00427                                                         increment,
00428                                                         volume);
00429 
00430         slider->initFromXML(node, parent);
00431 
00432         return slider;
00433 }

Generated on Thu Jul 1 06:09:11 2010 for Second Life Viewer by  doxygen 1.4.7