llsliderctrl.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llsliderctrl.h"
00035 
00036 #include "audioengine.h"
00037 #include "sound_ids.h"
00038 
00039 #include "llmath.h"
00040 #include "llfontgl.h"
00041 #include "llgl.h"
00042 #include "llkeyboard.h"
00043 #include "lllineeditor.h"
00044 #include "llslider.h"
00045 #include "llstring.h"
00046 #include "lltextbox.h"
00047 #include "llui.h"
00048 #include "lluiconstants.h"
00049 #include "llcontrol.h"
00050 #include "llfocusmgr.h"
00051 #include "llresmgr.h"
00052 
00053 const U32 MAX_STRING_LENGTH = 10;
00054 
00055  
00056 LLSliderCtrl::LLSliderCtrl(const LLString& name, const LLRect& rect, 
00057                                                    const LLString& label,
00058                                                    const LLFontGL* font,
00059                                                    S32 label_width,
00060                                                    S32 text_left,
00061                                                    BOOL show_text,
00062                                                    BOOL can_edit_text,
00063                                                    BOOL volume,
00064                                                    void (*commit_callback)(LLUICtrl*, void*),
00065                                                    void* callback_user_data,
00066                                                    F32 initial_value, F32 min_value, F32 max_value, F32 increment,
00067                                                    const LLString& control_which)
00068         : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data ),
00069           mFont(font),
00070           mShowText( show_text ),
00071           mCanEditText( can_edit_text ),
00072           mVolumeSlider( volume ),
00073           mPrecision( 3 ),
00074           mLabelBox( NULL ),
00075           mLabelWidth( label_width ),
00076           mValue( initial_value ),
00077           mEditor( NULL ),
00078           mTextBox( NULL ),
00079           mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
00080           mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
00081           mSliderMouseUpCallback( NULL ),
00082           mSliderMouseDownCallback( NULL )
00083 {
00084         S32 top = mRect.getHeight();
00085         S32 bottom = 0;
00086         S32 left = 0;
00087 
00088         // Label
00089         if( !label.empty() )
00090         {
00091                 if (label_width == 0)
00092                 {
00093                         label_width = font->getWidth(label);
00094                 }
00095                 LLRect label_rect( left, top, label_width, bottom );
00096                 mLabelBox = new LLTextBox( "SliderCtrl Label", label_rect, label.c_str(), font );
00097                 addChild(mLabelBox);
00098         }
00099 
00100         S32 slider_right = mRect.getWidth();
00101         if( show_text )
00102         {
00103                 slider_right = text_left - SLIDERCTRL_SPACING;
00104         }
00105 
00106         S32 slider_left = label_width ? label_width + SLIDERCTRL_SPACING : 0;
00107         LLRect slider_rect( slider_left, top, slider_right, bottom );
00108         mSlider = new LLSlider( 
00109                 "slider",
00110                 slider_rect, 
00111                 LLSliderCtrl::onSliderCommit, this, 
00112                 initial_value, min_value, max_value, increment, volume,
00113                 control_which );
00114         addChild( mSlider );
00115         
00116         if( show_text )
00117         {
00118                 LLRect text_rect( text_left, top, mRect.getWidth(), bottom );
00119                 if( can_edit_text )
00120                 {
00121                         mEditor = new LLLineEditor( "SliderCtrl Editor", text_rect,
00122                                 "", font,
00123                                 MAX_STRING_LENGTH,
00124                                 &LLSliderCtrl::onEditorCommit, NULL, NULL, this,
00125                                 &LLLineEditor::prevalidateFloat );
00126                         mEditor->setFollowsLeft();
00127                         mEditor->setFollowsBottom();
00128                         mEditor->setFocusReceivedCallback( &LLSliderCtrl::onEditorGainFocus );
00129                         mEditor->setIgnoreTab(TRUE);
00130                         // don't do this, as selecting the entire text is single clicking in some cases
00131                         // and double clicking in others
00132                         //mEditor->setSelectAllonFocusReceived(TRUE);
00133                         addChild(mEditor);
00134                 }
00135                 else
00136                 {
00137                         mTextBox = new LLTextBox( "SliderCtrl Text", text_rect, "",     font);
00138                         mTextBox->setFollowsLeft();
00139                         mTextBox->setFollowsBottom();
00140                         addChild(mTextBox);
00141                 }
00142         }
00143 
00144         updateText();
00145 }
00146 
00147 LLSliderCtrl::~LLSliderCtrl()
00148 {
00149         // Children all cleaned up by default view destructor.
00150 }
00151 
00152 // static
00153 void LLSliderCtrl::onEditorGainFocus( LLUICtrl* caller, void *userdata )
00154 {
00155         LLSliderCtrl* self = (LLSliderCtrl*) userdata;
00156         llassert( caller == self->mEditor );
00157 
00158         self->onFocusReceived();
00159 }
00160 
00161 F32 LLSliderCtrl::getValueF32() const
00162 {
00163         return mSlider->getValueF32();
00164 }
00165 
00166 void LLSliderCtrl::setValue(F32 v, BOOL from_event)
00167 {
00168         mSlider->setValue( v, from_event );
00169         mValue = mSlider->getValueF32();
00170         updateText();
00171 }
00172 
00173 BOOL LLSliderCtrl::setLabelArg( const LLString& key, const LLStringExplicit& text )
00174 {
00175         BOOL res = FALSE;
00176         if (mLabelBox)
00177         {
00178                 res = mLabelBox->setTextArg(key, text);
00179                 if (res && mLabelWidth == 0)
00180                 {
00181                         S32 label_width = mFont->getWidth(mLabelBox->getText());
00182                         LLRect rect = mLabelBox->getRect();
00183                         S32 prev_right = rect.mRight;
00184                         rect.mRight = rect.mLeft + label_width;
00185                         mLabelBox->setRect(rect);
00186                                 
00187                         S32 delta = rect.mRight - prev_right;
00188                         rect = mSlider->getRect();
00189                         S32 left = rect.mLeft + delta;
00190                         left = llclamp(left, 0, rect.mRight-SLIDERCTRL_SPACING);
00191                         rect.mLeft = left;
00192                         mSlider->setRect(rect);
00193                 }
00194         }
00195         return res;
00196 }
00197 
00198 void LLSliderCtrl::clear()
00199 {
00200         setValue(0.0f);
00201         if( mEditor )
00202         {
00203                 mEditor->setText( LLString::null );
00204         }
00205         if( mTextBox )
00206         {
00207                 mTextBox->setText( LLString::null );
00208         }
00209 
00210 }
00211 
00212 BOOL LLSliderCtrl::isMouseHeldDown()
00213 {
00214         return mSlider->hasMouseCapture();
00215 }
00216 
00217 void LLSliderCtrl::updateText()
00218 {
00219         if( mEditor || mTextBox )
00220         {
00221                 LLLocale locale(LLLocale::USER_LOCALE);
00222 
00223                 // Don't display very small negative values as -0.000
00224                 F32 displayed_value = (F32)(floor(getValueF32() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision));
00225 
00226                 LLString format = llformat("%%.%df", mPrecision);
00227                 LLString text = llformat(format.c_str(), displayed_value);
00228                 if( mEditor )
00229                 {
00230                         mEditor->setText( text );
00231                 }
00232                 else
00233                 {
00234                         mTextBox->setText( text );
00235                 }
00236         }
00237 }
00238 
00239 // static
00240 void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
00241 {
00242         LLSliderCtrl* self = (LLSliderCtrl*) userdata;
00243         llassert( caller == self->mEditor );
00244 
00245         BOOL success = FALSE;
00246         F32 val = self->mValue;
00247         F32 saved_val = self->mValue;
00248 
00249         LLString text = self->mEditor->getText();
00250         if( LLLineEditor::postvalidateFloat( text ) )
00251         {
00252                 LLLocale locale(LLLocale::USER_LOCALE);
00253                 val = (F32) atof( text.c_str() );
00254                 if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
00255                 {
00256                         if( self->mValidateCallback )
00257                         {
00258                                 self->setValue( val );  // set the value temporarily so that the callback can retrieve it.
00259                                 if( self->mValidateCallback( self, self->mCallbackUserData ) )
00260                                 {
00261                                         success = TRUE;
00262                                 }
00263                         }
00264                         else
00265                         {
00266                                 self->setValue( val );
00267                                 success = TRUE;
00268                         }
00269                 }
00270         }
00271 
00272         if( success )
00273         {
00274                 self->onCommit();
00275         }
00276         else
00277         {
00278                 if( self->getValueF32() != saved_val )
00279                 {
00280                         self->setValue( saved_val );
00281                 }
00282                 self->reportInvalidData();              
00283         }
00284         self->updateText();
00285 }
00286 
00287 // static
00288 void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
00289 {
00290         LLSliderCtrl* self = (LLSliderCtrl*) userdata;
00291         llassert( caller == self->mSlider );
00292 
00293         BOOL success = FALSE;
00294         F32 saved_val = self->mValue;
00295         F32 new_val = self->mSlider->getValueF32();
00296 
00297         if( self->mValidateCallback )
00298         {
00299                 self->mValue = new_val;  // set the value temporarily so that the callback can retrieve it.
00300                 if( self->mValidateCallback( self, self->mCallbackUserData ) )
00301                 {
00302                         success = TRUE;
00303                 }
00304         }
00305         else
00306         {
00307                 self->mValue = new_val;
00308                 success = TRUE;
00309         }
00310 
00311         if( success )
00312         {
00313                 self->onCommit();
00314         }
00315         else
00316         {
00317                 if( self->mValue != saved_val )
00318                 {
00319                         self->setValue( saved_val );
00320                 }
00321                 self->reportInvalidData();              
00322         }
00323         self->updateText();
00324 }
00325 
00326 void LLSliderCtrl::setEnabled(BOOL b)
00327 {
00328         LLView::setEnabled( b );
00329 
00330         if( mLabelBox )
00331         {
00332                 mLabelBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
00333         }
00334 
00335         mSlider->setEnabled( b );
00336 
00337         if( mEditor )
00338         {
00339                 mEditor->setEnabled( b );
00340         }
00341 
00342         if( mTextBox )
00343         {
00344                 mTextBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
00345         }
00346 }
00347 
00348 
00349 void LLSliderCtrl::setTentative(BOOL b)
00350 {
00351         if( mEditor )
00352         {
00353                 mEditor->setTentative(b);
00354         }
00355         LLUICtrl::setTentative(b);
00356 }
00357 
00358 
00359 void LLSliderCtrl::onCommit()
00360 {
00361         setTentative(FALSE);
00362 
00363         if( mEditor )
00364         {
00365                 mEditor->setTentative(FALSE);
00366         }
00367 
00368         LLUICtrl::onCommit();
00369 }
00370 
00371 
00372 void LLSliderCtrl::setPrecision(S32 precision)
00373 {
00374         if (precision < 0 || precision > 10)
00375         {
00376                 llerrs << "LLSliderCtrl::setPrecision - precision out of range" << llendl;
00377                 return;
00378         }
00379 
00380         mPrecision = precision;
00381         updateText();
00382 }
00383 
00384 void LLSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) )
00385 {
00386         mSliderMouseDownCallback = slider_mousedown_callback;
00387         mSlider->setMouseDownCallback( LLSliderCtrl::onSliderMouseDown );
00388 }
00389 
00390 // static
00391 void LLSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata)
00392 {
00393         LLSliderCtrl* self = (LLSliderCtrl*) userdata;
00394         if( self->mSliderMouseDownCallback )
00395         {
00396                 self->mSliderMouseDownCallback( self, self->mCallbackUserData );
00397         }
00398 }
00399 
00400 
00401 void LLSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) )
00402 {
00403         mSliderMouseUpCallback = slider_mouseup_callback;
00404         mSlider->setMouseUpCallback( LLSliderCtrl::onSliderMouseUp );
00405 }
00406 
00407 // static
00408 void LLSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata)
00409 {
00410         LLSliderCtrl* self = (LLSliderCtrl*) userdata;
00411         if( self->mSliderMouseUpCallback )
00412         {
00413                 self->mSliderMouseUpCallback( self, self->mCallbackUserData );
00414         }
00415 }
00416 
00417 void LLSliderCtrl::onTabInto()
00418 {
00419         if( mEditor )
00420         {
00421                 mEditor->onTabInto(); 
00422         }
00423 }
00424 
00425 void LLSliderCtrl::reportInvalidData()
00426 {
00427         make_ui_sound("UISndBadKeystroke");
00428 }
00429 
00430 //virtual
00431 LLString LLSliderCtrl::getControlName() const
00432 {
00433         return mSlider->getControlName();
00434 }
00435 
00436 // virtual
00437 void LLSliderCtrl::setControlName(const LLString& control_name, LLView* context)
00438 {
00439         mSlider->setControlName(control_name, context);
00440 }
00441 
00442 // virtual
00443 LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const
00444 {
00445         LLXMLNodePtr node = LLUICtrl::getXML();
00446 
00447         node->createChild("show_text", TRUE)->setBoolValue(mShowText);
00448 
00449         node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
00450 
00451         node->createChild("volume", TRUE)->setBoolValue(mVolumeSlider);
00452         
00453         node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
00454 
00455         if (mLabelBox)
00456         {
00457                 node->createChild("label", TRUE)->setStringValue(mLabelBox->getText());
00458         }
00459 
00460         // TomY TODO: Do we really want to export the transient state of the slider?
00461         node->createChild("value", TRUE)->setFloatValue(mValue);
00462 
00463         if (mSlider)
00464         {
00465                 node->createChild("initial_val", TRUE)->setFloatValue(mSlider->getInitialValue());
00466                 node->createChild("min_val", TRUE)->setFloatValue(mSlider->getMinValue());
00467                 node->createChild("max_val", TRUE)->setFloatValue(mSlider->getMaxValue());
00468                 node->createChild("increment", TRUE)->setFloatValue(mSlider->getIncrement());
00469         }
00470         addColorXML(node, mTextEnabledColor, "text_enabled_color", "LabelTextColor");
00471         addColorXML(node, mTextDisabledColor, "text_disabled_color", "LabelDisabledColor");
00472 
00473         return node;
00474 }
00475 
00476 LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00477 {
00478         LLString name("slider");
00479         node->getAttributeString("name", name);
00480 
00481         LLString label;
00482         node->getAttributeString("label", label);
00483 
00484         LLRect rect;
00485         createRect(node, rect, parent, LLRect());
00486 
00487         LLFontGL* font = LLView::selectFont(node);
00488 
00489         // HACK: Font might not be specified.
00490         if (!font)
00491         {
00492                 font = LLFontGL::sSansSerifSmall;
00493         }
00494 
00495         S32 label_width = 0;
00496         node->getAttributeS32("label_width", label_width);
00497 
00498         BOOL show_text = TRUE;
00499         node->getAttributeBOOL("show_text", show_text);
00500 
00501         BOOL can_edit_text = FALSE;
00502         node->getAttributeBOOL("can_edit_text", can_edit_text);
00503 
00504         BOOL volume = FALSE;
00505         node->getAttributeBOOL("volume", volume);
00506 
00507         F32 initial_value = 0.f;
00508         node->getAttributeF32("initial_val", initial_value);
00509 
00510         F32 min_value = 0.f;
00511         node->getAttributeF32("min_val", min_value);
00512 
00513         F32 max_value = 1.f; 
00514         node->getAttributeF32("max_val", max_value);
00515 
00516         F32 increment = 0.1f;
00517         node->getAttributeF32("increment", increment);
00518 
00519         U32 precision = 3;
00520         node->getAttributeU32("decimal_digits", precision);
00521 
00522         S32 text_left = 0;
00523         if (show_text)
00524         {
00525                 // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
00526                 if ( max_value )
00527                         text_left = font->getWidth("0") * ( static_cast < S32 > ( log10  ( max_value ) ) + precision + 1 );
00528 
00529                 if ( increment < 1.0f )
00530                         text_left += font->getWidth(".");       // (mostly) take account of decimal point in value
00531 
00532                 if ( min_value < 0.0f || max_value < 0.0f )
00533                         text_left += font->getWidth("-");       // (mostly) take account of minus sign 
00534 
00535                 // padding to make things look nicer
00536                 text_left += 8;
00537         }
00538 
00539         LLUICtrlCallback callback = NULL;
00540 
00541         if (label.empty())
00542         {
00543                 label.assign(node->getTextContents());
00544         }
00545 
00546         LLSliderCtrl* slider = new LLSliderCtrl(name,
00547                                                         rect,
00548                                                         label,
00549                                                         font,
00550                                                         label_width,
00551                                                         rect.getWidth() - text_left,
00552                                                         show_text,
00553                                                         can_edit_text,
00554                                                         volume,
00555                                                         callback,
00556                                                         NULL,
00557                                                         initial_value, 
00558                                                         min_value, 
00559                                                         max_value, 
00560                                                         increment);
00561 
00562         slider->setPrecision(precision);
00563 
00564         slider->initFromXML(node, parent);
00565 
00566         slider->updateText();
00567         
00568         return slider;
00569 }

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