themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_Panzoomer.cxx
blob6b21c98eb305a20107d5c8ca9155d96f4b17c4b1
2 /*******************************************************************************/
3 /* Copyright (C) 2012 Jonathan Moore Liles */
4 /* */
5 /* This program is free software; you can redistribute it and/or modify it */
6 /* under the terms of the GNU General Public License as published by the */
7 /* Free Software Foundation; either version 2 of the License, or (at your */
8 /* option) any later version. */
9 /* */
10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
12 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
13 /* more details. */
14 /* */
15 /* You should have received a copy of the GNU General Public License along */
16 /* with This program; see the file COPYING. If not,write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /*******************************************************************************/
20 #include <FL/Fl.H>
21 #include <FL/fl_draw.H>
22 #include <FL/Fl_Panzoomer.H>
24 Fl_Panzoomer::Fl_Panzoomer ( int X, int Y, int W, int H, const char *L ) :
25 Fl_Valuator( X,Y,W,H,L )
27 _zoom = 1;
28 _zoom_min = 0;
29 _zoom_max = 4;
30 _zoom_changed = false;
32 _ymin = _ymax = _xmin = _xmax = _ysize = _xsize =
33 _xpos = _ypos = 0;
35 step( 1 );
38 int
39 Fl_Panzoomer::x_value ( int pos, int size, int first, int total )
41 if ( pos + size > first + total )
42 total = pos+size-first;
44 if ( (int)_xmin == first &&
45 (int)_xmax == total &&
46 (int)_xpos == pos &&
47 (int)_xsize == size )
48 return pos;
50 damage( FL_DAMAGE_USER1 );
52 _xmin = first;
53 _xmax = total;
54 _xpos = pos;
55 _xsize = size;
57 return pos;
60 int
61 Fl_Panzoomer::y_value ( int pos, int size, int first, int total )
63 if ( pos + size > first + total )
64 total = pos+size-first;
66 if ( (int)_ymin == first &&
67 (int)_ymax == total &&
68 (int)_ypos == pos &&
69 (int)_ysize == size )
70 return pos;
72 damage( FL_DAMAGE_USER1 );
74 _ymin = first;
75 _ymax = total;
76 _ypos = pos;
77 _ysize = size;
79 return pos;
82 void
83 Fl_Panzoomer::x_value ( double v )
85 if ( _xpos == v )
86 return;
88 _xpos = v;
89 if ( _xpos < _xmin )
90 _xpos = _xmin;
91 else if ( _xpos > _xmax - _xsize)
92 _xpos = _xmax - _xsize;
94 damage( FL_DAMAGE_USER1 );
97 void
98 Fl_Panzoomer::y_value ( double v )
100 if ( _ypos == v )
101 return;
103 _ypos = v;
105 if ( _ypos < _ymin )
106 _ypos = _ymin;
107 else if ( _ypos > _ymax - _ysize )
108 _ypos = _ymax - _ysize;
110 damage( FL_DAMAGE_USER1 );
113 void
114 Fl_Panzoomer::zoom ( int v )
116 int z = _zoom;
118 _zoom = v;
120 if ( _zoom > _zoom_max )
121 _zoom = _zoom_max;
122 else
123 if ( _zoom < _zoom_min )
124 _zoom = _zoom_min;
126 if ( z != _zoom )
128 _zoom_changed = true;
129 do_callback();
130 _zoom_changed = false;
134 void
135 Fl_Panzoomer::draw ( void )
137 draw(x(),y(),w(),h());
140 void
141 Fl_Panzoomer::draw ( int X, int Y, int W, int H )
143 fl_draw_box( box(), X,Y,W,H,color());
145 X += Fl::box_dx( box() );
146 Y += Fl::box_dy( box() );
147 W -= Fl::box_dw( box() );
148 H -= Fl::box_dh( box() );
150 fl_push_clip( X,Y,W,H );
152 draw_background( X,Y,W,H );
153 draw_cursor( X,Y,W,H );
155 fl_pop_clip();
157 draw_label();
160 void
161 Fl_Panzoomer::draw_background ( int X, int Y, int W, int H )
165 void
166 Fl_Panzoomer::draw_cursor ( int X, int Y, int W, int H )
168 int cx,cy,cw,ch;
170 cx = X; cy = Y; cw = W; ch = H;
172 cursor_bounds( cx,cy,cw,ch );
174 fl_rectf( cx,cy,cw,ch,
175 fl_color_add_alpha( FL_WHITE, 40 ));
177 fl_rect( cx,cy,cw,ch,
178 fl_color_add_alpha( FL_WHITE, 200 ));
181 void
182 Fl_Panzoomer::cursor_bounds ( int &cx, int &cy, int &cw, int &ch ) const
184 const int minh = 12;
185 const int minw = 12;
187 int X,Y,W,H;
189 X = cx;
190 Y = cy;
191 W = cw;
192 H = ch;
194 double hval;
195 if ( _xmin == _xmax )
196 hval = 0.5;
197 else
199 hval = (_xpos-_xmin)/(_xmax-_xmin);
201 if (hval > 1.0) hval = 1.0;
202 else if (hval < 0.0) hval = 0.0;
205 double vval;
206 if ( _ymin == _ymax )
207 vval = 0.5;
208 else
210 vval = (_ypos-_ymin)/(_ymax-_ymin);
212 if (vval > 1.0) vval = 1.0;
213 else if (vval < 0.0) vval = 0.0;
216 cx = X + (hval) * W + .5;
217 cy = _ymax ? Y + (vval) * H + .5 : Y;
218 cw = W * (_xsize/_xmax);
219 ch = _ymax ? H * (_ysize/_ymax) : H;
221 cw = cw < minw ? minw : cw;
222 ch = ch < minh ? minh : ch;
226 Fl_Panzoomer::handle ( int m )
228 return handle( m, x(),y(),w(),h());
232 Fl_Panzoomer::handle ( int m, int X, int Y, int W, int H )
234 static int xoffset;
235 static int yoffset;
236 static bool drag;
238 X += Fl::box_dx( box() );
239 Y += Fl::box_dy( box() );
240 W -= Fl::box_dw( box() );
241 H -= Fl::box_dh( box() );
243 switch ( m )
245 case FL_ENTER:
246 case FL_LEAVE:
247 return 1;
248 case FL_PUSH:
250 int cx,cy,cw,ch;
252 cx = X; cy = Y; cw = W; ch = H;
254 cursor_bounds( cx,cy,cw,ch );
256 if ( Fl::event_inside( cx,cy,cw,ch ) )
258 xoffset = Fl::event_x() - cx;
259 yoffset = Fl::event_y() - cy;
261 else
263 xoffset = cw / 2;
264 yoffset = ch / 2;
267 if (// Fl::event_inside( cx,cy,cw,ch ) &&
268 Fl::event_button1() )
269 drag = true;
271 /* fallthrough */
272 // return 1;
274 case FL_DRAG:
276 int cx,cy,cw,ch;
278 cx = X; cy = Y; cw = W; ch = H;
280 cursor_bounds( cx,cy,cw,ch );
282 if ( drag )
284 x_value((((double)Fl::event_x() - X - xoffset) / W) * _xmax);
285 y_value( (((double)Fl::event_y() - Y - yoffset) / H) * _ymax );
287 if ( when() & FL_WHEN_CHANGED )
288 do_callback();
291 damage( FL_DAMAGE_USER1 );
293 return 1;
294 break;
296 case FL_MOUSEWHEEL:
298 const int dy = Fl::event_dy();
299 const int dx = Fl::event_dx();
301 if ( dy && Fl::event_ctrl() )
303 zoom( _zoom + dy );
305 damage( FL_DAMAGE_USER1 );
307 return 1;
310 if ( Fl::event_alt() )
311 return 0;
313 if ( Fl::event_shift())
315 if ( dx )
316 y_value( _ypos + ( (double)dx*5 / H ) * _ymax );
318 if ( dy )
319 x_value( _xpos + ( (double)dy*5 / W ) * _xmax );
321 if ( when() & FL_WHEN_CHANGED )
322 do_callback();
324 damage( FL_DAMAGE_USER1 );
326 return 1;
328 else
330 if ( dy )
331 y_value( _ypos + ( (double)dy*5 / H ) * _ymax );
333 if ( dx )
334 x_value( _xpos + ( (double)dx*5 / W ) * _xmax );
336 if ( when() & FL_WHEN_CHANGED )
337 do_callback();
339 damage( FL_DAMAGE_USER1 );
341 return 1;
344 return 0;
345 break;
347 case FL_RELEASE:
349 if ( drag )
351 drag = false;
353 if ( when() & FL_WHEN_RELEASE )
354 do_callback();
357 return 1;
359 case FL_KEYBOARD:
361 if ( Fl::event_shift() || Fl::event_ctrl() || Fl::event_alt() )
362 return 0;
364 double xv = _xpos;
365 double yv = _ypos;
367 /* FIXME: hack */
368 int xls = _xsize / 50;
369 int yls = _ysize / 50;
371 switch ( Fl::event_key() )
373 case FL_Up:
374 yv -= yls;
375 break;
376 case FL_Down:
377 yv += yls;
378 break;
379 case FL_Left:
380 xv -= xls;
381 break;
382 case FL_Right:
383 xv += xls;
384 break;
385 default:
386 return 0;
389 x_value( xv );
390 y_value( yv );
392 do_callback();
394 redraw();
396 return 1;
398 break;
402 return 0;