1 | // |
---|
2 | // "$Id$" |
---|
3 | // |
---|
4 | // Valuator widget for the Fast Light Tool Kit (FLTK). |
---|
5 | // |
---|
6 | // Copyright 1998-2005 by Bill Spitzak and others. |
---|
7 | // |
---|
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. |
---|
12 | // |
---|
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. |
---|
17 | // |
---|
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 |
---|
21 | // USA. |
---|
22 | // |
---|
23 | // Please report all bugs and problems on the following page: |
---|
24 | // |
---|
25 | // http://www.fltk.org/str.php |
---|
26 | // |
---|
27 | |
---|
28 | // Base class for sliders and all other one-value "knobs" |
---|
29 | |
---|
30 | #include <FL/Fl.H> |
---|
31 | #include <FL/Fl_Valuator.H> |
---|
32 | #include <FL/math.h> |
---|
33 | #include <stdio.h> |
---|
34 | #include "flstring.h" |
---|
35 | |
---|
36 | Fl_Valuator::Fl_Valuator(int X, int Y, int W, int H, const char* L) |
---|
37 | : Fl_Widget(X,Y,W,H,L) { |
---|
38 | align(FL_ALIGN_BOTTOM); |
---|
39 | when(FL_WHEN_CHANGED); |
---|
40 | value_ = 0; |
---|
41 | previous_value_ = 1; |
---|
42 | min = 0; |
---|
43 | max = 1; |
---|
44 | A = 0.0; |
---|
45 | B = 1; |
---|
46 | } |
---|
47 | |
---|
48 | const double epsilon = 4.66e-10; |
---|
49 | |
---|
50 | void Fl_Valuator::step(double s) { |
---|
51 | if (s < 0) s = -s; |
---|
52 | A = rint(s); |
---|
53 | B = 1; |
---|
54 | while (fabs(s-A/B) > epsilon && B<=(0x7fffffff/10)) {B *= 10; A = rint(s*B);} |
---|
55 | } |
---|
56 | |
---|
57 | void Fl_Valuator::precision(int p) { |
---|
58 | A = 1.0; |
---|
59 | for (B = 1; p--;) B *= 10; |
---|
60 | } |
---|
61 | |
---|
62 | void Fl_Valuator::value_damage() {damage(FL_DAMAGE_EXPOSE);} // by default do partial-redraw |
---|
63 | |
---|
64 | int Fl_Valuator::value(double v) { |
---|
65 | clear_changed(); |
---|
66 | if (v == value_) return 0; |
---|
67 | value_ = v; |
---|
68 | value_damage(); |
---|
69 | return 1; |
---|
70 | } |
---|
71 | |
---|
72 | double Fl_Valuator::softclamp(double v) { |
---|
73 | int which = (min<=max); |
---|
74 | double p = previous_value_; |
---|
75 | if ((v<min)==which && p!=min && (p<min)!=which) return min; |
---|
76 | else if ((v>max)==which && p!=max && (p>max)!=which) return max; |
---|
77 | else return v; |
---|
78 | } |
---|
79 | |
---|
80 | // inline void Fl_Valuator::handle_push() {previous_value_ = value_;} |
---|
81 | |
---|
82 | void Fl_Valuator::handle_drag(double v) { |
---|
83 | if (v != value_) { |
---|
84 | value_ = v; |
---|
85 | value_damage(); |
---|
86 | set_changed(); |
---|
87 | if (when() & FL_WHEN_CHANGED) do_callback(); |
---|
88 | } |
---|
89 | } |
---|
90 | |
---|
91 | void Fl_Valuator::handle_release() { |
---|
92 | if (when()&FL_WHEN_RELEASE) { |
---|
93 | // insure changed() is off even if no callback is done. It may have |
---|
94 | // been turned on by the drag, and then the slider returned to it's |
---|
95 | // initial position: |
---|
96 | clear_changed(); |
---|
97 | // now do the callback only if slider in new position or always is on: |
---|
98 | if (value_ != previous_value_ || when() & FL_WHEN_NOT_CHANGED) { |
---|
99 | do_callback(); |
---|
100 | } |
---|
101 | } |
---|
102 | } |
---|
103 | |
---|
104 | double Fl_Valuator::round(double v) { |
---|
105 | if (A) return rint(v*B/A)*A/B; |
---|
106 | else return v; |
---|
107 | } |
---|
108 | |
---|
109 | double Fl_Valuator::clamp(double v) { |
---|
110 | if ((v<min)==(min<=max)) return min; |
---|
111 | else if ((v>max)==(min<=max)) return max; |
---|
112 | else return v; |
---|
113 | } |
---|
114 | |
---|
115 | double Fl_Valuator::increment(double v, int n) { |
---|
116 | if (!A) return v+n*(max-min)/100; |
---|
117 | if (min > max) n = -n; |
---|
118 | return (rint(v*B/A)+n)*A/B; |
---|
119 | } |
---|
120 | |
---|
121 | int Fl_Valuator::format(char* buffer) { |
---|
122 | double v = value(); |
---|
123 | // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT |
---|
124 | if (!A || !B) return snprintf(buffer, 128, "%g", v); |
---|
125 | |
---|
126 | // Figure out how many digits are required to correctly format the |
---|
127 | // value. |
---|
128 | int i, c = 0; |
---|
129 | char temp[32]; |
---|
130 | // output a number with many digits after the decimal point. This |
---|
131 | // seems to be needed to get high precission |
---|
132 | snprintf(temp, sizeof(temp), "%.12f", A/B); |
---|
133 | // strip all trailing 0's |
---|
134 | for (i=strlen(temp)-1; i>0; i--) { |
---|
135 | if (temp[i]!='0') break; |
---|
136 | } |
---|
137 | // count digits until we find the decimal point (or comma or whatever |
---|
138 | // letter is set in the current locale) |
---|
139 | for (; i>0; i--, c++) { |
---|
140 | if (!isdigit(temp[i])) break; |
---|
141 | } |
---|
142 | |
---|
143 | // MRS: THIS IS A HACK - RECOMMEND ADDING BUFFER SIZE ARGUMENT |
---|
144 | return snprintf(buffer, 128, "%.*f", c, v); |
---|
145 | } |
---|
146 | |
---|
147 | // |
---|
148 | // End of "$Id$". |
---|
149 | // |
---|