All,

Tea break experiment: here's a possible implementation of this, using a
hybrid of my fl_offscreen approach and Albrecht's Fl_Scroll with the
scrollbars disabled.

Seems to work OK.
Has to be said I jumped into typing without really thinking about the
problem, so this is probably just about the most complex way to do
this...

I have provided buttons to do the scroll steps, or following Albrecht's
other suggestion, if you click to "grab" a non-active part of the
scrolll area you can drag it around by hand...

Seems to work - hope it makes some sort of sense.

-------------------
// scroll offscreen
// fltk-config --compile scroll-offs.cxx
/* Standard headers */
#include <stdio.h>

#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Repeat_Button.H>
#include <FL/Fl_Scroll.H>
#include <Fl/fl_draw.h>

static Fl_Double_Window *main_win = (Fl_Double_Window *)0;
static Fl_Offscreen offscr = 0;
static int offscrW = 750; // offscreen region size
static int offscrH = 750;
static int viewW = 300, viewH = 300; // viewport size
const int scroll_step = 10;

class offscreen_group : public Fl_Group {
protected:
        void draw( );
    int ow, oh; // offscreen size
        int x1, y1;
        int drag_state;
public:
        offscreen_group(int X, int Y, int OW, int OH) :
        Fl_Group(0, 0, OW,OH) {
                ow = OW; oh = OH;
                xoff = yoff = x1 = y1 = 0;
                drag_state = 0;
        }
        int handle(int);
        // these should be protected and have accessors.
        // indeed, they should not really be here at all...
        int xoff, yoff; // viewport scroll offsets
};

/***********************************************************************
******/
void offscreen_group::draw() {
        int wo = w();
        int ho = h();
        if (!offscr) offscr = fl_create_offscreen(ow, oh);
        if(!offscr) return; // create must have failed!
        fl_begin_offscreen(offscr);
        // draw the widget hierarchy of this group into the offscreen
        Fl_Group::draw();
        fl_end_offscreen();
        // copy the offscreen back onto this window...
        fl_copy_offscreen(0, 0, wo, ho, offscr, 0, 0);
}

/***********************************************************************
******/
int offscreen_group::handle(int ev) {
        int ret = Fl_Group::handle(ev);
        // handle dragging of visible page area
        if(!ret) { // event not taken - is it a drag?
                Fl_Scroll *scroller = (Fl_Scroll *)parent();
                int vw = scroller->w();
                int vh = scroller->h();

                switch(ev) {
                case FL_PUSH:
                                main_win->cursor(FL_CURSOR_HAND);
                                x1 = Fl::event_x_root();
                                y1 = Fl::event_y_root();
                                drag_state = 1; // drag
                                ret = 1;
                                break;

                case FL_DRAG:
                                if(drag_state == 1) { // dragging page
                                        int x2 = Fl::event_x_root();
                                        int y2 = Fl::event_y_root();
                                        int xd = x1 - x2;
                                        int yd = y1 - y2;
                                        x1 = x2; y1 = y2;
                                        xoff += xd;
                                        yoff += yd;
                                        // check the page bounds
                                        if(yoff > (h() - vh)) yoff =
(h() - vh);
                                        else if(yoff < 0) yoff = 0;

                                        if(xoff > (w() - vw)) xoff =
(w() - vw);
                                        else if(xoff < 0) xoff = 0;

                                        scroller->position(scroller->x()
+ xoff + 1,
                                           scroller->y() + yoff + 1);
                                        redraw();
                                        ret = 1;
                                }
                                break;

                case FL_RELEASE:
                                main_win->cursor(FL_CURSOR_DEFAULT);
                                drag_state = 0;
                                ret = 1;
                                break;

                default:
                                break;
                }
        }
        return ret;
} // handle

/***********************************************************************
******/
static void cb_bt_click(Fl_Button*, void*){
        puts("Click!"); fflush(stdout);
} // cb_bt_click
/***********************************************************************
******/
offscreen_group *osg = (offscreen_group *)0;
Fl_Scroll *scroller = (Fl_Scroll *)0;

static void cb_bt_mv(Fl_Button*, void*v){
        int i = (int)v;
        int vw = scroller->w();
        int vh = scroller->h();
        switch(i){
                case 1: // up
                        osg->yoff += scroll_step;
                        if(osg->yoff > (osg->h() - vh)) osg->yoff =
(osg->h() - vh);
                        break;
                case 2: // dn
                        osg->yoff -= scroll_step;
                        if(osg->yoff < 0) osg->yoff = 0;
                        break;
                case 3: // ll
                        osg->xoff += scroll_step;
                        if(osg->xoff > (osg->w() - vw)) osg->xoff =
(osg->w() - vw);
                        break;
                case 4: // rr
                        osg->xoff -= scroll_step;
                        if(osg->xoff < 0) osg->xoff = 0;
                        break;
                default:
                        return;
        }
        scroller->position(scroller->x() + osg->xoff + 1,
                           scroller->y() + osg->yoff + 1);
        osg->redraw();
} // cb_bt_mv
/***********************************************************************
******/
int main(int argc, char **argv) {
        main_win = new Fl_Double_Window(450, 430, "Fl_Offscreen group
test");
        main_win->begin();

        // buttons to control the "scroll" region
        Fl_Repeat_Button *up = new Fl_Repeat_Button(viewW+10,
viewH+10-30, 30, 30, "@#8->");
        up->callback((Fl_Callback*)cb_bt_mv, (void *)1);
        Fl_Repeat_Button *dn = new Fl_Repeat_Button(viewW+10,
viewH+10+30, 30, 30, "@#2->");
        dn->callback((Fl_Callback*)cb_bt_mv, (void *)2);
        Fl_Repeat_Button *ll = new Fl_Repeat_Button(viewW+10-30,
viewH+10, 30, 30, "@#4->");
        ll->callback((Fl_Callback*)cb_bt_mv, (void *)3);
        Fl_Repeat_Button *rr = new Fl_Repeat_Button(viewW+10+30,
viewH+10, 30, 30, "@#6->");
        rr->callback((Fl_Callback*)cb_bt_mv, (void *)4);

        // bounding scroller
        scroller = new Fl_Scroll(10, 10, viewW, viewH);
        scroller->begin();

        // offscreen "scroll" region and its viewport
        osg = new offscreen_group(10, 10, offscrW, offscrH);
        osg->begin();
        osg->box(FL_FLAT_BOX);
        int a = 11;
        // make some random widgets within the "scroll" region
        Fl_Button *b0;
        while ((a + 60) < offscrW)
        {
                b0 = new Fl_Button(a, a, 60, 60, "BUTTON");
                b0->callback((Fl_Callback*)cb_bt_click);
                b0->clear_visible_focus();
                a += 60;
        }
        osg->end();

        scroller->end();
        scroller->type(0); // turn off the scrollbars etc
        scroller->box(FL_BORDER_BOX);

        main_win->end();
        main_win->show(argc, argv);
        return Fl::run( );
}

/* end of file */
-------------------
SELEX Sensors and Airborne Systems Limited
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 
3EL
A company registered in England & Wales.  Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************

_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to