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"
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
00078
00079
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
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
00188 if (!getIsChrome())
00189 {
00190 setFocus(TRUE);
00191 }
00192 if( mMouseDownCallback )
00193 {
00194 mMouseDownCallback( this, mCallbackUserData );
00195 }
00196
00197 if (MASK_CONTROL & mask)
00198 {
00199 setValueAndCommit(mInitialValue);
00200 }
00201 else
00202 {
00203
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
00214
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
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
00255
00256
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
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
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
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
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 }