On 08/15/14 16:11, Greg Ercolano wrote:
> On 08/15/14 06:28, 'John' via fltk.general wrote:
>> I'm a dabbler in FLTK, but haven't used it an a number of years.
>>
>> I'm drawing some text in a scrolled window. I want some of the text on
>> the screen to always be the same and not scroll (imagine headers in a table).
> [..]
> I'd say the right thing to do here is to make a separate
> widget that draws your fixed-position header, and parent
> it to the window, and put the scroll below it as a sibling.
>
> This way the header will be treated as a separate widget.
>
> If you need interaction between your header widget and
> the scroller (i.e. if the horizontal scroll is moved,
> your header knows about it), then you can trap the
> Fl_Scroll's horizontal scroller callback and do what you
> need to find its position and just the header's drawing
> as needed.
Here's an example of the above, complete with trapping
Fl_Scroll's horiz scrollbar callback to scroll the "header"
along with the scroller's content.
In this case I added a MyHeader class which has code to
handle drawing the header, and there's some optional code
to attach Fl_Scroll's hscrollbar to the widget to handle
offsetting the header's drawing.
_____________________________________________________________________________
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
#include <stdio.h>
class MyHeader : public Fl_Widget {
Fl_Callback *old_callback; // horiz scroll callback
void *old_userdata; // horiz scroll userdata
Fl_Scrollbar *hs_scrollbar; // horiz scrollbar
public:
MyHeader(int X,int Y,int W,int H,const char*L=0) : Fl_Widget(X,Y,W,H,L) {
old_callback = 0;
old_userdata = 0;
hs_scrollbar = 0;
}
void draw() {
// DRAW BG
fl_color(color());
fl_rectf(x(),y(),w(),h());
// Draw text -- clip
fl_push_clip(x(), y(), w(), h());
int offset = hs_scrollbar ? hs_scrollbar->value() : 0;
fl_color(FL_BLACK);
fl_line(x()-offset,y()+h()-2,x()+w()-offset,y()+h()-2);
fl_draw("foo | bar | bla", x()+10-offset, y()+h()-5);
fl_pop_clip();
}
static void HscrollCallback(Fl_Widget *w, void *userdata) {
MyHeader *mh = (MyHeader*)userdata; // establish 'this'
mh->redraw(); // trigger redraw; offset changed
if (mh->old_callback)
mh->old_callback(w, mh->old_userdata); // invoke Fl_Scroll's callback()
}
void InterceptHscroll(Fl_Scroll &scroll) {
// Keep old callback + userdata
old_callback = scroll.hscrollbar.callback();
old_userdata = scroll.hscrollbar.user_data();
hs_scrollbar = &(scroll.hscrollbar);
// Hook in our callback
scroll.hscrollbar.callback(HscrollCallback, (void*)this);
}
};
// SCROLLABLE CANVAS EXAMPLE -- JUST DRAWS AN 'X'
class MyCanvas : public Fl_Widget {
public:
MyCanvas(int X,int Y,int W,int H,const char*L=0) : Fl_Widget(X,Y,W,H,L) {
}
void draw() {
// DRAW BG
fl_color(color());
fl_rectf(x(),y(),w(),h());
// DRAW 'X' OVER BG
// Do your graphics here..
//
int x1=x(), y1=y(); // Fl_Scroll works by changing our widget's x() and y(),
int x2=x()+w()-1, y2=y()+h()-1; // so take these into account for our drawing coordinates
fl_color(FL_BLACK);
fl_line(x1,y1,x2,y2);
fl_line(x1,y2,x2,y1);
// Draw a string that scrolls
fl_font(FL_HELVETICA,14);
char astring[100];
sprintf(astring, "%d", 60);
fl_draw(astring, x1, y1+60);
}
};
int main() {
Fl_Double_Window win(301,251);
MyHeader header(0,0, 200,30);
Fl_Scroll scroll(0,30,200,200);
MyCanvas canvas(0,0,350,350); // purposely make drawing area larger than scroll
scroll.end();
header.InterceptHscroll(scroll);