From ee705fffa373cd683515751866171c5a69110f6f Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Wed, 24 Feb 2010 08:58:47 -0600 Subject: [PATCH] FL/Fl_Scalepack: Give scalepack the ability contain a resizable() child. --- FL/Fl_Scalepack.C | 188 ++++++++++++++++++++++++++++++++++++++++------ FL/Fl_Scalepack.H | 2 + 2 files changed, 165 insertions(+), 25 deletions(-) diff --git a/FL/Fl_Scalepack.C b/FL/Fl_Scalepack.C index a86b985..cd6bcc4 100644 --- a/FL/Fl_Scalepack.C +++ b/FL/Fl_Scalepack.C @@ -25,16 +25,20 @@ fit itself. Of course, this only works well with highly flexible widgets, but the task comes up often enough to warrent this class. - If any child happens to be the resizable() widget, it is given half - of the available area, with the other widgets packed around it in - the remaining space. + If and child happens to be the resizable() widget, then it will be + resized so the all the other children can fit around it, with their + current sizes (and the size of the Fl_Scalepack) maintained. + NOTES: An Fl_Pack as a direct child will not work, because Fl_Pack + changes its size in draw(), which throws off our resize + calculation. The whole idea of widgets being able to resize + themselves within draw() is horribly broken... */ #include "Fl_Scalepack.H" #include - +#include #include Fl_Scalepack::Fl_Scalepack ( int X, int Y, int W, int H, const char *L ) : @@ -44,9 +48,23 @@ Fl_Scalepack::Fl_Scalepack ( int X, int Y, int W, int H, const char *L ) : _spacing = 0; } +void +Fl_Scalepack::resize ( int X, int Y, int W, int H ) +{ + /* Fl_Group's resize will change our child widget sizes, which + interferes with our own resizing method. */ + Fl_Widget::resize( X, Y, W, H ); +} + void Fl_Scalepack::draw ( void ) { + + if ( resizable() == this ) + /* this resizable( this ) is the default for Fl_Group and is + * reset by Fl_Group::clear(), but it is not our default... */ + resizable( 0 ); + int tx = x() + Fl::box_dx( box() ); int ty = y() + Fl::box_dy( box() ); int tw = w() - Fl::box_dw( box() ); @@ -54,45 +72,165 @@ Fl_Scalepack::draw ( void ) if ( damage() & FL_DAMAGE_ALL ) { - draw_box(); + if ( box() == FL_NO_BOX ) + fl_rectf( x(), y(), w(), h(), FL_BACKGROUND_COLOR ); + else + draw_box(); + draw_label(); } int v = 0; + int cth = 0; + int ctw = 0; + + Fl_Widget * const * a = array(); + for ( int i = children(); i--; ) - if ( child( i )->visible() ) + { + Fl_Widget *o = *a++; + + if ( o->visible() ) + { ++v; + if ( o != this->resizable() ) + { + cth += o->h(); + ctw += o->w(); + } + + cth += _spacing; + ctw += _spacing; + } + } + + ctw -= _spacing; + cth -= _spacing; + if ( 0 == v ) return; - int sz, pos; - - if ( type() == HORIZONTAL ) + if ( this->resizable() ) { - sz = tw / v; - pos = tw - ( tw % sz ); + int pos = 0; + + Fl_Widget * const * a = array(); + + for ( int i = children(); i--; ) + { + Fl_Widget *o = *a++; + + if ( o->visible() ) + { + int X, Y, W, H; + + if ( type() == HORIZONTAL ) + { + X = tx + pos; + Y = ty; + W = o->w(); + H = th; + } + else + { + X = tx; + Y = ty + pos; + W = tw; + H = o->h(); + } + + if ( this->resizable() == o ) + { + if ( type() == HORIZONTAL ) + W = tw - ctw - 3; + else + H = th - cth; + } + + if (X != o->x() || Y != o->y() || W != o->w() || H != o->h() ) + { + o->resize(X,Y,W,H); + o->clear_damage(FL_DAMAGE_ALL); + } + + if ( damage() & FL_DAMAGE_ALL ) + { + draw_child( *o ); + draw_outside_label( *o ); + } + else + update_child( *o ); + +/* if ( this->resizable() == o ) */ +/* fl_rect( o->x(), o->y(), o->w(), o->h(), type() == VERTICAL ? FL_GREEN : FL_BLUE ); */ + + if ( type() == HORIZONTAL ) + pos += o->w() + spacing(); + else + pos += o->h() + spacing(); + + } + } } else { - sz = th / v; - pos = th - ( th % sz ); - } + int sz = 0; + int pos = 0; - for ( int i = children(); i--; ) - if ( child( i )->visible() ) + if ( type() == HORIZONTAL ) + sz = (tw - (_spacing * (v - 1))) / v; + else + sz = (th - (_spacing * (v - 1))) / v; + + Fl_Widget * const * a = array(); + + for ( int i = children(); i--; ) { - pos -= sz; + Fl_Widget *o = *a++; - if ( type() == HORIZONTAL ) - child( i )->resize( tx + pos, ty, sz, th ); - else - child( i )->resize( tx, ty + pos, tw, sz ); + if ( o->visible() ) + { + int X, Y, W, H; - if ( damage() & FL_DAMAGE_CHILD ) - update_child( *child( i ) ); - else - draw_child( *child( i ) ); + if ( type() == HORIZONTAL ) + { + X = tx + pos; + Y = ty; + W = sz; + H = th; + } + else + { + X = tx; + Y = ty + pos; + W = tw; + H = sz; + } + + if (X != o->x() || Y != o->y() || W != o->w() || H != o->h() ) + { + o->resize(X,Y,W,H); + o->clear_damage(FL_DAMAGE_ALL); + } + + if ( damage() & FL_DAMAGE_ALL ) + { + draw_child( *o ); + draw_outside_label( *o ); + } + else + update_child( *o ); + +// fl_rect( o->x(), o->y(), o->w(), o->h(), type() == VERTICAL ? FL_RED : FL_YELLOW ); + + if ( type() == HORIZONTAL ) + pos += o->w() + spacing(); + else + pos += o->h() + spacing(); + + } } + } } diff --git a/FL/Fl_Scalepack.H b/FL/Fl_Scalepack.H index 935b578..9974bba 100644 --- a/FL/Fl_Scalepack.H +++ b/FL/Fl_Scalepack.H @@ -36,6 +36,8 @@ public: int spacing ( void ) const { return _spacing; } void spacing ( int v ) { _spacing = v; redraw(); } + virtual void resize ( int, int, int, int ); + virtual void draw ( void ); };