1 //
2 // "$Id: Fl_Scrollbar.cxx 6042 2008-02-25 13:00:53Z matt $"
3 //
4 // Scroll bar widget for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2006 by Bill Spitzak and others.
7 //
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.
12 //
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.
17 //
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 // USA.
22 //
23 // Please report all bugs and problems on the following page:
24 //
25 // http://www.fltk.org/str.php
26 //
27
28 #include <FL/Fl.H>
29 #include <FL/Fl_Scrollbar.H>
30 #include <FL/fl_draw.H>
31 #include <math.h>
32 #include "flstring.h"
33
34 #define INITIALREPEAT .5
35 #define REPEAT .05
36
increment_cb()37 void Fl_Scrollbar::increment_cb() {
38 int ls = maximum()>=minimum() ? linesize_ : -linesize_;
39 int i;
40 switch (pushed_) {
41 case 1:
42 i = -ls;
43 break;
44 default:
45 i = ls;
46 break;
47 case 5:
48 i = -int((maximum()-minimum())*slider_size()/(1.0-slider_size())) + ls;
49 if (i > -ls) i = -ls;
50 break;
51 case 6:
52 i = int((maximum()-minimum())*slider_size()/(1.0-slider_size())) - ls;
53 if (i < ls) i = ls;
54 break;
55 }
56 handle_drag(clamp(value() + i));
57 }
58
timeout_cb(void * v)59 void Fl_Scrollbar::timeout_cb(void* v) {
60 Fl_Scrollbar* s = (Fl_Scrollbar*)v;
61 s->increment_cb();
62 Fl::add_timeout(REPEAT, timeout_cb, s);
63 }
64
handle(int event)65 int Fl_Scrollbar::handle(int event) {
66 // area of scrollbar:
67 int area;
68 int X=x(); int Y=y(); int W=w(); int H=h();
69
70 // adjust slider area to be inside the arrow buttons:
71 if (horizontal()) {
72 if (W >= 3*H) {X += H; W -= 2*H;}
73 } else {
74 if (H >= 3*W) {Y += W; H -= 2*W;}
75 }
76
77 // which widget part is highlighted?
78 int relx;
79 int ww;
80 if (horizontal()) {
81 relx = Fl::event_x()-X;
82 ww = W;
83 } else {
84 relx = Fl::event_y()-Y;
85 ww = H;
86 }
87 if (relx < 0) area = 1;
88 else if (relx >= ww) area = 2;
89 else {
90 int S = int(slider_size()*ww+.5);
91 int T = (horizontal() ? H : W)/2+1;
92 if (type()==FL_VERT_NICE_SLIDER || type()==FL_HOR_NICE_SLIDER) T += 4;
93 if (S < T) S = T;
94 double val =
95 (maximum()-minimum()) ? (value()-minimum())/(maximum()-minimum()) : 0.5;
96 int sliderx;
97 if (val >= 1.0) sliderx = ww-S;
98 else if (val <= 0.0) sliderx = 0;
99 else sliderx = int(val*(ww-S)+.5);
100 if (Fl::event_button() == FL_MIDDLE_MOUSE) area = 8;
101 else if (relx < sliderx) area = 5;
102 else if (relx >= sliderx+S) area = 6;
103 else area = 8;
104 }
105
106 switch (event) {
107 case FL_ENTER:
108 case FL_LEAVE:
109 return 1;
110 case FL_RELEASE:
111 damage(FL_DAMAGE_ALL);
112 if (pushed_) {
113 Fl::remove_timeout(timeout_cb, this);
114 pushed_ = 0;
115 }
116 handle_release();
117 return 1;
118 case FL_PUSH:
119 if (pushed_) return 1;
120 if (area != 8) pushed_ = area;
121 if (pushed_) {
122 handle_push();
123 Fl::add_timeout(INITIALREPEAT, timeout_cb, this);
124 increment_cb();
125 damage(FL_DAMAGE_ALL);
126 return 1;
127 }
128 return Fl_Slider::handle(event, X,Y,W,H);
129 case FL_DRAG:
130 if (pushed_) return 1;
131 return Fl_Slider::handle(event, X,Y,W,H);
132 case FL_MOUSEWHEEL :
133 if (horizontal()) {
134 if (Fl::e_dx==0) return 0;
135 handle_drag(clamp(value() + linesize_ * Fl::e_dx));
136 return 1;
137 } else {
138 if (Fl::e_dy==0) return 0;
139 handle_drag(clamp(value() + linesize_ * Fl::e_dy));
140 return 1;
141 }
142 case FL_SHORTCUT:
143 case FL_KEYBOARD: {
144 int v = value();
145 int ls = maximum()>=minimum() ? linesize_ : -linesize_;
146 if (horizontal()) {
147 switch (Fl::event_key()) {
148 case FL_Left:
149 v -= ls;
150 break;
151 case FL_Right:
152 v += ls;
153 break;
154 default:
155 return 0;
156 }
157 } else { // vertical
158 switch (Fl::event_key()) {
159 case FL_Up:
160 v -= ls;
161 break;
162 case FL_Down:
163 v += ls;
164 break;
165 case FL_Page_Up:
166 if (slider_size() >= 1.0) return 0;
167 v -= int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
168 v += ls;
169 break;
170 case FL_Page_Down:
171 if (slider_size() >= 1.0) return 0;
172 v += int((maximum()-minimum())*slider_size()/(1.0-slider_size()));
173 v -= ls;
174 break;
175 case FL_Home:
176 v = int(minimum());
177 break;
178 case FL_End:
179 v = int(maximum());
180 break;
181 default:
182 return 0;
183 }
184 }
185 v = int(clamp(v));
186 if (v != value()) {
187 Fl_Slider::value(v);
188 value_damage();
189 set_changed();
190 do_callback();
191 }
192 return 1;}
193 }
194 return 0;
195 }
196
draw()197 void Fl_Scrollbar::draw() {
198 if (damage()&FL_DAMAGE_ALL) draw_box();
199 int X = x()+Fl::box_dx(box());
200 int Y = y()+Fl::box_dy(box());
201 int W = w()-Fl::box_dw(box());
202 int H = h()-Fl::box_dh(box());
203 if (horizontal()) {
204 if (W < 3*H) {Fl_Slider::draw(X,Y,W,H); return;}
205 Fl_Slider::draw(X+H,Y,W-2*H,H);
206 if (damage()&FL_DAMAGE_ALL) {
207 draw_box((pushed_==1) ? fl_down(slider()) : slider(),
208 X, Y, H, H, selection_color());
209 draw_box((pushed_==2) ? fl_down(slider()) : slider(),
210 X+W-H, Y, H, H, selection_color());
211 if (active_r())
212 fl_color(labelcolor());
213 else
214 fl_color(fl_inactive(labelcolor()));
215 int w1 = (H-4)/3; if (w1 < 1) w1 = 1;
216 int x1 = X+(H-w1-1)/2;
217 int yy1 = Y+(H-2*w1-1)/2;
218 if (Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
219 fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1-1, yy1+w1, x1+w1, yy1);
220 x1 += (W-H);
221 fl_polygon(x1, yy1, x1+1, yy1+w1, x1, yy1+2*w1, x1+w1, yy1+w1);
222 } else {
223 fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1, yy1);
224 x1 += (W-H);
225 fl_polygon(x1, yy1, x1, yy1+2*w1, x1+w1, yy1+w1);
226 }
227 }
228 } else { // vertical
229 if (H < 3*W) {Fl_Slider::draw(X,Y,W,H); return;}
230 Fl_Slider::draw(X,Y+W,W,H-2*W);
231 if (damage()&FL_DAMAGE_ALL) {
232 draw_box((pushed_==1) ? fl_down(slider()) : slider(),
233 X, Y, W, W, selection_color());
234 draw_box((pushed_==2) ? fl_down(slider()) : slider(),
235 X, Y+H-W, W, W, selection_color());
236 if (active_r())
237 fl_color(labelcolor());
238 else
239 fl_color(fl_inactive(labelcolor()));
240 int w1 = (W-4)/3; if (w1 < 1) w1 = 1;
241 int x1 = X+(W-2*w1-1)/2;
242 int yy1 = Y+(W-w1-1)/2;
243 if (Fl::scheme_ && !strcmp(Fl::scheme_, "gtk+")) {
244 fl_polygon(x1, yy1+w1, x1+w1, yy1+w1-1, x1+2*w1, yy1+w1, x1+w1, yy1);
245 yy1 += H-W;
246 fl_polygon(x1, yy1, x1+w1, yy1+1, x1+w1, yy1+w1);
247 fl_polygon(x1+w1, yy1+1, x1+2*w1, yy1, x1+w1, yy1+w1);
248 } else {
249 fl_polygon(x1, yy1+w1, x1+2*w1, yy1+w1, x1+w1, yy1);
250 yy1 += H-W;
251 fl_polygon(x1, yy1, x1+w1, yy1+w1, x1+2*w1, yy1);
252 }
253 }
254 }
255 }
256
Fl_Scrollbar(int X,int Y,int W,int H,const char * L)257 Fl_Scrollbar::Fl_Scrollbar(int X, int Y, int W, int H, const char* L)
258 : Fl_Slider(X, Y, W, H, L)
259 {
260 box(FL_FLAT_BOX);
261 color(FL_DARK2);
262 slider(FL_UP_BOX);
263 linesize_ = 16;
264 pushed_ = 0;
265 step(1);
266 }
267
~Fl_Scrollbar()268 Fl_Scrollbar::~Fl_Scrollbar()
269 {
270 if (pushed_)
271 Fl::remove_timeout(timeout_cb, this);
272 }
273
274
275 //
276 // End of "$Id: Fl_Scrollbar.cxx 6042 2008-02-25 13:00:53Z matt $".
277 //
278