diff --git a/DPM.C b/DPM.C index dae915f..ff14a93 100644 --- a/DPM.C +++ b/DPM.C @@ -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 #include #include @@ -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 ); */ + + } } diff --git a/DPM.H b/DPM.H index e6942f7..2ddcf85 100644 --- a/DPM.H +++ b/DPM.H @@ -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 ); + } }; diff --git a/Meter.H b/Meter.H index 38e6216..70d9e29 100644 --- a/Meter.H +++ b/Meter.H @@ -19,10 +19,14 @@ /* Base class for all meters */ +#include +#include + 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 +#include + + +/* ... 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(); } + +};