fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Slider.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Slider.cxx 7903 2010-11-28 21:06:39Z matt $"
00003 //
00004 // Slider 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 #include <FL/Fl.H>
00029 #include <FL/Fl_Slider.H>
00030 #include <FL/fl_draw.H>
00031 #include <math.h>
00032 #include "flstring.h"
00033 
00034 void Fl_Slider::_Fl_Slider() {
00035   slider_size_ = 0;
00036   slider_ = 0; // FL_UP_BOX;
00037 }
00038 
00043 Fl_Slider::Fl_Slider(int X, int Y, int W, int H, const char* L)
00044 : Fl_Valuator(X, Y, W, H, L) {
00045   box(FL_DOWN_BOX);
00046   _Fl_Slider();
00047 }
00048 
00053 Fl_Slider::Fl_Slider(uchar t, int X, int Y, int W, int H, const char* L)
00054   : Fl_Valuator(X, Y, W, H, L) {
00055   type(t);
00056   box(t==FL_HOR_NICE_SLIDER || t==FL_VERT_NICE_SLIDER ?
00057       FL_FLAT_BOX : FL_DOWN_BOX);
00058   _Fl_Slider();
00059 }
00060 
00061 void Fl_Slider::slider_size(double v) {
00062   if (v <  0) v = 0;
00063   if (v > 1) v = 1;
00064   if (slider_size_ != float(v)) {
00065     slider_size_ = float(v); 
00066     damage(FL_DAMAGE_EXPOSE);
00067   }
00068 }
00069 
00074 void Fl_Slider::bounds(double a, double b) {
00075   if (minimum() != a || maximum() != b) {
00076     Fl_Valuator::bounds(a, b); 
00077     damage(FL_DAMAGE_EXPOSE);
00078   }
00079 }
00080 
00089 int Fl_Slider::scrollvalue(int pos, int size, int first, int total) {
00090   step(1, 1);
00091   if (pos+size > first+total) total = pos+size-first;
00092   slider_size(size >= total ? 1.0 : double(size)/double(total));
00093   bounds(first, total-size+first);
00094   return value(pos);
00095 }
00096 
00097 // All slider interaction is done as though the slider ranges from
00098 // zero to one, and the left (bottom) edge of the slider is at the
00099 // given position.  Since when the slider is all the way to the
00100 // right (top) the left (bottom) edge is not all the way over, a
00101 // position on the widget itself covers a wider range than 0-1,
00102 // actually it ranges from 0 to 1/(1-size).
00103 
00104 void Fl_Slider::draw_bg(int X, int Y, int W, int H) {
00105   fl_push_clip(X, Y, W, H);
00106   draw_box();
00107   fl_pop_clip();
00108 
00109   Fl_Color black = active_r() ? FL_FOREGROUND_COLOR : FL_INACTIVE_COLOR;
00110   if (type() == FL_VERT_NICE_SLIDER) {
00111     draw_box(FL_THIN_DOWN_BOX, X+W/2-2, Y, 4, H, black);
00112   } else if (type() == FL_HOR_NICE_SLIDER) {
00113     draw_box(FL_THIN_DOWN_BOX, X, Y+H/2-2, W, 4, black);
00114   }
00115 }
00116 
00117 void Fl_Slider::draw(int X, int Y, int W, int H) {
00118 
00119   double val;
00120   if (minimum() == maximum())
00121     val = 0.5;
00122   else {
00123     val = (value()-minimum())/(maximum()-minimum());
00124     if (val > 1.0) val = 1.0;
00125     else if (val < 0.0) val = 0.0;
00126   }
00127 
00128   int ww = (horizontal() ? W : H);
00129   int xx, S;
00130   if (type()==FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) {
00131     S = int(val*ww+.5);
00132     if (minimum()>maximum()) {S = ww-S; xx = ww-S;}
00133     else xx = 0;
00134   } else {
00135     S = int(slider_size_*ww+.5);
00136     int T = (horizontal() ? H : W)/2+1;
00137     if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
00138     if (S < T) S = T;
00139     xx = int(val*(ww-S)+.5);
00140   }
00141   int xsl, ysl, wsl, hsl;
00142   if (horizontal()) {
00143     xsl = X+xx;
00144     wsl = S;
00145     ysl = Y;
00146     hsl = H;
00147   } else {
00148     ysl = Y+xx;
00149     hsl = S;
00150     xsl = X;
00151     wsl = W;
00152   }
00153 
00154   draw_bg(X, Y, W, H);
00155 
00156   Fl_Boxtype box1 = slider();
00157   if (!box1) {box1 = (Fl_Boxtype)(box()&-2); if (!box1) box1 = FL_UP_BOX;}
00158   if (type() == FL_VERT_NICE_SLIDER) {
00159     draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY);
00160     int d = (hsl-4)/2;
00161     draw_box(FL_THIN_DOWN_BOX, xsl+2, ysl+d, wsl-4, hsl-2*d,selection_color());
00162   } else if (type() == FL_HOR_NICE_SLIDER) {
00163     draw_box(box1, xsl, ysl, wsl, hsl, FL_GRAY);
00164     int d = (wsl-4)/2;
00165     draw_box(FL_THIN_DOWN_BOX, xsl+d, ysl+2, wsl-2*d, hsl-4,selection_color());
00166   } else {
00167     if (wsl>0 && hsl>0) draw_box(box1, xsl, ysl, wsl, hsl, selection_color());
00168 
00169     if (type()!=FL_HOR_FILL_SLIDER && type() != FL_VERT_FILL_SLIDER &&
00170         Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
00171       if (W>H && wsl>(hsl+8)) {
00172         // Draw horizontal grippers
00173         int yy, hh;
00174         hh = hsl-8;
00175         xx = xsl+(wsl-hsl-4)/2;
00176         yy = ysl+3;
00177 
00178         fl_color(fl_darker(selection_color()));
00179         fl_line(xx, yy+hh, xx+hh, yy);
00180         fl_line(xx+6, yy+hh, xx+hh+6, yy);
00181         fl_line(xx+12, yy+hh, xx+hh+12, yy);
00182 
00183         xx++;
00184         fl_color(fl_lighter(selection_color()));
00185         fl_line(xx, yy+hh, xx+hh, yy);
00186         fl_line(xx+6, yy+hh, xx+hh+6, yy);
00187         fl_line(xx+12, yy+hh, xx+hh+12, yy);
00188       } else if (H>W && hsl>(wsl+8)) {
00189         // Draw vertical grippers
00190         int yy;
00191         xx = xsl+4;
00192         ww = wsl-8;
00193         yy = ysl+(hsl-wsl-4)/2;
00194 
00195         fl_color(fl_darker(selection_color()));
00196         fl_line(xx, yy+ww, xx+ww, yy);
00197         fl_line(xx, yy+ww+6, xx+ww, yy+6);
00198         fl_line(xx, yy+ww+12, xx+ww, yy+12);
00199 
00200         yy++;
00201         fl_color(fl_lighter(selection_color()));
00202         fl_line(xx, yy+ww, xx+ww, yy);
00203         fl_line(xx, yy+ww+6, xx+ww, yy+6);
00204         fl_line(xx, yy+ww+12, xx+ww, yy+12);
00205       }
00206     }
00207   }
00208 
00209   draw_label(xsl, ysl, wsl, hsl);
00210   if (Fl::focus() == this) {
00211     if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) draw_focus();
00212     else draw_focus(box1, xsl, ysl, wsl, hsl);
00213   }
00214 }
00215 
00216 void Fl_Slider::draw() {
00217   if (damage()&FL_DAMAGE_ALL) draw_box();
00218   draw(x()+Fl::box_dx(box()),
00219        y()+Fl::box_dy(box()),
00220        w()-Fl::box_dw(box()),
00221        h()-Fl::box_dh(box()));
00222 }
00223 
00224 int Fl_Slider::handle(int event, int X, int Y, int W, int H) {
00225   // Fl_Widget_Tracker wp(this);
00226   switch (event) {
00227   case FL_PUSH: {
00228     Fl_Widget_Tracker wp(this);
00229     if (!Fl::event_inside(X, Y, W, H)) return 0;
00230     handle_push();
00231     if (wp.deleted()) return 1; }
00232     // fall through ...
00233   case FL_DRAG: {
00234 
00235     double val;
00236     if (minimum() == maximum())
00237       val = 0.5;
00238     else {
00239       val = (value()-minimum())/(maximum()-minimum());
00240       if (val > 1.0) val = 1.0;
00241       else if (val < 0.0) val = 0.0;
00242     }
00243 
00244     int ww = (horizontal() ? W : H);
00245     int mx = (horizontal() ? Fl::event_x()-X : Fl::event_y()-Y);
00246     int S;
00247     static int offcenter;
00248 
00249     if (type() == FL_HOR_FILL_SLIDER || type() == FL_VERT_FILL_SLIDER) {
00250 
00251       S = 0;
00252       if (event == FL_PUSH) {
00253         int xx = int(val*ww+.5);
00254         offcenter = mx-xx;
00255         if (offcenter < -10 || offcenter > 10) offcenter = 0;
00256         else return 1;
00257       }
00258 
00259     } else {
00260 
00261       S = int(slider_size_*ww+.5); if (S >= ww) return 0;
00262       int T = (horizontal() ? H : W)/2+1;
00263       if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
00264       if (S < T) S = T;
00265       if (event == FL_PUSH) {
00266         int xx = int(val*(ww-S)+.5);
00267         offcenter = mx-xx;
00268         if (offcenter < 0) offcenter = 0;
00269         else if (offcenter > S) offcenter = S;
00270         else return 1;
00271       }
00272     }
00273 
00274     int xx = mx-offcenter;
00275     double v;
00276     char tryAgain = 1;
00277     while (tryAgain)
00278     {
00279       tryAgain = 0;
00280       if (xx < 0) {
00281         xx = 0;
00282         offcenter = mx; if (offcenter < 0) offcenter = 0;
00283       } else if (xx > (ww-S)) {
00284         xx = ww-S;
00285         offcenter = mx-xx; if (offcenter > S) offcenter = S;
00286       }
00287       v = round(xx*(maximum()-minimum())/(ww-S) + minimum());
00288       // make sure a click outside the sliderbar moves it:
00289       if (event == FL_PUSH && v == value()) {
00290         offcenter = S/2;
00291         event = FL_DRAG;
00292         tryAgain = 1;
00293       }
00294     }
00295     handle_drag(clamp(v));
00296     } return 1;
00297   case FL_RELEASE:
00298     handle_release();
00299     return 1;
00300   case FL_KEYBOARD:
00301     { Fl_Widget_Tracker wp(this);
00302       switch (Fl::event_key()) {
00303         case FL_Up:
00304           if (horizontal()) return 0;
00305           handle_push();
00306           if (wp.deleted()) return 1;
00307           handle_drag(clamp(increment(value(),-1)));
00308           if (wp.deleted()) return 1;
00309           handle_release();
00310           return 1;
00311         case FL_Down:
00312           if (horizontal()) return 0;
00313           handle_push();
00314           if (wp.deleted()) return 1;
00315           handle_drag(clamp(increment(value(),1)));
00316           if (wp.deleted()) return 1;
00317           handle_release();
00318           return 1;
00319         case FL_Left:
00320           if (!horizontal()) return 0;
00321           handle_push();
00322           if (wp.deleted()) return 1;
00323           handle_drag(clamp(increment(value(),-1)));
00324           if (wp.deleted()) return 1;
00325           handle_release();
00326           return 1;
00327         case FL_Right:
00328           if (!horizontal()) return 0;
00329           handle_push();
00330           if (wp.deleted()) return 1;
00331           handle_drag(clamp(increment(value(),1)));
00332           if (wp.deleted()) return 1;
00333           handle_release();
00334           return 1;
00335         default:
00336           return 0;
00337       }
00338     }
00339     // break not required because of switch...
00340   case FL_FOCUS :
00341   case FL_UNFOCUS :
00342     if (Fl::visible_focus()) {
00343       redraw();
00344       return 1;
00345     } else return 0;
00346   case FL_ENTER :
00347   case FL_LEAVE :
00348     return 1;
00349   default:
00350     return 0;
00351   }
00352 }
00353 
00354 int Fl_Slider::handle(int event) {
00355   if (event == FL_PUSH && Fl::visible_focus()) {
00356     Fl::focus(this);
00357     redraw();
00358   }
00359 
00360   return handle(event,
00361                 x()+Fl::box_dx(box()),
00362                 y()+Fl::box_dy(box()),
00363                 w()-Fl::box_dw(box()),
00364                 h()-Fl::box_dh(box()));
00365 }
00366 
00367 //
00368 // End of "$Id: Fl_Slider.cxx 7903 2010-11-28 21:06:39Z matt $".
00369 //