| @@ -24,6 +24,11 @@ | |||
| #include "DPM.H" | |||
| /* we cache the gradient for (probably excessive) speed */ | |||
| float DPM::_dim; | |||
| Fl_Color DPM::_gradient[128] = { (Fl_Color)-1 }; | |||
| Fl_Color DPM::_dim_gradient[128]; | |||
| #include <FL/Fl.H> | |||
| #include <FL/fl_draw.H> | |||
| #include <FL/Fl_Group.H> | |||
| @@ -34,13 +39,14 @@ | |||
| DPM::DPM ( int X, int Y, int W, int H, const char *L ) : | |||
| Meter( X, Y, W, H, L ) | |||
| { | |||
| divisions( 64 ); | |||
| segments( 64 ); | |||
| type( FL_VERTICAL ); | |||
| dim( 0.80f ); | |||
| dim( 0.70f ); | |||
| min_color( fl_darker( FL_GREEN ) ); | |||
| max_color( FL_RED ); | |||
| /* initialize gradients */ | |||
| if ( DPM::_gradient[ 0 ] == -1 ) | |||
| DPM::blend( FL_GREEN, FL_RED ); | |||
| box( FL_ROUNDED_BOX ); | |||
| } | |||
| @@ -72,32 +78,60 @@ DPM::draw_label ( void ) | |||
| void | |||
| DPM::draw ( void ) | |||
| { | |||
| // draw_box( FL_FLAT_BOX, x(), y(), w(), h(), color() ); | |||
| int v = pos( value() ); | |||
| int pv = pos( peak() ); | |||
| int bh = h() / _divisions; | |||
| int bw = w() / _divisions; | |||
| int bh = h() / _segments; | |||
| int bw = w() / _segments; | |||
| if ( damage() & FL_DAMAGE_ALL ) | |||
| if ( damage() == FL_DAMAGE_ALL ) | |||
| draw_label(); | |||
| for ( int p = _divisions; p > 0; p-- ) | |||
| const int active = active_r(); | |||
| int hi, lo; | |||
| /* only draw as many segments as necessary */ | |||
| if ( damage() == FL_DAMAGE_USER1 ) | |||
| { | |||
| // Fl_Color c = fl_color_average( _min_color, _max_color, ((30.0f * log10f( (float)(_divisions - p ) ) )) / _divisions ); | |||
| Fl_Color c = fl_color_average( _max_color, _min_color, (float) p / _divisions ); | |||
| if ( old_value() > value() ) | |||
| { | |||
| hi = pos( old_value() ); | |||
| lo = v; | |||
| } | |||
| else | |||
| { | |||
| hi = v; | |||
| lo = pos( old_value() ); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| lo = 0; | |||
| hi = _segments; | |||
| } | |||
| for ( int p = hi; p > lo; p-- ) | |||
| { | |||
| Fl_Color c = DPM::div_color( p ); | |||
| if ( p > v && p != pv ) | |||
| // c = fl_color_average( color(), c, _dim ); | |||
| c = fl_color_average( FL_BLACK, c, _dim ); | |||
| c = dim_div_color( p ); | |||
| if ( ! active_r() ) | |||
| if ( ! active ) | |||
| c = fl_inactive( c ); | |||
| if ( type() == FL_HORIZONTAL ) | |||
| draw_box( box(), x() + (p * bw), y(), bw, h(), c ); | |||
| fl_draw_box( box(), x() + (p * bw), y(), bw, h(), c ); | |||
| else | |||
| draw_box( box(), x(), y() + h() - (p * bh), w(), bh, c ); | |||
| } | |||
| fl_draw_box( box(), x(), y() + h() - (p * bh), w(), bh, c ); | |||
| /* fl_color( c ); */ | |||
| /* fl_rectf( x(), y() + h() - (p * bh), w(), bh ); */ | |||
| /* fl_color( FL_BLACK ); */ | |||
| /* fl_rect( x(), y() + h() - (p * bh), w(), bh ); */ | |||
| } | |||
| } | |||
| @@ -26,17 +26,31 @@ | |||
| class DPM : public Meter | |||
| { | |||
| int _divisions; | |||
| float _dim; | |||
| int _segments; | |||
| Fl_Color _min_color; | |||
| Fl_Color _max_color; | |||
| int pos ( float v ) | |||
| { | |||
| return deflection( v ) * _divisions; | |||
| return deflection( v ) * _segments; | |||
| } | |||
| static float _dim; | |||
| static Fl_Color _gradient[]; | |||
| static Fl_Color _dim_gradient[]; | |||
| Fl_Color | |||
| div_color ( int i ) | |||
| { | |||
| return _gradient[ i * 127 / _segments ]; | |||
| } | |||
| Fl_Color | |||
| dim_div_color ( int i ) | |||
| { | |||
| return _dim_gradient[ i * 127 / _segments ]; | |||
| } | |||
| protected: | |||
| virtual void draw_label ( void ); | |||
| @@ -48,16 +62,20 @@ public: | |||
| // void value ( float v ) { if ( pos( v ) != pos( value() ) ) redraw(); Meter::value( v ) } | |||
| bool divisions ( void ) const { return _divisions; } | |||
| void divisions ( int v ) { _divisions = v; } | |||
| bool segments ( void ) const { return _segments; } | |||
| void segments ( int v ) { _segments = v; } | |||
| float dim ( void ) const { return _dim; } | |||
| void dim ( float v ) { _dim = v; redraw(); } | |||
| Fl_Color min_color ( void ) const { return _min_color; } | |||
| void min_color ( Fl_Color v ) { _min_color = v; } | |||
| Fl_Color max_color ( void ) const { return _max_color; } | |||
| void max_color ( Fl_Color v ) { _max_color = v; } | |||
| static | |||
| void | |||
| blend ( Fl_Color min, Fl_Color max ) | |||
| { | |||
| for ( int i = 128; i-- ; ) | |||
| _gradient[ i ] = fl_color_average( max, min, i / (float)128 ); | |||
| for ( int i = 128; i-- ; ) | |||
| _dim_gradient[ i ] = fl_color_average( FL_BLACK, _gradient[ i ], _dim ); | |||
| } | |||
| }; | |||
| @@ -19,10 +19,14 @@ | |||
| /* Base class for all meters */ | |||
| #include <FL/Fl.H> | |||
| #include <FL/Fl_Widget.H> | |||
| class Meter : public Fl_Widget | |||
| { | |||
| float _peak; | |||
| float _old_value; | |||
| float _value; | |||
| protected: | |||
| @@ -31,7 +35,12 @@ protected: | |||
| virtual int handle ( int m ) | |||
| { | |||
| if ( m == FL_PUSH ) | |||
| reset(); | |||
| { | |||
| // if ( Fl::event_button3() ) | |||
| // hide(); | |||
| // else | |||
| reset(); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -61,22 +70,31 @@ protected: | |||
| return def / 115.0f; | |||
| } | |||
| float old_value ( void ) const { return _old_value; } | |||
| public: | |||
| Meter ( int X, int Y, int W, int H, const char *L = 0 ) : | |||
| Fl_Widget( X, Y, W, H, L ) | |||
| { | |||
| _peak = _value = -80.0f; | |||
| _old_value = 4.0f; | |||
| } | |||
| virtual ~Meter ( ) { } | |||
| void value ( float v ) | |||
| { | |||
| _value = v; | |||
| if ( _value != v ) | |||
| { | |||
| damage( FL_DAMAGE_USER1 ); | |||
| _old_value = _value; | |||
| _value = v; | |||
| if ( _value > _peak ) | |||
| _peak = _value; | |||
| if ( _value > _peak ) | |||
| _peak = _value; | |||
| } | |||
| } | |||
| float value ( void ) const { return _value; } | |||
| @@ -85,3 +103,33 @@ public: | |||
| void reset ( void ) { _peak = -80.0f; redraw(); } | |||
| }; | |||
| #include <FL/Fl_Group.H> | |||
| #include <stdio.h> | |||
| /* ... Extension methods for any group containing only meters. Access | |||
| * via a cast to (Meter_Pack *) */ | |||
| class Meter_Pack : public Fl_Group | |||
| { | |||
| public: | |||
| /** return a pointer to the meter for channel /c/ in group of meters /g/ */ | |||
| Meter * | |||
| channel ( int c ) | |||
| { | |||
| if ( c > children() ) | |||
| { | |||
| fprintf( stderr, "no such channel\n" ); | |||
| return NULL; | |||
| } | |||
| return (Meter *)child( c ); | |||
| } | |||
| int | |||
| channels ( void ) const { return children(); } | |||
| }; | |||