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_Scrollbar.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Scrollbar.cxx 7903 2010-11-28 21:06:39Z matt $"
00003 //
00004 // Scroll bar 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 
00029 #include <FL/Fl.H>
00030 #include <FL/Fl_Scrollbar.H>
00031 #include <FL/fl_draw.H>
00032 #include <math.h>
00033 #include "flstring.h"
00034 
00035 #define INITIALREPEAT .5
00036 #define REPEAT .05
00037 
00038 void Fl_Scrollbar::increment_cb() {
00039   char inv = maximum()<minimum();
00040   int ls = inv ? -linesize_ : linesize_;
00041   int i;
00042   switch (pushed_) {
00043     case 1: // clicked on arrow left
00044       i = -ls;
00045       break;
00046     default: // clicked on arrow right
00047       i =  ls;
00048       break;
00049     case 5: // clicked into the box next to the slider on the left
00050       i = -(int((maximum()-minimum())*slider_size()/(1.0-slider_size())));
00051       if (inv) {
00052         if (i<-ls) i = -ls;
00053       } else {
00054         if (i>-ls) i = -ls; // err
00055       }
00056       break;
00057     case 6: // clicked into the box next to the slider on the right
00058       i = (int((maximum()-minimum())*slider_size()/(1.0-slider_size())));
00059       if (inv) {
00060         if (i>ls) i = ls;
00061       } else {
00062         if (i<ls) i = ls; // err
00063       }
00064       break;
00065   }
00066   handle_drag(clamp(value() + i));
00067 }
00068 
00069 void Fl_Scrollbar::timeout_cb(void* v) {
00070   Fl_Scrollbar* s = (Fl_Scrollbar*)v;
00071   s->increment_cb();
00072   Fl::add_timeout(REPEAT, timeout_cb, s);
00073 }
00074 
00075 int Fl_Scrollbar::handle(int event) {
00076   // area of scrollbar:
00077   int area;
00078   int X=x(); int Y=y(); int W=w(); int H=h();
00079 
00080   // adjust slider area to be inside the arrow buttons:
00081   if (horizontal()) {
00082     if (W >= 3*H) {X += H; W -= 2*H;}
00083   } else {
00084     if (H >= 3*W) {Y += W; H -= 2*W;}
00085   }
00086 
00087   // which widget part is highlighted?
00088   int relx;
00089   int ww;
00090   if (horizontal()) {
00091     relx = Fl::event_x()-X;
00092     ww = W;
00093   } else {
00094     relx = Fl::event_y()-Y;
00095     ww = H;
00096   }
00097   if (relx < 0) area = 1;
00098   else if (relx >= ww) area = 2;
00099   else {
00100     int S = int(slider_size()*ww+.5);
00101     int T = (horizontal() ? H : W)/2+1;
00102     if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
00103     if (S < T) S = T;
00104     double val =
00105       (maximum()-minimum()) ? (value()-minimum())/(maximum()-minimum()) : 0.5;
00106     int sliderx;
00107     if (val >= 1.0) sliderx = ww-S;
00108     else if (val <= 0.0) sliderx = 0;
00109     else sliderx = int(val*(ww-S)+.5);
00110     if (Fl::event_button() == FL_MIDDLE_MOUSE) area = 8;
00111     else if (relx < sliderx) area = 5;
00112     else if (relx >= sliderx+S) area = 6;
00113     else area = 8;
00114   }
00115 
00116   switch (event) {
00117   case FL_ENTER:
00118   case FL_LEAVE:
00119     return 1;
00120   case FL_RELEASE:
00121       damage(FL_DAMAGE_ALL);
00122     if (pushed_) {
00123       Fl::remove_timeout(timeout_cb, this);
00124       pushed_ = 0;
00125     }
00126     handle_release();
00127     return 1;
00128   case FL_PUSH:
00129     if (pushed_) return 1;
00130     if (area != 8) pushed_ = area;
00131     if (pushed_) {
00132       handle_push();
00133       Fl::add_timeout(INITIALREPEAT, timeout_cb, this);
00134       increment_cb();
00135       damage(FL_DAMAGE_ALL);
00136       return 1;
00137     }
00138     return Fl_Slider::handle(event, X,Y,W,H);
00139   case FL_DRAG:
00140     if (pushed_) return 1;
00141     return Fl_Slider::handle(event, X,Y,W,H);
00142   case FL_MOUSEWHEEL :
00143     if (horizontal()) {
00144       if (Fl::e_dx==0) return 0;
00145       int ls = maximum()>=minimum() ? linesize_ : -linesize_;
00146       handle_drag(clamp(value() + ls * Fl::e_dx));
00147       return 1;
00148     } else {
00149       if (Fl::e_dy==0) return 0;
00150       int ls = maximum()>=minimum() ? linesize_ : -linesize_;
00151       handle_drag(clamp(value() + ls * Fl::e_dy));
00152       return 1;
00153     }
00154   case FL_SHORTCUT:
00155   case FL_KEYBOARD: {
00156     int v = value();
00157     int ls = maximum()>=minimum() ? linesize_ : -linesize_;
00158     if (horizontal()) {
00159       switch (Fl::event_key()) {
00160       case FL_Left:
00161         v -= ls;
00162         break;
00163       case FL_Right:
00164         v += ls;
00165         break;
00166       default:
00167         return 0;
00168       }
00169     } else { // vertical
00170       switch (Fl::event_key()) {
00171       case FL_Up:
00172         v -= ls;
00173         break;
00174       case FL_Down:
00175         v += ls;
00176         break;
00177       case FL_Page_Up:
00178         if (slider_size() >= 1.0) return 0;
00179         v -= int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
00180         v += ls;
00181         break;
00182       case FL_Page_Down:
00183         if (slider_size() >= 1.0) return 0;
00184         v += int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
00185         v -= ls;
00186         break;
00187       case FL_Home:
00188         v = int(minimum());
00189         break;
00190       case FL_End:
00191         v = int(maximum());
00192         break;
00193       default:
00194         return 0;
00195       }
00196     }
00197     v = int(clamp(v));
00198     if (v != value()) {
00199       Fl_Slider::value(v);
00200       value_damage();
00201       set_changed();
00202       do_callback();
00203     }
00204     return 1;}
00205   }
00206   return 0;
00207 }
00208 
00209 void Fl_Scrollbar::draw() {
00210   if (damage()&FL_DAMAGE_ALL) draw_box();
00211   int X = x()+Fl::box_dx(box());
00212   int Y = y()+Fl::box_dy(box());
00213   int W = w()-Fl::box_dw(box());
00214   int H = h()-Fl::box_dh(box());
00215   if (horizontal()) {
00216     if (W < 3*H) {Fl_Slider::draw(X,Y,W,H); return;}
00217     Fl_Slider::draw(X+H,Y,W-2*H,H);
00218     if (damage()&FL_DAMAGE_ALL) {
00219       draw_box((pushed_==1) ? fl_down(slider()) : slider(),
00220                X, Y, H, H, selection_color());
00221       draw_box((pushed_==2) ? fl_down(slider()) : slider(),
00222                X+W-H, Y, H, H, selection_color());
00223       if (active_r())
00224         fl_color(labelcolor());
00225       else
00226         fl_color(fl_inactive(labelcolor()));
00227       int w1 = (H-4)/3; if (w1 < 1) w1 = 1;
00228       int x1 = X+(H-w1-1)/2;
00229       int yy1 = Y+(H-2*w1-1)/2;
00230       if (Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
00231         fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1-1, yy1+w1, x1+w1, yy1);
00232         x1 += (W-H);
00233         fl_polygon(x1, yy1, x1+1, yy1+w1, x1, yy1+2*w1, x1+w1, yy1+w1);
00234       } else {
00235         fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1, yy1);
00236         x1 += (W-H);
00237         fl_polygon(x1, yy1, x1, yy1+2*w1, x1+w1, yy1+w1);
00238       }
00239     }
00240   } else { // vertical
00241     if (H < 3*W) {Fl_Slider::draw(X,Y,W,H); return;}
00242     Fl_Slider::draw(X,Y+W,W,H-2*W);
00243     if (damage()&FL_DAMAGE_ALL) {
00244       draw_box((pushed_==1) ? fl_down(slider()) : slider(),
00245                X, Y, W, W, selection_color());
00246       draw_box((pushed_==2) ? fl_down(slider()) : slider(),
00247                X, Y+H-W, W, W, selection_color());
00248       if (active_r())
00249         fl_color(labelcolor());
00250       else
00251         fl_color(fl_inactive(labelcolor()));
00252       int w1 = (W-4)/3; if (w1 < 1) w1 = 1;
00253       int x1 = X+(W-2*w1-1)/2;
00254       int yy1 = Y+(W-w1-1)/2;
00255       if (Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
00256         fl_polygon(x1, yy1+w1, x1+w1, yy1+w1-1, x1+2*w1, yy1+w1, x1+w1, yy1);
00257         yy1 += H-W;
00258         fl_polygon(x1, yy1, x1+w1, yy1+1, x1+w1, yy1+w1);
00259         fl_polygon(x1+w1, yy1+1, x1+2*w1, yy1, x1+w1, yy1+w1);
00260       } else {
00261         fl_polygon(x1, yy1+w1, x1+2*w1, yy1+w1, x1+w1, yy1);
00262         yy1 += H-W;
00263         fl_polygon(x1, yy1, x1+w1, yy1+w1, x1+2*w1, yy1);
00264       }
00265     }
00266   }
00267 }
00268 
00273 Fl_Scrollbar::Fl_Scrollbar(int X, int Y, int W, int H, const char* L)
00274   : Fl_Slider(X, Y, W, H, L) {
00275   box(FL_FLAT_BOX);
00276   color(FL_DARK2);
00277   slider(FL_UP_BOX);
00278   linesize_ = 16;
00279   pushed_ = 0;
00280   step(1);
00281 }
00282 
00284 Fl_Scrollbar::~Fl_Scrollbar() {
00285   if (pushed_)
00286     Fl::remove_timeout(timeout_cb, this);
00287 }
00288 
00289 
00290 //
00291 // End of "$Id: Fl_Scrollbar.cxx 7903 2010-11-28 21:06:39Z matt $".
00292 //