FLTK 1.3.0
Fl_Spinner.H
00001 //
00002 // "$Id: Fl_Spinner.H 8339 2011-01-30 12:50:19Z ianmacarthur $"
00003 //
00004 // Spinner widget for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 /* \file
00029    Fl_Spinner widget . */
00030 
00031 #ifndef Fl_Spinner_H
00032 #  define Fl_Spinner_H
00033 
00034 //
00035 // Include necessary headers...
00036 //
00037 
00038 #  include <FL/Enumerations.H>
00039 #  include <FL/Fl_Group.H>
00040 #  include <FL/Fl_Input.H>
00041 #  include <FL/Fl_Repeat_Button.H>
00042 #  include <stdio.h>
00043 #  include <stdlib.h>
00044 
00045 
00051 class FL_EXPORT Fl_Spinner : public Fl_Group {
00052   
00053   double        value_;                 // Current value
00054   double        minimum_;               // Minimum value
00055   double        maximum_;               // Maximum value
00056   double        step_;                  // Amount to add/subtract for up/down
00057   const char    *format_;               // Format string
00058 
00059   Fl_Input      input_;                 // Input field for the value
00060   Fl_Repeat_Button
00061                 up_button_,             // Up button
00062                 down_button_;           // Down button
00063 
00064 
00065   static void   sb_cb(Fl_Widget *w, Fl_Spinner *sb) {
00066                   double v;             // New value
00067 
00068                   if (w == &(sb->input_)) {
00069                     // Something changed in the input field...
00070                     v = atof(sb->input_.value());
00071 
00072                     if (v < sb->minimum_) {
00073                       sb->value_ = sb->minimum_;
00074                       sb->update();
00075                     } else if (v > sb->maximum_) {
00076                       sb->value_ = sb->maximum_;
00077                       sb->update();
00078                     } else sb->value_ = v;
00079                   } else if (w == &(sb->up_button_)) {
00080                     // Up button pressed...
00081                     v = sb->value_ + sb->step_;
00082 
00083                     if (v > sb->maximum_) sb->value_ = sb->minimum_;
00084                     else sb->value_ = v;
00085 
00086                     sb->update();
00087                   } else if (w == &(sb->down_button_)) {
00088                     // Down button pressed...
00089                     v = sb->value_ - sb->step_;
00090 
00091                     if (v < sb->minimum_) sb->value_ = sb->maximum_;
00092                     else sb->value_ = v;
00093 
00094                     sb->update();
00095                   }
00096 
00097                   sb->do_callback();
00098                 }
00099   void          update() {
00100                   char s[255];          // Value string
00101 
00102                   if (format_[0]=='%'&&format_[1]=='.'&&format_[2]=='*') {  // precision argument
00103                     // this code block is a simplified version of
00104                     // Fl_Valuator::format() and works well (but looks ugly)
00105                     int c = 0;
00106                     char temp[64], *sp = temp;
00107                     sprintf(temp, "%.12f", step_);
00108                     while (*sp) sp++;
00109                     sp--;
00110                     while (sp>temp && *sp=='0') sp--;
00111                     while (sp>temp && (*sp>='0' && *sp<='9')) { sp--; c++; }
00112                     sprintf(s, format_, c, value_);
00113                   } else {
00114                     sprintf(s, format_, value_);
00115                   }
00116                   input_.value(s);
00117                 }
00118 
00119   public:
00120 
00126                 Fl_Spinner(int X, int Y, int W, int H, const char *L = 0)
00127                   : Fl_Group(X, Y, W, H, L),
00128                     input_(X, Y, W - H / 2 - 2, H),
00129                     up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, "@-42<"),
00130                     down_button_(X + W - H / 2 - 2, Y + H - H / 2,
00131                                  H / 2 + 2, H / 2, "@-42>") {
00132                   end();
00133 
00134                   value_   = 1.0;
00135                   minimum_ = 1.0;
00136                   maximum_ = 100.0;
00137                   step_    = 1.0;
00138                   format_  = "%g";
00139 
00140                   align(FL_ALIGN_LEFT);
00141 
00142                   input_.value("1");
00143                   input_.type(FL_INT_INPUT);
00144                   input_.when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE);
00145                   input_.callback((Fl_Callback *)sb_cb, this);
00146 
00147                   up_button_.callback((Fl_Callback *)sb_cb, this);
00148 
00149                   down_button_.callback((Fl_Callback *)sb_cb, this);
00150                 }
00151 
00153   const char    *format() { return (format_); }
00155   void          format(const char *f) { format_ = f; update(); }
00156 
00157   int           handle(int event) {
00158                   switch (event) {
00159                     case FL_KEYDOWN :
00160                     case FL_SHORTCUT :
00161                       if (Fl::event_key() == FL_Up) {
00162                         up_button_.do_callback();
00163                         return 1;
00164                       } else if (Fl::event_key() == FL_Down) {
00165                         down_button_.do_callback();
00166                         return 1;
00167                       } else return 0;
00168 
00169                     case FL_FOCUS :
00170                       if (input_.take_focus()) return 1;
00171                       else return 0;
00172                   }
00173 
00174                   return Fl_Group::handle(event);
00175                 }
00176 
00178   double        maxinum() const { return (maximum_); }
00180   double        maximum() const { return (maximum_); }
00182   void          maximum(double m) { maximum_ = m; }
00184   double        mininum() const { return (minimum_); }
00186   double        minimum() const { return (minimum_); }
00188   void          minimum(double m) { minimum_ = m; }
00190   void          range(double a, double b) { minimum_ = a; maximum_ = b; }
00191   void          resize(int X, int Y, int W, int H) {
00192                   Fl_Group::resize(X,Y,W,H);
00193 
00194                   input_.resize(X, Y, W - H / 2 - 2, H);
00195                   up_button_.resize(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2);
00196                   down_button_.resize(X + W - H / 2 - 2, Y + H - H / 2,
00197                                       H / 2 + 2, H / 2);
00198                 }
00204   double        step() const { return (step_); }
00206   void          step(double s) {
00207                   step_ = s;
00208                   if (step_ != (int)step_) input_.type(FL_FLOAT_INPUT);
00209                   else input_.type(FL_INT_INPUT);
00210                   update();
00211                 }
00213   Fl_Color      textcolor() const {
00214                   return (input_.textcolor());
00215                 }
00217   void          textcolor(Fl_Color c) {
00218                   input_.textcolor(c);
00219                 }
00221   Fl_Font       textfont() const {
00222                   return (input_.textfont());
00223                 }
00225   void          textfont(Fl_Font f) {
00226                   input_.textfont(f);
00227                 }
00229   Fl_Fontsize  textsize() const {
00230                   return (input_.textsize());
00231                 }
00233   void          textsize(Fl_Fontsize s) {
00234                   input_.textsize(s);
00235                 }
00239   uchar         type() const { return (input_.type()); }
00246   void          type(uchar v) { 
00247                   if (v==FL_FLOAT_INPUT) {
00248                     format("%.*f");
00249                   } else {
00250                     format("%.0f");
00251                   }
00252                   input_.type(v); 
00253                 }
00255   double        value() const { return (value_); }
00261   void          value(double v) { value_ = v; update(); }
00262 };
00263 
00264 #endif // !Fl_Spinner_H
00265 
00266 //
00267 // End of "$Id: Fl_Spinner.H 8339 2011-01-30 12:50:19Z ianmacarthur $".
00268 //