themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_Scrollbar.cxx
blob2c2724896609841d808937cf57c52643650baa55
1 //
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.
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
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
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"
35 #define INITIALREPEAT .5
36 #define REPEAT .05
38 void 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
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
64 break;
66 handle_drag(clamp(value() + i));
69 void 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);
75 int 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();
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;}
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;
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;
116 switch (event) {
117 case FL_ENTER:
118 case FL_LEAVE:
119 return 1;
120 case FL_RELEASE:
121 redraw();
122 if (pushed_) {
123 Fl::remove_timeout(timeout_cb, this);
124 pushed_ = 0;
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 redraw();
136 return 1;
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;
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;
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;
197 v = int(clamp(v));
198 if (v != value()) {
199 Fl_Slider::value(v);
200 value_damage();
201 set_changed();
202 do_callback();
204 return 1;}
206 return 0;
209 void 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);
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);
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.
273 Fl_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);
283 /** Destroys the Scrollbar. */
284 Fl_Scrollbar::~Fl_Scrollbar() {
285 if (pushed_)
286 Fl::remove_timeout(timeout_cb, this);
291 // End of "$Id: Fl_Scrollbar.cxx 7903 2010-11-28 21:06:39Z matt $".