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