2 /*******************************************************************************/
3 /* Copyright (C) 2008 Jonathan Moore Liles */
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. */
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 */
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_Dial.H>
22 #include <FL/fl_draw.H>
29 #include <FL/Fl_Shared_Image.H>
35 Fl_Image
*original
; /* originl image */
37 Fl_Image
*scaled
; /* downscaled image */
39 class image_node
*next
;
42 static image_node
*_first
= 0;
44 int Fl_Dial::_default_style
= Fl_Dial::PLASTIC_DIAL
;
45 Fl_Image
*Fl_Dial::_default_image
= 0;
47 /** This simple box is suitable for use with knob-type widgets. It
48 * comprises a border with shadow, and a cap with glare-lines akin
49 * to those seen on burnished aluminum knobs. */
51 burnished_oval_box ( int x
, int y
, int w
, int h
, Fl_Color c
)
54 fl_color( fl_darker( c
) );
55 fl_pie( x
, y
, w
, h
, 0, 360 );
56 fl_color( fl_darker( fl_darker( c
) ) );
57 fl_pie( x
, y
, w
, h
, 180 + 215, 180 + 45 );
67 fl_pie( x
, y
, w
, h
, 0, 360 );
74 fl_color( fl_color_average( FL_WHITE
, c
, 0.15f
) );
75 fl_pie( x
, y
, w
, h
, a1
, a2
);
76 fl_pie( x
, y
, w
, h
, 180 + a1
, 180 + a2
);
77 fl_color( fl_color_average( FL_WHITE
, c
, 0.25f
) );
79 const int d
= (a2
- a1
) / 2;
80 fl_pie( x
, y
, w
, h
, a1
+ (d
/ 2), a2
- (d
/ 2) );
81 fl_pie( x
, y
, w
, h
, 180 + a1
+ (d
/ 2), 180 + a2
- (d
/ 2) );
88 Fl_Dial::draw_box ( void )
92 static Fl_Widget
*_mouse_inside
= NULL
;
95 Fl_Dial::handle ( int m
)
97 /* Fl_Dial and friends should really handle mousewheel, but they don't in FTLK1 */
102 _mouse_inside
= this;
104 return Fl_Dial_Base::handle(m
) || 1;
106 _mouse_inside
= NULL
;
108 return Fl_Dial_Base::handle(m
) || 1;
111 if ( this != Fl::belowmouse() )
116 const int steps
= Fl::event_ctrl() ? 128 : 16;
118 const float step
= fabs( maximum() - minimum() ) / (float)steps
;
122 /* slider is in 'upside down' configuration, invert meaning of mousewheel */
123 if ( maximum() > minimum() )
126 handle_drag(clamp(value() + step
* dy
));
133 get_knob_dimensions ( &X
, &Y
, &S
);
135 return Fl_Dial_Base::handle( m
, X
, Y
, S
, S
);
139 Fl_Dial::draw ( void )
143 get_knob_dimensions ( &X
, &Y
, &S
);
148 double angle
= ( angle2() - angle1() ) * ( value() - minimum()) / ( maximum() - minimum() ) + angle1();
152 if ( t
== PIXMAP_DIAL
)
154 Fl_Image
*im
= pixmap();
157 im
= Fl_Dial::_default_image
;
161 fl_push_clip( x(), y(), w(), h() );
163 int knob_width
= im
->h();
164 const int frames
= im
->w() / im
->h();
166 const int index
= (int)( ( frames
- 1 ) * ( value() - minimum()) / ( maximum() - minimum() ));
168 /* if ( ( damage() == FL_DAMAGE_ALL ) || */
169 /* ( ( damage() & FL_DAMAGE_EXPOSE ) && */
170 /* index != _last_pixmap_index ) ) */
173 /* FIXME: Why doesn't this work? */
174 /* if ( ! active_r() ) */
176 /* im->inactive(); */
179 if ( w() >= knob_width
)
181 im
->draw( x() + ( w() / 2 ) - ( knob_width
/ 2 ),
182 y() + ( h() / 2 ) - ( knob_width
/ 2 ),
190 // while ( knob_width > w() )
195 Fl_Image
*scaled
= 0;
197 for ( i
= _first
; i
; i
= i
->next
)
199 if ( i
->original
== im
&&
200 i
->scaled
&& i
->scaled
->h() == knob_width
)
209 scaled
= im
->copy( knob_width
* frames
, knob_width
);
211 i
= new image_node();
219 scaled
->draw( x() + ( w() / 2 ) - ( knob_width
/ 2 ),
220 y() + ( h() / 2 ) - ( knob_width
/ 2 ),
227 _last_pixmap_index
= index
;
235 /* draw as plastic dial instead when image is missing */
241 /* fl_line_style( FL_SOLID, 0 ); */
242 if ( type() == ARC_DIAL
)
243 fl_draw_box( box(), X
, Y
, S
, S
, color() );
250 fl_line_style( FL_SOLID
, S
/ 6 );
253 fl_color( fl_darker( color() ) );
254 fl_arc( X
, Y
, S
, S
, 270 - angle1(), 270 - angle2() );
257 fl_color( selection_color() );
258 fl_arc( X
, Y
, S
, S
, 270 - angle1(), 270 - angle
);
260 fl_line_style( FL_SOLID
, 0 );
262 fl_color( fl_contrast( labelcolor(), color() ) );
264 else if ( t
== PLASTIC_DIAL
|| t
== BURNISHED_DIAL
)
268 draw_cursor( X
, Y
, S
);
273 if ( _mouse_inside
== this )
275 /* TODO: Make this optional */
278 fl_font( FL_HELVETICA
, 10 );
283 snprintf( s
, sizeof( s
), buf
, value() );
285 fl_color( FL_FOREGROUND_COLOR
);
286 fl_draw( s
, X
, Y
, S
, S
, FL_ALIGN_CENTER
);
291 Fl_Dial::get_knob_dimensions ( int *X
, int *Y
, int *S
)
293 int ox
, oy
, ww
, hh
, side
;
302 ox
= ox
+ (ww
- side
) / 2;
307 oy
= oy
+ (hh
- side
) / 2;
309 side
= w() > h() ? hh
: ww
;
317 Fl_Dial::draw_cursor ( int ox
, int oy
, int side
)
321 // fl_color(fl_color_average(FL_BACKGROUND_COLOR, FL_BLACK, .7f));
323 angle
= ( angle2() - angle1() ) * ( value() - minimum()) / ( maximum() - minimum() ) + angle1();
325 fl_color( fl_contrast( selection_color(), FL_BACKGROUND_COLOR
) );
327 fl_line_style( FL_SOLID
, side
/ 8 );
331 /* account for edge conditions */
332 angle
= angle
< angle1() + d
? angle1() + d
: angle
;
333 angle
= angle
> angle2() - d
? angle2() - d
: angle
;
337 side
-= side
* 0.15 * 2;
339 fl_arc( ox
, oy
, side
, side
, 270 - (angle
- d
), 270 - (angle
+ d
) );
340 // fl_arc( ox, oy, side, side, 270 - (angle + d), 270 - (angle - d) );
342 fl_line_style( FL_SOLID
, 0 );
346 Fl_Dial::draw_knob ( int type
)
348 int ox
, oy
, ww
, hh
, side
;
350 get_knob_dimensions ( &ox
, &oy
, &side
);
355 fl_clip(ox
, oy
, ww
, hh
);
360 /* fl_color(FL_BACKGROUND_COLOR); */
361 /* fl_rectf(ox, oy, side, side); */
364 if ( damage() & FL_DAMAGE_ALL
)
366 fl_color(fl_color_average(color(), FL_BACKGROUND2_COLOR
, .6));
368 fl_pie(ox
+ 1, oy
+ 3, side
- 2, side
- 12, 0, 360);
372 draw_scale(ox
, oy
, side
);
375 Fl_Color c
= active_r() ? fl_color_average(FL_BACKGROUND_COLOR
, FL_WHITE
, .7) : FL_INACTIVE_COLOR
;
377 if ( type
== BURNISHED_DIAL
)
379 burnished_oval_box( ox
+ o
, oy
+ o
, side
- (o
*2), side
- (o
*2), c
);
384 fl_color(FL_BACKGROUND_COLOR
);
386 fl_pie(ox
+ o
, oy
+ o
, side
- (o
*2), side
- (o
*2), 0, 360);
390 fl_color(fl_color_average(FL_BACKGROUND_COLOR
, FL_BLACK
, .8f
));
391 fl_pie(ox
+ o
+ 2, oy
+ o
+ 3, side
- o
*2, side
- o
*2, 0, 360);
392 /* fl_color(fl_color_average(FL_BACKGROUND_COLOR, FL_BLACK, .2f)); */
393 /* fl_pie(ox + o + 4, oy + o + 5, side - o*2, side - o*2, 0, 360); */
398 fl_arc(ox
+ o
, oy
+ o
, side
- o
*2, side
- o
*2, 0, 360);
400 fl_color(fl_color_average(FL_BACKGROUND_COLOR
, FL_WHITE
, .6));
402 fl_pie(ox
+ o
, oy
+ o
, side
- o
*2, side
- o
*2, 0, 360);
410 Fl_Dial::draw_scale ( int ox
, int oy
, int side
)
412 float x1
, y1
, x2
, y2
, rds
, cx
, cy
, ca
, sa
;
416 if (_scaleticks
== 0)
418 double a_step
= (10.0 * 3.14159 / 6.0) / _scaleticks
;
419 double a_orig
= -(3.14159 / 3.0);
420 for (int a
= 0; a
<= _scaleticks
; a
++)
422 double na
= a_orig
+ a
* a_step
;
425 x1
= cx
+ (rds
) * ca
;
426 y1
= cy
- (rds
) * sa
;
427 x2
= cx
+ (rds
- 6) * ca
;
428 y2
= cy
- (rds
- 6) * sa
;
429 fl_color(FL_BACKGROUND_COLOR
);
430 fl_line(x1
, y1
, x2
, y2
);
435 Fl_Dial::scaleticks ( int tck
)
440 if (_scaleticks
> 31)
443 damage(FL_DAMAGE_ALL
);