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

Reply via email to