2 // "$Id: Fl_Valuator.cxx 7903 2010-11-28 21:06:39Z matt $"
4 // Valuator widget for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 // Base class for sliders and all other one-value "knobs"
32 #include <FL/Fl_Valuator.H>
37 Fl_Valuator::Fl_Valuator(int X
, int Y
, int W
, int H
, const char* L
)
39 Creates a new Fl_Valuator widget using the given position,
40 size, and label string. The default boxtype is FL_NO_BOX.
42 : Fl_Widget(X
,Y
,W
,H
,L
) {
43 align(FL_ALIGN_BOTTOM
);
44 when(FL_WHEN_CHANGED
);
53 const double epsilon
= 4.66e-10;
55 /** See double Fl_Valuator::step() const */
56 void Fl_Valuator::step(double s
) {
60 while (fabs(s
-A
/B
) > epsilon
&& B
<=(0x7fffffff/10)) {B
*= 10; A
= rint(s
*B
);}
63 /** Sets the step value to 1/10<SUP>digits</SUP>.*/
64 void Fl_Valuator::precision(int p
) {
66 for (B
= 1; p
--;) B
*= 10;
68 /** Asks for partial redraw */
69 void Fl_Valuator::value_damage() {damage(FL_DAMAGE_USER1
);} // by default do partial-redraw
72 Sets the current value. The new value is <I>not</I>
73 clamped or otherwise changed before storing it. Use
74 clamp() or round() to modify the value before
75 calling value(). The widget is redrawn if the new value
76 is different than the current one. The initial value is zero.
77 <P>changed() will return true if the user has moved the slider,
78 but it will be turned off by value(x) and just before doing a callback
79 (the callback can turn it back on if desired).
81 int Fl_Valuator::value(double v
) {
83 if (v
== value_
) return 0;
88 /** Clamps the value, but accepts v if the previous value is not already out of range */
89 double Fl_Valuator::softclamp(double v
) {
90 int which
= (min
<=max
);
91 double p
= previous_value_
;
92 if ((v
<min
)==which
&& p
!=min
&& (p
<min
)!=which
) return min
;
93 else if ((v
>max
)==which
&& p
!=max
&& (p
>max
)!=which
) return max
;
97 // inline void Fl_Valuator::handle_push() {previous_value_ = value_;}
98 /** Called during a drag operation, after an FL_WHEN_CHANGED event is received and before the callback. */
99 void Fl_Valuator::handle_drag(double v
) {
104 if (when() & FL_WHEN_CHANGED
) do_callback();
107 /** Called after an FL_WHEN_RELEASE event is received and before the callback. */
108 void Fl_Valuator::handle_release() {
109 if (when()&FL_WHEN_RELEASE
) {
110 // insure changed() is off even if no callback is done. It may have
111 // been turned on by the drag, and then the slider returned to it's
114 // now do the callback only if slider in new position or always is on:
115 if (value_
!= previous_value_
|| when() & FL_WHEN_NOT_CHANGED
) {
122 Round the passed value to the nearest step increment. Does
123 nothing if step is zero.
125 double Fl_Valuator::round(double v
) {
126 if (A
) return rint(v
*B
/A
)*A
/B
;
130 /** Clamps the passed value to the valuator range.*/
131 double Fl_Valuator::clamp(double v
) {
132 if ((v
<min
)==(min
<=max
)) return min
;
133 else if ((v
>max
)==(min
<=max
)) return max
;
138 Adds n times the step value to the passed value. If
139 step was set to zero it uses fabs(maximum() - minimum()) /
142 double Fl_Valuator::increment(double v
, int n
) {
143 if (!A
) return v
+n
*(max
-min
)/100;
144 if (min
> max
) n
= -n
;
145 return (rint(v
*B
/A
)+n
)*A
/B
;
149 Uses internal rules to format the fields numerical value into
150 the character array pointed to by the passed parameter.</P>
152 <P>The actual format used depends on the current step value. If
153 the step value has been set to zero then a %g format is used.
154 If the step value is non-zero, then a %.*f format is used,
155 where the precision is calculated to show sufficient digits
156 for the current step value. An integer step value, such as 1
157 or 1.0, gives a precision of 0, so the formatted value will
158 appear as an integer.</P>
160 <P>This method is used by the Fl_Value_... group of widgets to
161 format the current value into a text string.
162 The return value is the length of the formatted text.
163 The formatted value is written into in <i>buffer</i>.
164 <i>buffer</i> should have space for at least 128 bytes.</P>
166 <P>You may override this function to create your own text formatting.
168 int Fl_Valuator::format(char* buffer
) {
170 // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT
171 if (!A
|| !B
) return snprintf(buffer
, 128, "%g", v
);
173 // Figure out how many digits are required to correctly format the
177 // output a number with many digits after the decimal point. This
178 // seems to be needed to get high precission
179 snprintf(temp
, sizeof(temp
), "%.12f", A
/B
);
180 // strip all trailing 0's
181 for (i
=strlen(temp
)-1; i
>0; i
--) {
182 if (temp
[i
]!='0') break;
184 // count digits until we find the decimal point (or comma or whatever
185 // letter is set in the current locale)
186 for (; i
>0; i
--, c
++) {
187 if (!isdigit(temp
[i
])) break;
190 // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT
191 return snprintf(buffer
, 128, "%.*f", c
, v
);
195 // End of "$Id: Fl_Valuator.cxx 7903 2010-11-28 21:06:39Z matt $".