llmultisliderctrl.cpp

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

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