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 static LLRegisterWidget<LLSlider> r1("slider_bar");
00045 static LLRegisterWidget<LLSlider> r2("volume_slider");
00046
00047
00048 LLSlider::LLSlider(
00049 const LLString& name,
00050 const LLRect& rect,
00051 void (*on_commit_callback)(LLUICtrl* ctrl, void* userdata),
00052 void* callback_userdata,
00053 F32 initial_value,
00054 F32 min_value,
00055 F32 max_value,
00056 F32 increment,
00057 BOOL volume,
00058 const LLString& control_name)
00059 :
00060 LLUICtrl( name, rect, TRUE, on_commit_callback, callback_userdata,
00061 FOLLOWS_LEFT | FOLLOWS_TOP),
00062 mValue( initial_value ),
00063 mInitialValue( initial_value ),
00064 mMinValue( min_value ),
00065 mMaxValue( max_value ),
00066 mIncrement( increment ),
00067 mVolumeSlider( volume ),
00068 mMouseOffset( 0 ),
00069 mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ),
00070 mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ),
00071 mThumbCenterColor( LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ),
00072 mMouseDownCallback( NULL ),
00073 mMouseUpCallback( NULL )
00074 {
00075 mThumbImage = LLUI::sImageProvider->getUIImage("icn_slide-thumb_dark.tga");
00076 mTrackImage = LLUI::sImageProvider->getUIImage("icn_slide-groove_dark.tga");
00077 mTrackHighlightImage = LLUI::sImageProvider->getUIImage("icn_slide-highlight.tga");
00078
00079
00080
00081
00082 setControlName(control_name, NULL);
00083 setValue(getValueF32());
00084
00085 updateThumbRect();
00086 mDragStartThumbRect = mThumbRect;
00087 }
00088
00089
00090 void LLSlider::setValue(F32 value, BOOL from_event)
00091 {
00092 value = llclamp( value, mMinValue, mMaxValue );
00093
00094
00095 value -= mMinValue;
00096 value += mIncrement/2.0001f;
00097 value -= fmod(value, mIncrement);
00098 value += mMinValue;
00099
00100 if (!from_event && mValue != value)
00101 {
00102 setControlValue(value);
00103 }
00104
00105 mValue = value;
00106 updateThumbRect();
00107 }
00108
00109 void LLSlider::updateThumbRect()
00110 {
00111 F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue);
00112
00113 S32 thumb_width = mThumbImage->getWidth();
00114 S32 thumb_height = mThumbImage->getHeight();
00115 S32 left_edge = (thumb_width / 2);
00116 S32 right_edge = getRect().getWidth() - (thumb_width / 2);
00117
00118 S32 x = left_edge + S32( t * (right_edge - left_edge) );
00119 mThumbRect.mLeft = x - (thumb_width / 2);
00120 mThumbRect.mRight = mThumbRect.mLeft + thumb_width;
00121 mThumbRect.mBottom = getLocalRect().getCenterY() - (thumb_height / 2);
00122 mThumbRect.mTop = mThumbRect.mBottom + thumb_height;
00123 }
00124
00125
00126 void LLSlider::setValueAndCommit(F32 value)
00127 {
00128 F32 old_value = mValue;
00129 setValue(value);
00130
00131 if (mValue != old_value)
00132 {
00133 onCommit();
00134 }
00135 }
00136
00137
00138 BOOL LLSlider::handleHover(S32 x, S32 y, MASK mask)
00139 {
00140 if( hasMouseCapture() )
00141 {
00142 S32 thumb_half_width = mThumbImage->getWidth()/2;
00143 S32 left_edge = thumb_half_width;
00144 S32 right_edge = getRect().getWidth() - (thumb_half_width);
00145
00146 x += mMouseOffset;
00147 x = llclamp( x, left_edge, right_edge );
00148
00149 F32 t = F32(x - left_edge) / (right_edge - left_edge);
00150 setValueAndCommit(t * (mMaxValue - mMinValue) + mMinValue );
00151
00152 getWindow()->setCursor(UI_CURSOR_ARROW);
00153 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
00154 }
00155 else
00156 {
00157 getWindow()->setCursor(UI_CURSOR_ARROW);
00158 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
00159 }
00160 return TRUE;
00161 }
00162
00163 BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask)
00164 {
00165 BOOL handled = FALSE;
00166
00167 if( hasMouseCapture() )
00168 {
00169 gFocusMgr.setMouseCapture( NULL );
00170
00171 if( mMouseUpCallback )
00172 {
00173 mMouseUpCallback( this, mCallbackUserData );
00174 }
00175 handled = TRUE;
00176 make_ui_sound("UISndClickRelease");
00177 }
00178 else
00179 {
00180 handled = TRUE;
00181 }
00182
00183 return handled;
00184 }
00185
00186 BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask)
00187 {
00188
00189 if (!getIsChrome())
00190 {
00191 setFocus(TRUE);
00192 }
00193 if( mMouseDownCallback )
00194 {
00195 mMouseDownCallback( this, mCallbackUserData );
00196 }
00197
00198 if (MASK_CONTROL & mask)
00199 {
00200 setValueAndCommit(mInitialValue);
00201 }
00202 else
00203 {
00204
00205 if (mThumbRect.pointInRect(x,y))
00206 {
00207 mMouseOffset = (mThumbRect.mLeft + mThumbImage->getWidth()/2) - x;
00208 }
00209 else
00210 {
00211 mMouseOffset = 0;
00212 }
00213
00214
00215
00216 gFocusMgr.setMouseCapture( this );
00217 mDragStartThumbRect = mThumbRect;
00218 }
00219 make_ui_sound("UISndClick");
00220
00221 return TRUE;
00222 }
00223
00224 BOOL LLSlider::handleKeyHere(KEY key, MASK mask)
00225 {
00226 BOOL handled = FALSE;
00227 switch(key)
00228 {
00229 case KEY_UP:
00230 case KEY_DOWN:
00231
00232 handled = TRUE;
00233 break;
00234 case KEY_LEFT:
00235 setValueAndCommit(getValueF32() - getIncrement());
00236 handled = TRUE;
00237 break;
00238 case KEY_RIGHT:
00239 setValueAndCommit(getValueF32() + getIncrement());
00240 handled = TRUE;
00241 break;
00242 default:
00243 break;
00244 }
00245 return handled;
00246 }
00247
00248 void LLSlider::draw()
00249 {
00250
00251 updateThumbRect();
00252
00253
00254
00255
00256 LLGLSNoTexture no_texture;
00257
00258 F32 opacity = getEnabled() ? 1.f : 0.3f;
00259 LLColor4 center_color = (mThumbCenterColor % opacity);
00260 LLColor4 track_color = (mTrackColor % opacity);
00261
00262
00263 LLRect track_rect(mThumbImage->getWidth() / 2,
00264 getLocalRect().getCenterY() + (mTrackImage->getHeight() / 2),
00265 getRect().getWidth() - mThumbImage->getWidth() / 2,
00266 getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
00267 LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
00268 mTrackImage->draw(track_rect);
00269 mTrackHighlightImage->draw(highlight_rect);
00270
00271
00272 if( hasMouseCapture() )
00273 {
00274
00275 mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor % 0.3f);
00276 }
00277 if (hasFocus())
00278 {
00279
00280 mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
00281 }
00282
00283 mThumbImage->draw(mThumbRect, hasMouseCapture() ? mThumbOutlineColor : center_color);
00284
00285 LLUICtrl::draw();
00286 }
00287
00288
00289 LLXMLNodePtr LLSlider::getXML(bool save_children) const
00290 {
00291 LLXMLNodePtr node = LLUICtrl::getXML();
00292
00293 node->createChild("initial_val", TRUE)->setFloatValue(getInitialValue());
00294 node->createChild("min_val", TRUE)->setFloatValue(getMinValue());
00295 node->createChild("max_val", TRUE)->setFloatValue(getMaxValue());
00296 node->createChild("increment", TRUE)->setFloatValue(getIncrement());
00297 node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider);
00298
00299 return node;
00300 }
00301
00302
00303
00304 LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory)
00305 {
00306 LLString name("slider_bar");
00307 node->getAttributeString("name", name);
00308
00309 LLRect rect;
00310 createRect(node, rect, parent, LLRect());
00311
00312 F32 initial_value = 0.f;
00313 node->getAttributeF32("initial_val", initial_value);
00314
00315 F32 min_value = 0.f;
00316 node->getAttributeF32("min_val", min_value);
00317
00318 F32 max_value = 1.f;
00319 node->getAttributeF32("max_val", max_value);
00320
00321 F32 increment = 0.1f;
00322 node->getAttributeF32("increment", increment);
00323
00324 BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
00325 node->getAttributeBOOL("volume", volume);
00326
00327 LLSlider* slider = new LLSlider(name,
00328 rect,
00329 NULL,
00330 NULL,
00331 initial_value,
00332 min_value,
00333 max_value,
00334 increment,
00335 volume);
00336
00337 slider->initFromXML(node, parent);
00338
00339 return slider;
00340 }