|
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) ![]() |
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 //