ntk-chtheme: Add new color scheme. Save/restore selection color.
[ntk.git] / FL / Fl_Spinner.H
blob5d141bd31b705e0ca455558f182e7178d1485add
1 //
2 // "$Id: Fl_Spinner.H 8339 2011-01-30 12:50:19Z ianmacarthur $"
3 //
4 // Spinner widget for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 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.
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
21 // USA.
23 // Please report all bugs and problems on the following page:
25 //     http://www.fltk.org/str.php
28 /* \file
29    Fl_Spinner widget . */
31 #ifndef Fl_Spinner_H
32 #  define Fl_Spinner_H
35 // Include necessary headers...
38 #  include <FL/Enumerations.H>
39 #  include <FL/Fl_Group.H>
40 #  include <FL/Fl_Input.H>
41 #  include <FL/Fl_Repeat_Button.H>
42 #  include <stdio.h>
43 #  include <stdlib.h>
46 /**
47   This widget is a combination of the input
48   widget and repeat buttons. The user can either type into the
49   input area or use the buttons to change the value.
51 class FL_EXPORT Fl_Spinner : public Fl_Group {
52   
53   double        value_;                 // Current value
54   double        minimum_;               // Minimum value
55   double        maximum_;               // Maximum value
56   double        step_;                  // Amount to add/subtract for up/down
57   const char    *format_;               // Format string
59   Fl_Input      input_;                 // Input field for the value
60   Fl_Repeat_Button
61                 up_button_,             // Up button
62                 down_button_;           // Down button
65   static void   sb_cb(Fl_Widget *w, Fl_Spinner *sb) {
66                   double v;             // New value
68                   if (w == &(sb->input_)) {
69                     // Something changed in the input field...
70                     v = atof(sb->input_.value());
72                     if (v < sb->minimum_) {
73                       sb->value_ = sb->minimum_;
74                       sb->update();
75                     } else if (v > sb->maximum_) {
76                       sb->value_ = sb->maximum_;
77                       sb->update();
78                     } else sb->value_ = v;
79                   } else if (w == &(sb->up_button_)) {
80                     // Up button pressed...
81                     v = sb->value_ + sb->step_;
83                     if (v > sb->maximum_) sb->value_ = sb->minimum_;
84                     else sb->value_ = v;
86                     sb->update();
87                   } else if (w == &(sb->down_button_)) {
88                     // Down button pressed...
89                     v = sb->value_ - sb->step_;
91                     if (v < sb->minimum_) sb->value_ = sb->maximum_;
92                     else sb->value_ = v;
94                     sb->update();
95                   }
97                   sb->do_callback();
98                 }
99   void          update() {
100                   char s[255];          // Value string
102                   if (format_[0]=='%'&&format_[1]=='.'&&format_[2]=='*') {  // precision argument
103                     // this code block is a simplified version of
104                     // Fl_Valuator::format() and works well (but looks ugly)
105                     int c = 0;
106                     char temp[64], *sp = temp;
107                     sprintf(temp, "%.12f", step_);
108                     while (*sp) sp++;
109                     sp--;
110                     while (sp>temp && *sp=='0') sp--;
111                     while (sp>temp && (*sp>='0' && *sp<='9')) { sp--; c++; }
112                     sprintf(s, format_, c, value_);
113                   } else {
114                     sprintf(s, format_, value_);
115                   }
116                   input_.value(s);
117                 }
119   public:
121                 /**
122                   Creates a new Fl_Spinner widget using the given position, size,
123                   and label string.
124                   <P>Inherited destructor Destroys the widget and any value associated with it.
125                 */
126                 Fl_Spinner(int X, int Y, int W, int H, const char *L = 0)
127                   : Fl_Group(X, Y, W, H, L),
128                     input_(X, Y, W - H / 2 - 2, H),
129                     up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, "@-42<"),
130                     down_button_(X + W - H / 2 - 2, Y + H - H / 2,
131                                  H / 2 + 2, H / 2, "@-42>") {
132                   end();
134                   value_   = 1.0;
135                   minimum_ = 1.0;
136                   maximum_ = 100.0;
137                   step_    = 1.0;
138                   format_  = "%g";
140                   align(FL_ALIGN_LEFT);
142                   input_.value("1");
143                   input_.type(FL_INT_INPUT);
144                   input_.when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE);
145                   input_.callback((Fl_Callback *)sb_cb, this);
147                   up_button_.callback((Fl_Callback *)sb_cb, this);
149                   down_button_.callback((Fl_Callback *)sb_cb, this);
150                 }
152   /** Sets or returns the format string for the value. */
153   const char    *format() { return (format_); }
154   /** Sets or returns the format string for the value. */
155   void          format(const char *f) { format_ = f; update(); }
157   int           handle(int event) {
158                   switch (event) {
159                     case FL_KEYDOWN :
160                     case FL_SHORTCUT :
161                       if (Fl::event_key() == FL_Up) {
162                         up_button_.do_callback();
163                         return 1;
164                       } else if (Fl::event_key() == FL_Down) {
165                         down_button_.do_callback();
166                         return 1;
167                       } else return 0;
169                     case FL_FOCUS :
170                       if (input_.take_focus()) return 1;
171                       else return 0;
172                   }
174                   return Fl_Group::handle(event);
175                 }
177   /** Speling mistakes retained for source compatibility \deprecated */
178   double        maxinum() const { return (maximum_); }
179   /** Gets the maximum value of the widget. */
180   double        maximum() const { return (maximum_); }
181   /** Sets the maximum value of the widget. */
182   void          maximum(double m) { maximum_ = m; }
183   /** Speling mistakes retained for source compatibility \deprecated */
184   double        mininum() const { return (minimum_); }
185   /** Gets the minimum value of the widget. */
186   double        minimum() const { return (minimum_); }
187   /** Sets the minimum value of the widget. */
188   void          minimum(double m) { minimum_ = m; }
189   /** Sets the minimum and maximum values for the widget. */
190   void          range(double a, double b) { minimum_ = a; maximum_ = b; }
191   void          resize(int X, int Y, int W, int H) {
192                   Fl_Group::resize(X,Y,W,H);
194                   input_.resize(X, Y, W - H / 2 - 2, H);
195                   up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2);
196                   down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2,
197                                       H / 2 + 2, H / 2);
198                 }
199   /**
200     Sets or returns the amount to change the value when the user clicks a button. 
201     Before setting step to a non-integer value, the spinner 
202     type() should be changed to floating point. 
203   */
204   double        step() const { return (step_); }
205   /** See double Fl_Spinner::step() const */
206   void          step(double s) {
207                   step_ = s;
208                   if (step_ != (int)step_) input_.type(FL_FLOAT_INPUT);
209                   else input_.type(FL_INT_INPUT);
210                   update();
211                 }
212   /** Gets the color of the text in the input field. */
213   Fl_Color      textcolor() const {
214                   return (input_.textcolor());
215                 }
216   /** Sets the color of the text in the input field. */
217   void          textcolor(Fl_Color c) {
218                   input_.textcolor(c);
219                 }
220   /** Gets the font of the text in the input field. */
221   Fl_Font       textfont() const {
222                   return (input_.textfont());
223                 }
224   /** Sets the font of the text in the input field. */
225   void          textfont(Fl_Font f) {
226                   input_.textfont(f);
227                 }
228   /** Gets the size of the text in the input field. */
229   Fl_Fontsize  textsize() const {
230                   return (input_.textsize());
231                 }
232   /** Sets the size of the text in the input field. */
233   void          textsize(Fl_Fontsize s) {
234                   input_.textsize(s);
235                 }
236   /** Gets the numeric representation in the input field.
237    \see Fl_Spinner::type(uchar) 
238   */
239   uchar         type() const { return (input_.type()); }
240   /** Sets the numeric representation in the input field.
241    Valid values are FL_INT_INPUT and FL_FLOAT_INPUT.
242    Also changes the format() template.
243    Setting a new spinner type via a superclass pointer will not work.
244    \note  type is not a virtual function. 
245    */
246   void          type(uchar v) { 
247                   if (v==FL_FLOAT_INPUT) {
248                     format("%.*f");
249                   } else {
250                     format("%.0f");
251                   }
252                   input_.type(v); 
253                 }
254   /** Gets the current value of the widget. */
255   double        value() const { return (value_); }
256   /**
257     Sets the current value of the widget.
258     Before setting value to a non-integer value, the spinner 
259     type() should be changed to floating point. 
260   */
261   void          value(double v) { value_ = v; update(); }
264 #endif // !Fl_Spinner_H
267 // End of "$Id: Fl_Spinner.H 8339 2011-01-30 12:50:19Z ianmacarthur $".