aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llmultisliderctrl.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/llui/llmultisliderctrl.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to 'linden/indra/llui/llmultisliderctrl.cpp')
-rw-r--r--linden/indra/llui/llmultisliderctrl.cpp634
1 files changed, 634 insertions, 0 deletions
diff --git a/linden/indra/llui/llmultisliderctrl.cpp b/linden/indra/llui/llmultisliderctrl.cpp
new file mode 100644
index 0000000..0d23dd7
--- /dev/null
+++ b/linden/indra/llui/llmultisliderctrl.cpp
@@ -0,0 +1,634 @@
1/**
2 * @file llmultisliderctrl.cpp
3 * @brief LLMultiSliderCtrl base class
4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 *
7 * Copyright (c) 2007-2008, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32#include "linden_common.h"
33
34#include "llmultisliderctrl.h"
35
36#include "audioengine.h"
37#include "sound_ids.h"
38
39#include "llmath.h"
40#include "llfontgl.h"
41#include "llgl.h"
42#include "llkeyboard.h"
43#include "lllineeditor.h"
44#include "llmultislider.h"
45#include "llstring.h"
46#include "lltextbox.h"
47#include "llui.h"
48#include "lluiconstants.h"
49#include "llcontrol.h"
50#include "llfocusmgr.h"
51#include "llresmgr.h"
52
53const U32 MAX_STRING_LENGTH = 10;
54
55
56LLMultiSliderCtrl::LLMultiSliderCtrl(const LLString& name, const LLRect& rect,
57 const LLString& label,
58 const LLFontGL* font,
59 S32 label_width,
60 S32 text_left,
61 BOOL show_text,
62 BOOL can_edit_text,
63 void (*commit_callback)(LLUICtrl*, void*),
64 void* callback_user_data,
65 F32 initial_value, F32 min_value, F32 max_value, F32 increment,
66 S32 max_sliders, BOOL allow_overlap,
67 BOOL draw_track,
68 BOOL use_triangle,
69 const LLString& control_which)
70 : LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data ),
71 mFont(font),
72 mShowText( show_text ),
73 mCanEditText( can_edit_text ),
74 mPrecision( 3 ),
75 mLabelBox( NULL ),
76 mLabelWidth( label_width ),
77
78 mEditor( NULL ),
79 mTextBox( NULL ),
80 mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
81 mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
82 mSliderMouseUpCallback( NULL ),
83 mSliderMouseDownCallback( NULL )
84{
85 S32 top = getRect().getHeight();
86 S32 bottom = 0;
87 S32 left = 0;
88
89 // Label
90 if( !label.empty() )
91 {
92 if (label_width == 0)
93 {
94 label_width = font->getWidth(label);
95 }
96 LLRect label_rect( left, top, label_width, bottom );
97 mLabelBox = new LLTextBox( "MultiSliderCtrl Label", label_rect, label.c_str(), font );
98 addChild(mLabelBox);
99 }
100
101 S32 slider_right = getRect().getWidth();
102 if( show_text )
103 {
104 slider_right = text_left - MULTI_SLIDERCTRL_SPACING;
105 }
106
107 S32 slider_left = label_width ? label_width + MULTI_SLIDERCTRL_SPACING : 0;
108 LLRect slider_rect( slider_left, top, slider_right, bottom );
109 mMultiSlider = new LLMultiSlider(
110 "multi_slider",
111 slider_rect,
112 LLMultiSliderCtrl::onSliderCommit, this,
113 initial_value, min_value, max_value, increment,
114 max_sliders, allow_overlap, draw_track,
115 use_triangle,
116 control_which );
117 addChild( mMultiSlider );
118 mCurValue = mMultiSlider->getCurSliderValue();
119
120 if( show_text )
121 {
122 LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
123 if( can_edit_text )
124 {
125 mEditor = new LLLineEditor( "MultiSliderCtrl Editor", text_rect,
126 "", font,
127 MAX_STRING_LENGTH,
128 &LLMultiSliderCtrl::onEditorCommit, NULL, NULL, this,
129 &LLLineEditor::prevalidateFloat );
130 mEditor->setFollowsLeft();
131 mEditor->setFollowsBottom();
132 mEditor->setFocusReceivedCallback( &LLMultiSliderCtrl::onEditorGainFocus );
133 mEditor->setIgnoreTab(TRUE);
134 // don't do this, as selecting the entire text is single clicking in some cases
135 // and double clicking in others
136 //mEditor->setSelectAllonFocusReceived(TRUE);
137 addChild(mEditor);
138 }
139 else
140 {
141 mTextBox = new LLTextBox( "MultiSliderCtrl Text", text_rect, "", font);
142 mTextBox->setFollowsLeft();
143 mTextBox->setFollowsBottom();
144 addChild(mTextBox);
145 }
146 }
147
148 updateText();
149}
150
151LLMultiSliderCtrl::~LLMultiSliderCtrl()
152{
153 // Children all cleaned up by default view destructor.
154}
155
156// static
157void LLMultiSliderCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata )
158{
159 LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
160 llassert( caller == self->mEditor );
161
162 self->onFocusReceived();
163}
164
165
166void LLMultiSliderCtrl::setValue(const LLSD& value)
167{
168 mMultiSlider->setValue(value);
169 mCurValue = mMultiSlider->getCurSliderValue();
170 updateText();
171}
172
173void LLMultiSliderCtrl::setSliderValue(const LLString& name, F32 v, BOOL from_event)
174{
175 mMultiSlider->setSliderValue(name, v, from_event );
176 mCurValue = mMultiSlider->getCurSliderValue();
177 updateText();
178}
179
180void LLMultiSliderCtrl::setCurSlider(const LLString& name)
181{
182 mMultiSlider->setCurSlider(name);
183 mCurValue = mMultiSlider->getCurSliderValue();
184}
185
186BOOL LLMultiSliderCtrl::setLabelArg( const LLString& key, const LLString& text )
187{
188 BOOL res = FALSE;
189 if (mLabelBox)
190 {
191 res = mLabelBox->setTextArg(key, text);
192 if (res && mLabelWidth == 0)
193 {
194 S32 label_width = mFont->getWidth(mLabelBox->getText());
195 LLRect rect = mLabelBox->getRect();
196 S32 prev_right = rect.mRight;
197 rect.mRight = rect.mLeft + label_width;
198 mLabelBox->setRect(rect);
199
200 S32 delta = rect.mRight - prev_right;
201 rect = mMultiSlider->getRect();
202 S32 left = rect.mLeft + delta;
203 left = llclamp(left, 0, rect.mRight-MULTI_SLIDERCTRL_SPACING);
204 rect.mLeft = left;
205 mMultiSlider->setRect(rect);
206 }
207 }
208 return res;
209}
210
211const LLString& LLMultiSliderCtrl::addSlider()
212{
213 const LLString& name = mMultiSlider->addSlider();
214
215 // if it returns null, pass it on
216 if(name == LLString::null) {
217 return LLString::null;
218 }
219
220 // otherwise, update stuff
221 mCurValue = mMultiSlider->getCurSliderValue();
222 updateText();
223 return name;
224}
225
226const LLString& LLMultiSliderCtrl::addSlider(F32 val)
227{
228 const LLString& name = mMultiSlider->addSlider(val);
229
230 // if it returns null, pass it on
231 if(name == LLString::null) {
232 return LLString::null;
233 }
234
235 // otherwise, update stuff
236 mCurValue = mMultiSlider->getCurSliderValue();
237 updateText();
238 return name;
239}
240
241void LLMultiSliderCtrl::deleteSlider(const LLString& name)
242{
243 mMultiSlider->deleteSlider(name);
244 mCurValue = mMultiSlider->getCurSliderValue();
245 updateText();
246}
247
248
249void LLMultiSliderCtrl::clear()
250{
251 setCurSliderValue(0.0f);
252 if( mEditor )
253 {
254 mEditor->setText(LLString(""));
255 }
256 if( mTextBox )
257 {
258 mTextBox->setText(LLString(""));
259 }
260
261 // get rid of sliders
262 mMultiSlider->clear();
263
264}
265
266BOOL LLMultiSliderCtrl::isMouseHeldDown()
267{
268 return gFocusMgr.getMouseCapture() == mMultiSlider;
269}
270
271void LLMultiSliderCtrl::updateText()
272{
273 if( mEditor || mTextBox )
274 {
275 LLLocale locale(LLLocale::USER_LOCALE);
276
277 // Don't display very small negative values as -0.000
278 F32 displayed_value = (F32)(floor(getCurSliderValue() * pow(10.0, (F64)mPrecision) + 0.5) / pow(10.0, (F64)mPrecision));
279
280 LLString format = llformat("%%.%df", mPrecision);
281 LLString text = llformat(format.c_str(), displayed_value);
282 if( mEditor )
283 {
284 mEditor->setText( text );
285 }
286 else
287 {
288 mTextBox->setText( text );
289 }
290 }
291}
292
293// static
294void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
295{
296 LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
297 llassert( caller == self->mEditor );
298
299 BOOL success = FALSE;
300 F32 val = self->mCurValue;
301 F32 saved_val = self->mCurValue;
302
303 LLString text = self->mEditor->getText();
304 if( LLLineEditor::postvalidateFloat( text ) )
305 {
306 LLLocale locale(LLLocale::USER_LOCALE);
307 val = (F32) atof( text.c_str() );
308 if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() )
309 {
310 if( self->mValidateCallback )
311 {
312 self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it.
313 if( self->mValidateCallback( self, self->mCallbackUserData ) )
314 {
315 success = TRUE;
316 }
317 }
318 else
319 {
320 self->setCurSliderValue( val );
321 success = TRUE;
322 }
323 }
324 }
325
326 if( success )
327 {
328 self->onCommit();
329 }
330 else
331 {
332 if( self->getCurSliderValue() != saved_val )
333 {
334 self->setCurSliderValue( saved_val );
335 }
336 self->reportInvalidData();
337 }
338 self->updateText();
339}
340
341// static
342void LLMultiSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
343{
344 LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
345 //llassert( caller == self->mSlider );
346
347 BOOL success = FALSE;
348 F32 saved_val = self->mCurValue;
349 F32 new_val = self->mMultiSlider->getCurSliderValue();
350
351 if( self->mValidateCallback )
352 {
353 self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it.
354 if( self->mValidateCallback( self, self->mCallbackUserData ) )
355 {
356 success = TRUE;
357 }
358 }
359 else
360 {
361 self->mCurValue = new_val;
362 success = TRUE;
363 }
364
365 if( success )
366 {
367 self->onCommit();
368 }
369 else
370 {
371 if( self->mCurValue != saved_val )
372 {
373 self->setCurSliderValue( saved_val );
374 }
375 self->reportInvalidData();
376 }
377 self->updateText();
378}
379
380void LLMultiSliderCtrl::setEnabled(BOOL b)
381{
382 LLUICtrl::setEnabled( b );
383
384 if( mLabelBox )
385 {
386 mLabelBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
387 }
388
389 mMultiSlider->setEnabled( b );
390
391 if( mEditor )
392 {
393 mEditor->setEnabled( b );
394 }
395
396 if( mTextBox )
397 {
398 mTextBox->setColor( b ? mTextEnabledColor : mTextDisabledColor );
399 }
400}
401
402
403void LLMultiSliderCtrl::setTentative(BOOL b)
404{
405 if( mEditor )
406 {
407 mEditor->setTentative(b);
408 }
409 LLUICtrl::setTentative(b);
410}
411
412
413void LLMultiSliderCtrl::onCommit()
414{
415 setTentative(FALSE);
416
417 if( mEditor )
418 {
419 mEditor->setTentative(FALSE);
420 }
421
422 LLUICtrl::onCommit();
423}
424
425
426void LLMultiSliderCtrl::setPrecision(S32 precision)
427{
428 if (precision < 0 || precision > 10)
429 {
430 llerrs << "LLMultiSliderCtrl::setPrecision - precision out of range" << llendl;
431 return;
432 }
433
434 mPrecision = precision;
435 updateText();
436}
437
438void LLMultiSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) )
439{
440 mSliderMouseDownCallback = slider_mousedown_callback;
441 mMultiSlider->setMouseDownCallback( LLMultiSliderCtrl::onSliderMouseDown );
442}
443
444// static
445void LLMultiSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata)
446{
447 LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
448 if( self->mSliderMouseDownCallback )
449 {
450 self->mSliderMouseDownCallback( self, self->mCallbackUserData );
451 }
452}
453
454
455void LLMultiSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) )
456{
457 mSliderMouseUpCallback = slider_mouseup_callback;
458 mMultiSlider->setMouseUpCallback( LLMultiSliderCtrl::onSliderMouseUp );
459}
460
461// static
462void LLMultiSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata)
463{
464 LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata;
465 if( self->mSliderMouseUpCallback )
466 {
467 self->mSliderMouseUpCallback( self, self->mCallbackUserData );
468 }
469}
470
471void LLMultiSliderCtrl::onTabInto()
472{
473 if( mEditor )
474 {
475 mEditor->onTabInto();
476 }
477}
478
479void LLMultiSliderCtrl::reportInvalidData()
480{
481 make_ui_sound("UISndBadKeystroke");
482}
483
484//virtual
485LLString LLMultiSliderCtrl::getControlName() const
486{
487 return mMultiSlider->getControlName();
488}
489
490// virtual
491void LLMultiSliderCtrl::setControlName(const LLString& control_name, LLView* context)
492{
493 mMultiSlider->setControlName(control_name, context);
494}
495
496// virtual
497LLXMLNodePtr LLMultiSliderCtrl::getXML(bool save_children) const
498{
499 LLXMLNodePtr node = LLUICtrl::getXML();
500
501 node->createChild("show_text", TRUE)->setBoolValue(mShowText);
502
503 node->createChild("can_edit_text", TRUE)->setBoolValue(mCanEditText);
504
505 node->createChild("decimal_digits", TRUE)->setIntValue(mPrecision);
506
507 if (mLabelBox)
508 {
509 node->createChild("label", TRUE)->setStringValue(mLabelBox->getText());
510 }
511
512 // TomY TODO: Do we really want to export the transient state of the slider?
513 node->createChild("value", TRUE)->setFloatValue(mCurValue);
514
515 if (mMultiSlider)
516 {
517 node->createChild("initial_val", TRUE)->setFloatValue(mMultiSlider->getInitialValue());
518 node->createChild("min_val", TRUE)->setFloatValue(mMultiSlider->getMinValue());
519 node->createChild("max_val", TRUE)->setFloatValue(mMultiSlider->getMaxValue());
520 node->createChild("increment", TRUE)->setFloatValue(mMultiSlider->getIncrement());
521 }
522 addColorXML(node, mTextEnabledColor, "text_enabled_color", "LabelTextColor");
523 addColorXML(node, mTextDisabledColor, "text_disabled_color", "LabelDisabledColor");
524
525 return node;
526}
527
528LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
529{
530 LLString name("multi_slider");
531 node->getAttributeString("name", name);
532
533 LLString label;
534 node->getAttributeString("label", label);
535
536 LLRect rect;
537 createRect(node, rect, parent, LLRect());
538
539 LLFontGL* font = LLView::selectFont(node);
540
541 // HACK: Font might not be specified.
542 if (!font)
543 {
544 font = LLFontGL::sSansSerifSmall;
545 }
546
547 S32 label_width = 0;
548 node->getAttributeS32("label_width", label_width);
549
550 BOOL show_text = TRUE;
551 node->getAttributeBOOL("show_text", show_text);
552
553 BOOL can_edit_text = FALSE;
554 node->getAttributeBOOL("can_edit_text", can_edit_text);
555
556 BOOL allow_overlap = FALSE;
557 node->getAttributeBOOL("allow_overlap", allow_overlap);
558
559 BOOL draw_track = TRUE;
560 node->getAttributeBOOL("draw_track", draw_track);
561
562 BOOL use_triangle = FALSE;
563 node->getAttributeBOOL("use_triangle", use_triangle);
564
565 F32 initial_value = 0.f;
566 node->getAttributeF32("initial_val", initial_value);
567
568 F32 min_value = 0.f;
569 node->getAttributeF32("min_val", min_value);
570
571 F32 max_value = 1.f;
572 node->getAttributeF32("max_val", max_value);
573
574 F32 increment = 0.1f;
575 node->getAttributeF32("increment", increment);
576
577 U32 precision = 3;
578 node->getAttributeU32("decimal_digits", precision);
579
580 S32 max_sliders = 1;
581 node->getAttributeS32("max_sliders", max_sliders);
582
583
584 S32 text_left = 0;
585 if (show_text)
586 {
587 // calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
588 if ( max_value )
589 text_left = font->getWidth("0") * ( static_cast < S32 > ( log10 ( max_value ) ) + precision + 1 );
590
591 if ( increment < 1.0f )
592 text_left += font->getWidth("."); // (mostly) take account of decimal point in value
593
594 if ( min_value < 0.0f || max_value < 0.0f )
595 text_left += font->getWidth("-"); // (mostly) take account of minus sign
596
597 // padding to make things look nicer
598 text_left += 8;
599 }
600
601 LLUICtrlCallback callback = NULL;
602
603 if (label.empty())
604 {
605 label.assign(node->getTextContents());
606 }
607
608 LLMultiSliderCtrl* slider = new LLMultiSliderCtrl(name,
609 rect,
610 label,
611 font,
612 label_width,
613 rect.getWidth() - text_left,
614 show_text,
615 can_edit_text,
616 callback,
617 NULL,
618 initial_value,
619 min_value,
620 max_value,
621 increment,
622 max_sliders,
623 allow_overlap,
624 draw_track,
625 use_triangle);
626
627 slider->setPrecision(precision);
628
629 slider->initFromXML(node, parent);
630
631 slider->updateText();
632
633 return slider;
634}