On 04/21/13 10:50, Greg Ercolano wrote: > I made one of these once; in my case I didn't use a tile, > just used a regular Fl_Group in which the widgets were positioned, > and put a thin widget between each that acted as a 'resizer' which: > > 1) enlarged/shrunk the widget above it > 2) enlarged/shrunk the parent group > 3) moved all the children below it up/down > >> +---Fl_tile-------------------+ >> | +-------------------------+ | >> | | | | >> | | widget 0 | | >> | | | | >> | +-------------------------+ | >> | | resizer | | >> | +-------------------------+ | >> | | | | >> | | widget 1 | | >> | | | | >> | +-------------------------+ | >> | | resizer | | >> | +-------------------------+ | >> | | | | >> | | widget 2 | | >> | | | | >> | +-------------------------+ | >> +-----------------------------+
Here's an example implementation of the above based on an older work. This assumes the parent is an *Fl_Scroll*. This is so that widgets off-screen can be reached with a scroll bar. The ResizerButton class is what you would use in your app. The main() below it shows how to use it. The example code creates 10 Fl_Box widgets with a resizer below each. You can drag the resizers around to change the size of the widget above; the other widgets below will be moved around inside the scroller to accommodate. Scrollbars will appear for widgets that are off-screen. --- snip #include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Scroll.H> #include <FL/Fl_Box.H> #include <FL/Fl_Button.H> #include <FL/fl_draw.h> #include <stdio.h> // // Demonstrate a resizer class for widgets in an Fl_Scroll // erco 1.0 ??/??/04 - original test program // erco 1.1 04/21/13 - modernized // // CLASS FOR HANDLING A 'RESIZER' BETWEEN WIDGETS IN AN Fl_Scroll // // > Shows a resize cursor when hovered over // > Assumes: * Parent is an Fl_Scroll // * All children of Fl_Scroll are vertically arranged // * The widget above us has a bottom edge touching our top edge // ie. (w->y()+w->h() == this->y()) // // > When this widget is dragged: // * The widget above us (with a common edge) will be /resized/ vertically // * All children below us will be /moved/ vertically // class ResizerButton : public Fl_Button { int orig_h; int last_y; int min_h; // min height for widget above us void HandleDrag(int diff) { Fl_Scroll *grp = (Fl_Scroll*)parent(); int top = y(); int bot = y()+h(); // First pass: find widget directly above us with common edge // Possibly clamp 'diff' if widget would get too small.. // for ( int t=0; t<grp->children(); t++ ) { Fl_Widget *w = grp->child(t); if ( (w->y()+w->h()) == top ) { // found widget directly above? if ( (w->h()+diff) < min_h ) diff = w->h() - min_h; // clamp w->resize(w->x(), w->y(), w->w(), w->h()+diff); // change height break; // done with first pass } } // Second pass: find widgets below us, move based on clamped diff for ( int t=0; t<grp->children(); t++ ) { Fl_Widget *w = grp->child(t); if ( w->y() >= bot ) // found widget below us? w->resize(w->x(), w->y()+diff, w->w(), w->h()); // change position } // Change our position last resize(x(),y()+diff,w(),h()); grp->init_sizes(); grp->redraw(); } public: ResizerButton(int X,int Y,int W,int H) : Fl_Button(X,Y,W,H,"///////") { orig_h = H; last_y = 0; min_h = 10; align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); labelfont(FL_COURIER); labelsize(6); } void SetMinHeight(int val) { min_h = val; } int GetMinHeight() const { return min_h; } int handle(int e) { int ret = 0; int this_y = Fl::event_y_root(); switch (e) { case FL_FOCUS: ret = 1; break; case FL_ENTER: ret = 1; fl_cursor(FL_CURSOR_NS); break; case FL_LEAVE: ret = 1; fl_cursor(FL_CURSOR_DEFAULT); break; case FL_PUSH: ret = 1; last_y = this_y; break; case FL_DRAG: HandleDrag(this_y-last_y); last_y = this_y; ret = 1; break; default: break; } return(Fl_Button::handle(e) | ret); } void resize(int X,int Y,int W,int H) { Fl_Button::resize(X,Y,W,orig_h); // height of resizer stays constant size } }; // Demonstrate the ResizerButton class above // Creates 10 Fl_Box widgets with a resizer below each. // User can drag the resizers around to change the size of the widget above it. // The other widgets below will be moved around inside the scroller to accommodate. // int main(int argc, char** argv) { Fl_Window win(220,400); win.begin(); Fl_Scroll scr(0,0,220,400); scr.begin(); // Create 10 boxes with resizer between each for ( int i=0; i<10; i++ ) { // Create a box.. char s[10]; sprintf(s, "%c%c%c", 'A'+i,'a'+i,'a'+i); // 'unique' label Fl_Box *b = new Fl_Box (0,i*50,200,40); b->copy_label(s); b->box(FL_FLAT_BOX); b->color(FL_WHITE); b->align(FL_ALIGN_INSIDE|FL_ALIGN_LEFT); // And put a Resizer directly below it with a common edge. (The common edge is important) new ResizerButton(0,b->y()+b->h(),200,10); } scr.end(); win.end(); win.resizable(scr); win.show(); return(Fl::run()); } _______________________________________________ fltk mailing list fltk@easysw.com http://lists.easysw.com/mailman/listinfo/fltk