non/FL/Fl_Arc_Dial.C

333 lines
8.5 KiB
C
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*******************************************************************************/
/* Copyright (C) 2008 Jonathan Moore Liles */
/* */
/* This program is free software; you can redistribute it and/or modify it */
/* under the terms of the GNU General Public License as published by the */
/* Free Software Foundation; either version 2 of the License, or (at your */
/* option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
/* more details. */
/* */
/* You should have received a copy of the GNU General Public License along */
/* with This program; see the file COPYING. If not,write to the Free Software */
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*******************************************************************************/
#include "Fl_Arc_Dial.H"
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <algorithm>
int Fl_Arc_Dial::_default_style = Fl_Arc_Dial::PLASTIC_DIAL;
/** This simple box is suitable for use with knob-type widgets. It
* comprises a border with shadow, and a cap with glare-lines akin
* to those seen on burnished aluminum knobs. */
static void
burnished_oval_box ( int x, int y, int w, int h, Fl_Color c )
{
/* draw background */
fl_color( fl_darker( c ) );
fl_pie( x, y, w, h, 0, 360 );
fl_color( fl_darker( fl_darker( c ) ) );
fl_pie( x, y, w, h, 180 + 215, 180 + 45 );
/* shrink */
x += 4;
y += 4;
w -= 7;
h -= 7;
/* draw cap */
fl_color( c );
fl_pie( x, y, w, h, 0, 360 );
/* draw glare */
const int a1 = 10;
const int a2 = 90;
fl_color( fl_color_average( FL_WHITE, c, 0.15f ) );
fl_pie( x, y, w, h, a1, a2 );
fl_pie( x, y, w, h, 180 + a1, 180 + a2 );
fl_color( fl_color_average( FL_WHITE, c, 0.25f ) );
const int d = (a2 - a1) / 2;
fl_pie( x, y, w, h, a1 + (d / 2), a2 - (d / 2) );
fl_pie( x, y, w, h, 180 + a1 + (d / 2), 180 + a2 - (d / 2) );
}
void
Fl_Arc_Dial::draw_box ( void )
{
}
int
Fl_Arc_Dial::handle ( int m )
{
/* Fl_Dial and friends should really handle mousewheel, but they don't in FTLK1 */
switch ( m )
{
case FL_MOUSEWHEEL:
{
if ( this != Fl::belowmouse() )
return 0;
int steps = 16;
if ( Fl::event_ctrl() )
steps = 128;
float step = fabs( maximum() - minimum() ) / (float)steps;
float d = ((float)Fl::event_dy()) * step;
double v = value() + d;
if ( maximum() > minimum() )
{
if ( v < minimum() )
v = minimum();
else if ( v > maximum() )
v = maximum();
}
else
{
if ( v > minimum() )
v = minimum();
else if ( v < maximum() )
v = maximum();
}
value( v );
do_callback();
return 1;
}
}
int X, Y, S;
get_knob_dimensions ( &X, &Y, &S );
return Fl_Dial::handle( m, X, Y, S, S );
}
void
Fl_Arc_Dial::draw ( void )
{
int X, Y, S;
get_knob_dimensions ( &X, &Y, &S);
draw_box();
draw_label();
double angle = ( angle2() - angle1() ) * ( value() - minimum()) / ( maximum() - minimum() ) + angle1();
if ( type() == ARC_DIAL )
{
/* fl_line_style( FL_SOLID, 0 ); */
if ( type() == ARC_DIAL )
fl_draw_box( FL_ROUNDED_BOX, X, Y, S, S, color() );
/* shrink a bit */
X += S / 8.0;
Y += S / 8.0;
S -= S / 4;
fl_line_style( FL_SOLID, S / 6 );
/* background arc */
fl_color( fl_darker( color() ) );
fl_arc( X, Y, S, S, 270 - angle1(), 270 - angle2() );
/* foreground arc */
fl_color( selection_color() );
fl_arc( X, Y, S, S, 270 - angle1(), 270 - angle );
fl_line_style( FL_SOLID, 0 );
fl_color( fl_contrast( labelcolor(), color() ) );
}
else if ( type() == PLASTIC_DIAL || type() == BURNISHED_DIAL )
{
draw_knob();
draw_cursor( X, Y, S);
}
/* Some strange bug in FLTK prevents us from always been able to draw text
* here, so don't even try for now. */
/* char s[10]; */
/* fl_font( FL_HELVETICA, 8 ); */
/* snprintf( s, sizeof( s ), "%.1f", value() ); */
/* /\* fl_rectf( X, Y + S, S, 14, FL_BACKGROUND2_COLOR ); *\/ */
/* fl_color( FL_WHITE ); */
/* fl_draw( s, X, Y + S, S, 14, FL_ALIGN_CENTER ); */
}
void
Fl_Arc_Dial::get_knob_dimensions ( int *X, int *Y, int *S )
{
int ox, oy, ww, hh, side;
ox = x();
oy = y();
ww = w();
hh = h();
if (ww > hh)
{
side = hh;
ox = ox + (ww - side) / 2;
}
else
{
side = ww;
oy = oy + (hh - side) / 2;
}
side = w() > h() ? hh : ww;
*X = ox;
*Y = oy;
*S = side;
}
void
Fl_Arc_Dial::draw_cursor ( int ox, int oy, int side )
{
double angle;
// fl_color(fl_color_average(FL_BACKGROUND_COLOR, FL_BLACK, .7f));
angle = ( angle2() - angle1() ) * ( value() - minimum()) / ( maximum() - minimum() ) + angle1();
fl_color( fl_contrast( selection_color(), FL_BACKGROUND_COLOR ) );
fl_line_style( FL_SOLID, side / 8 );
const int d = 6;
/* account for edge conditions */
angle = angle < angle1() + d ? angle1() + d : angle;
angle = angle > angle2() - d ? angle2() - d : angle;
ox += side / 4;
oy += side / 4;
side -= side / 2;
fl_arc( ox, oy, side, side, 270 - (angle - d), 270 - (angle + d) );
fl_line_style( FL_SOLID, 0 );
}
void
Fl_Arc_Dial::draw_knob ( void )
{
int ox, oy, ww, hh, side;
get_knob_dimensions ( &ox, &oy, &side );
ww = w();
hh = h();
draw_label();
fl_clip(ox, oy, ww, hh);
// background
/* fl_color(FL_BACKGROUND_COLOR); */
/* fl_rectf(ox, oy, side, side); */
/* scale color */
fl_color(fl_color_average(color(), FL_BACKGROUND2_COLOR, .6));
fl_pie(ox + 1, oy + 3, side - 2, side - 12, 0, 360);
// scale
draw_scale(ox, oy, side);
Fl_Color c = active_r() ? fl_color_average(FL_BACKGROUND_COLOR, FL_WHITE, .7) : FL_INACTIVE_COLOR;
if ( type() == BURNISHED_DIAL )
{
burnished_oval_box( ox + 5, oy + 5, side - 12, side - 12, c );
}
else
{
fl_color(FL_BACKGROUND_COLOR);
fl_pie(ox + 6, oy + 6, side - 12, side - 12, 0, 360);
// shadow
fl_color(fl_color_average(FL_BACKGROUND_COLOR, FL_BLACK, .8f));
fl_pie(ox + 8, oy + 12, side - 16, side - 16, 0, 360);
fl_color(fl_color_average(FL_BACKGROUND_COLOR, FL_BLACK, .2f));
fl_pie(ox + 9, oy + 12, side - 18, side - 18, 0, 360);
// knob edge
fl_color( c);
fl_pie(ox + 8, oy + 8, side - 16, side - 16, 0, 360);
fl_color(fl_color_average(FL_BACKGROUND_COLOR, FL_WHITE, .6));
fl_pie(ox + 10, oy + 10, side - 20, side - 20, 0, 360);
}
fl_pop_clip();
}
void
Fl_Arc_Dial::draw_scale ( int ox, int oy, int side )
{
float x1, y1, x2, y2, rds, cx, cy, ca, sa;
rds = side / 2;
cx = ox + side / 2;
cy = oy + side / 2;
if (_scaleticks == 0)
return;
double a_step = (10.0 * 3.14159 / 6.0) / _scaleticks;
double a_orig = -(3.14159 / 3.0);
for (int a = 0; a <= _scaleticks; a++)
{
double na = a_orig + a * a_step;
ca = cos(na);
sa = sin(na);
x1 = cx + (rds) * ca;
y1 = cy - (rds) * sa;
x2 = cx + (rds - 6) * ca;
y2 = cy - (rds - 6) * sa;
fl_color(FL_BACKGROUND_COLOR);
fl_line(x1, y1, x2, y2);
}
}
void
Fl_Arc_Dial::scaleticks ( int tck )
{
_scaleticks = tck;
if (_scaleticks < 0)
_scaleticks = 0;
if (_scaleticks > 31)
_scaleticks = 31;
if (visible())
damage(FL_DAMAGE_ALL);
}