2 // "$Id: Fl_Slider.cxx 8726 2011-05-23 18:32:47Z AlbrechtS $"
4 // Slider widget for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2011 by Bill Spitzak and others.
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
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 #include <FL/Fl_Slider.H>
30 #include <FL/fl_draw.H>
34 #if defined(FL_DLL) // really needed for c'tors for MS VC++ only
35 #include <FL/Fl_Hor_Slider.H>
38 void Fl_Slider::_Fl_Slider() {
40 slider_
= 0; // FL_UP_BOX;
44 Creates a new Fl_Slider widget using the given position,
45 size, and label string. The default boxtype is FL_DOWN_BOX.
47 Fl_Slider::Fl_Slider(int X
, int Y
, int W
, int H
, const char* L
)
48 : Fl_Valuator(X
, Y
, W
, H
, L
) {
54 Creates a new Fl_Slider widget using the given box type, position,
55 size, and label string.
57 Fl_Slider::Fl_Slider(uchar t
, int X
, int Y
, int W
, int H
, const char* L
)
58 : Fl_Valuator(X
, Y
, W
, H
, L
) {
60 box(t
==FL_HOR_NICE_SLIDER
|| t
==FL_VERT_NICE_SLIDER
?
61 FL_FLAT_BOX
: FL_DOWN_BOX
);
65 void Fl_Slider::slider_size(double v
) {
68 if (slider_size_
!= float(v
)) {
69 slider_size_
= float(v
);
70 damage(FL_DAMAGE_EXPOSE
);
75 Sets the minimum (a) and maximum (b) values for the valuator widget.
76 if at least one of the values is changed, a partial redraw is asked.
78 void Fl_Slider::bounds(double a
, double b
) {
79 if (minimum() != a
|| maximum() != b
) {
80 Fl_Valuator::bounds(a
, b
);
81 damage(FL_DAMAGE_EXPOSE
);
86 Sets the size and position of the sliding knob in the box.
87 \param[in] pos position of first line displayed
88 \param[in] size size of window in lines
89 \param[in] first number of first line
90 \param[in] total total number of lines
91 Returns Fl_Valuator::value(p)
93 int Fl_Slider::scrollvalue(int pos
, int size
, int first
, int total
) {
95 if (pos
+size
> first
+total
) total
= pos
+size
-first
;
96 slider_size(size
>= total
? 1.0 : double(size
)/double(total
));
97 bounds(first
, total
-size
+first
);
101 // All slider interaction is done as though the slider ranges from
102 // zero to one, and the left (bottom) edge of the slider is at the
103 // given position. Since when the slider is all the way to the
104 // right (top) the left (bottom) edge is not all the way over, a
105 // position on the widget itself covers a wider range than 0-1,
106 // actually it ranges from 0 to 1/(1-size).
108 void Fl_Slider::draw_bg(int X
, int Y
, int W
, int H
) {
109 fl_push_clip(X
, Y
, W
, H
);
113 Fl_Color black
= active_r() ? FL_BLACK
: FL_INACTIVE_COLOR
;
114 if (type() == FL_VERT_NICE_SLIDER
) {
115 draw_box(FL_THIN_DOWN_BOX
, X
+W
/2-2, Y
, 4, H
, black
);
116 } else if (type() == FL_HOR_NICE_SLIDER
) {
117 draw_box(FL_THIN_DOWN_BOX
, X
, Y
+H
/2-2, W
, 4, black
);
121 void Fl_Slider::draw(int X
, int Y
, int W
, int H
) {
124 if (minimum() == maximum())
127 val
= (value()-minimum())/(maximum()-minimum());
128 if (val
> 1.0) val
= 1.0;
129 else if (val
< 0.0) val
= 0.0;
132 int ww
= (horizontal() ? W
: H
);
134 if (type()==FL_HOR_FILL_SLIDER
|| type() == FL_VERT_FILL_SLIDER
) {
136 if (minimum()>maximum()) {S
= ww
-S
; xx
= ww
-S
;}
139 S
= int(slider_size_
*ww
+.5);
140 int T
= (horizontal() ? H
: W
)/2+1;
141 if (type()==FL_VERT_NICE_SLIDER
|| type()==FL_HOR_NICE_SLIDER
) T
+= 4;
143 xx
= int(val
*(ww
-S
)+.5);
145 int xsl
, ysl
, wsl
, hsl
;
160 Fl_Boxtype box1
= slider();
161 if (!box1
) {box1
= (Fl_Boxtype
)(box()&-2); if (!box1
) box1
= FL_UP_BOX
;}
162 if (type() == FL_VERT_NICE_SLIDER
) {
163 draw_box(box1
, xsl
, ysl
, wsl
, hsl
, FL_GRAY
);
165 draw_box(FL_THIN_DOWN_BOX
, xsl
+2, ysl
+d
, wsl
-4, hsl
-2*d
,selection_color());
166 } else if (type() == FL_HOR_NICE_SLIDER
) {
167 draw_box(box1
, xsl
, ysl
, wsl
, hsl
, FL_GRAY
);
169 draw_box(FL_THIN_DOWN_BOX
, xsl
+d
, ysl
+2, wsl
-2*d
, hsl
-4,selection_color());
171 if (wsl
>0 && hsl
>0) draw_box(box1
, xsl
, ysl
, wsl
, hsl
, selection_color());
173 if (type()!=FL_HOR_FILL_SLIDER
&& type() != FL_VERT_FILL_SLIDER
&&
174 Fl::scheme_
&& !strcmp(Fl::scheme_
, "gtk+")) {
175 if (W
>H
&& wsl
>(hsl
+8)) {
176 // Draw horizontal grippers
179 xx
= xsl
+(wsl
-hsl
-4)/2;
182 fl_color(fl_darker(selection_color()));
183 fl_line(xx
, yy
+hh
, xx
+hh
, yy
);
184 fl_line(xx
+6, yy
+hh
, xx
+hh
+6, yy
);
185 fl_line(xx
+12, yy
+hh
, xx
+hh
+12, yy
);
188 fl_color(fl_lighter(selection_color()));
189 fl_line(xx
, yy
+hh
, xx
+hh
, yy
);
190 fl_line(xx
+6, yy
+hh
, xx
+hh
+6, yy
);
191 fl_line(xx
+12, yy
+hh
, xx
+hh
+12, yy
);
192 } else if (H
>W
&& hsl
>(wsl
+8)) {
193 // Draw vertical grippers
197 yy
= ysl
+(hsl
-wsl
-4)/2;
199 fl_color(fl_darker(selection_color()));
200 fl_line(xx
, yy
+ww
, xx
+ww
, yy
);
201 fl_line(xx
, yy
+ww
+6, xx
+ww
, yy
+6);
202 fl_line(xx
, yy
+ww
+12, xx
+ww
, yy
+12);
205 fl_color(fl_lighter(selection_color()));
206 fl_line(xx
, yy
+ww
, xx
+ww
, yy
);
207 fl_line(xx
, yy
+ww
+6, xx
+ww
, yy
+6);
208 fl_line(xx
, yy
+ww
+12, xx
+ww
, yy
+12);
213 draw_label(xsl
, ysl
, wsl
, hsl
);
214 if (Fl::focus() == this) {
215 if (type() == FL_HOR_FILL_SLIDER
|| type() == FL_VERT_FILL_SLIDER
) draw_focus();
216 else draw_focus(box1
, xsl
, ysl
, wsl
, hsl
);
220 void Fl_Slider::draw() {
221 if (damage()&FL_DAMAGE_ALL
) draw_box();
222 draw(x()+Fl::box_dx(box()),
223 y()+Fl::box_dy(box()),
224 w()-Fl::box_dw(box()),
225 h()-Fl::box_dh(box()));
228 int Fl_Slider::handle(int event
, int X
, int Y
, int W
, int H
) {
229 // Fl_Widget_Tracker wp(this);
232 Fl_Widget_Tracker
wp(this);
233 if (!Fl::event_inside(X
, Y
, W
, H
)) return 0;
235 if (wp
.deleted()) return 1; }
240 if (minimum() == maximum())
243 val
= (value()-minimum())/(maximum()-minimum());
244 if (val
> 1.0) val
= 1.0;
245 else if (val
< 0.0) val
= 0.0;
248 int ww
= (horizontal() ? W
: H
);
249 int mx
= (horizontal() ? Fl::event_x()-X
: Fl::event_y()-Y
);
251 static int offcenter
;
253 if (type() == FL_HOR_FILL_SLIDER
|| type() == FL_VERT_FILL_SLIDER
) {
256 if (event
== FL_PUSH
) {
257 int xx
= int(val
*ww
+.5);
259 if (offcenter
< -10 || offcenter
> 10) offcenter
= 0;
265 S
= int(slider_size_
*ww
+.5); if (S
>= ww
) return 0;
266 int T
= (horizontal() ? H
: W
)/2+1;
267 if (type()==FL_VERT_NICE_SLIDER
|| type()==FL_HOR_NICE_SLIDER
) T
+= 4;
269 if (event
== FL_PUSH
) {
270 int xx
= int(val
*(ww
-S
)+.5);
272 if (offcenter
< 0) offcenter
= 0;
273 else if (offcenter
> S
) offcenter
= S
;
278 int xx
= mx
-offcenter
;
286 offcenter
= mx
; if (offcenter
< 0) offcenter
= 0;
287 } else if (xx
> (ww
-S
)) {
289 offcenter
= mx
-xx
; if (offcenter
> S
) offcenter
= S
;
291 v
= round(xx
*(maximum()-minimum())/(ww
-S
) + minimum());
292 // make sure a click outside the sliderbar moves it:
293 if (event
== FL_PUSH
&& v
== value()) {
299 handle_drag(clamp(v
));
305 { Fl_Widget_Tracker
wp(this);
306 switch (Fl::event_key()) {
308 if (horizontal()) return 0;
310 if (wp
.deleted()) return 1;
311 handle_drag(clamp(increment(value(),-1)));
312 if (wp
.deleted()) return 1;
316 if (horizontal()) return 0;
318 if (wp
.deleted()) return 1;
319 handle_drag(clamp(increment(value(),1)));
320 if (wp
.deleted()) return 1;
324 if (!horizontal()) return 0;
326 if (wp
.deleted()) return 1;
327 handle_drag(clamp(increment(value(),-1)));
328 if (wp
.deleted()) return 1;
332 if (!horizontal()) return 0;
334 if (wp
.deleted()) return 1;
335 handle_drag(clamp(increment(value(),1)));
336 if (wp
.deleted()) return 1;
343 // break not required because of switch...
346 if (Fl::visible_focus()) {
355 if ( this != Fl::belowmouse() )
360 const int steps
= Fl::event_ctrl() ? 128 : 16;
362 const float step
= fabs( maximum() - minimum() ) / (float)steps
;
366 /* slider is in 'upside down' configuration, invert meaning of mousewheel */
367 if ( minimum() > maximum() )
370 handle_drag(clamp(value() + step
* dy
));
378 int Fl_Slider::handle(int event
) {
379 if (event
== FL_PUSH
&& Fl::visible_focus()) {
385 x()+Fl::box_dx(box()),
386 y()+Fl::box_dy(box()),
387 w()-Fl::box_dw(box()),
388 h()-Fl::box_dh(box()));
392 The following constructor must not be in the header file if we
393 build a shared object (DLL). Instead it is defined here to force
394 the constructor (and default destructor as well) to be defined
395 in the DLL and exported (STR #2632).
397 Note: if you the ctor here, do the same changes in the specific
398 header file as well. This redundant definition was chosen to enable
399 inline constructors in the header files (for static linking) as well
400 as the one here for dynamic linking (Windows DLL).
405 Fl_Hor_Slider::Fl_Hor_Slider(int X
,int Y
,int W
,int H
,const char *l
)
406 : Fl_Slider(X
,Y
,W
,H
,l
) {type(FL_HOR_SLIDER
);}
411 // End of "$Id: Fl_Slider.cxx 8726 2011-05-23 18:32:47Z AlbrechtS $".