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