Stick a widget(s) inside Fl_Scroll

51 views
Skip to first unread message

Dmitrij K

unread,
Jul 9, 2014, 4:17:12 AM7/9/14
to fltkg...@googlegroups.com
Hi.

I need a canvas widget with top ruler(scale in cm) and left ruler(scale in cm),
inside the Fl_Scroll (see Gimp for example).
I haven't ideas for this time how to stick them (may be in the resize/draw do position its?)

How I can do it ?

Thanks for yours answers and tips.

MacArthur, Ian (Selex ES, UK)

unread,
Jul 9, 2014, 4:57:52 AM7/9/14
to fltkg...@googlegroups.com
> I need a canvas widget with top ruler(scale in cm) and left ruler(scale
> in cm),
> inside the Fl_Scroll (see Gimp for example).
> I haven't ideas for this time how to stick them (may be in the
> resize/draw do position its?)
>
> How I can do it ?

There are many ways, but I think what I'd do is:

Create a group the size of the full canvas area you want, including the rulers. In this group put four widgets, one for each ruler, one for the join between the rulers and one for the canvas (I'd probably just derive something form Fl_Box for this.)

Then create the scroll at whatever size (i.e. smaller than the full canvas area), and stick the group inside the scroll.

That should be about it. Except... That's *not* going to be what you want; I'm guessing that really you want the rulers to be fixed on the display, but the canvas to move.

In this case, I'd put the rulers outside the scroll, and only the derived canvas inside the scroll. Then you would need to update your rulers to reflect the scroll movement by calling

scroll->xposition() and scroll->yposition()

to figure out how much the canvas was moved. The actual scale etc. of your rulers will be set by looking at the w() and h() of the scroll, and knowing about any "zoom" or etc. your code is applying.

Actually moving the canvas, of course, is handled by the Fl_Scroll widget, so you do not have to.




Selex ES Ltd
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.
********************************************************************

Dmitrij K

unread,
Jul 9, 2014, 6:07:17 AM7/9/14
to fltkg...@googlegroups.com
Ian, thank you very much for the your idea!
I will try that.

MacArthur, Ian (Selex ES, UK)

unread,
Jul 9, 2014, 8:35:01 AM7/9/14
to fltkg...@googlegroups.com
> Ian, thank you very much for the your idea!
> I will try that.


Lunchtime's over: here's a worked example... Not exactly what you asked for but I think it demonstrates most of the necessary features you'd need to make this work.

Also, purely because I was doing it anyway, I have derived a box that draws a rotated "vertical" label.
This because Svets was asking about vertical labels the other day (well 29th June or thereabouts anyway!) and I'd said I thought using rotated drawing might be worth a look, so this stands as a worked example for that too.

Run this from the command line, it takes one parameter, the name of an image file to display, like:

./scroll-test some-image.jpg

or equivalent.

Ought to work with any fltk supported image format... so might help Tom Grieve with his BMP display question too I suppose!

Three queries in one example: Is this a record!?

================================

//
// fltk-config --use-images --compile scroll-test.cxx
//
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Shared_Image.H>
#include <FL/fl_draw.H>

#include <stdio.h>

static Fl_Double_Window *main_win = 0;
static Fl_Box *h_rule = 0;

// contrive to draw a vertical label box for the vertical ruler...
class v_ruler : public Fl_Box {
public:
v_ruler(int X, int Y, int W, int H) : Fl_Box(X,Y,W,H) {}

char rt_text[256];

protected:
void draw() {
draw_box();
fl_font(labelfont(), labelsize());
fl_color(labelcolor());

// measure the text we want to rotate
int dx(0), dy(0);
fl_measure(rt_text, dy, dx); // note x,y flipped to rotate axes
dx /= 2;
dy /= 2;
// draw the rotated label string
fl_push_clip(x(),y(),w(),h());
fl_draw(90, rt_text, x() + w()/2 + dx, y() + h()/2 + dy);
fl_pop_clip();
} // draw
} ; // v_ruler

static v_ruler *v_rule = 0;

static void update_h_pos_label (int h_pos) {
static char h_label[256];
if (h_rule) {
sprintf(h_label, "Horizontal Position %d", h_pos);
h_rule->label(h_label);
h_rule->redraw();
}
} // update_h_pos_label

static void update_v_pos_label (int v_pos) {
if (v_rule) {
sprintf(v_rule->rt_text, "Vertical Position %d", v_pos);
v_rule->redraw();
}
} // update_v_pos_label

class fancy_scroll : public Fl_Scroll {
public:
fancy_scroll(int X, int Y, int W, int H) : Fl_Scroll(X,Y,W,H) {
hscrollbar.callback(my_hscrollbar_cb);
scrollbar.callback(my_vscrollbar_cb);
} // constructor

private:
static void my_hscrollbar_cb(Fl_Widget *o, void*) {
Fl_Scroll* s = (Fl_Scroll*)(o->parent());
s->scroll_to(int(((Fl_Scrollbar*)o)->value()), s->yposition());
update_h_pos_label(s->xposition());
} // my_hscrollbar_cb

static void my_vscrollbar_cb(Fl_Widget *o, void*) {
Fl_Scroll* s = (Fl_Scroll*)(o->parent());
s->scroll_to(s->xposition(), int(((Fl_Scrollbar*)o)->value()));
update_v_pos_label(s->yposition());
} // my_vscrollbar_cb
}; // fancy_scroll

static fancy_scroll *scroll = 0;

int main(int argc, char **argv) {

if(argc < 2) {
puts("Filename?");
return -1;
}

Fl::get_system_colors();
fl_register_images();
// load an image
Fl_Shared_Image *picture;
picture->get(argv[1]);

// Create the windows and widgets
main_win = new Fl_Double_Window (300, 300, "Scroller Test");
main_win->begin();

int sc_w = main_win->w() - 30;
int sc_h = main_win->h() - 30;
// draw the scroll region
scroll = new fancy_scroll (25, 25, sc_w, sc_h);
scroll->begin();

// get the loaded image
Fl_Image *image = (Fl_Image*)picture->images()[0];
// assign image to the display box - this is the "canvas" of the scroll region
Fl_Box *img_box = new Fl_Box(0, 0, image->w(), image->h());
img_box->image(image);

scroll->end();
scroll->type(Fl_Scroll::BOTH_ALWAYS);

// draw the "rulers"
sc_w = sc_w - Fl::scrollbar_size();
sc_h = sc_h - Fl::scrollbar_size();
h_rule = new Fl_Box(25, 3, sc_w, 20);
h_rule->box(FL_DOWN_BOX);

v_rule = new v_ruler(3, 25, 20, sc_h);
v_rule->box(FL_DOWN_BOX);

Fl_Box *corner = new Fl_Box(3, 3, 20, 20);
corner->box(FL_DOWN_BOX);

main_win->end();
main_win->resizable(scroll);
main_win->show();

// Force an initial flush to get the scroll refreshed.
// We do this so we can read back and set the initial "ruler" positions...
Fl::check();
// set the initial "ruler" positions...
update_h_pos_label(scroll->xposition());
update_v_pos_label(scroll->yposition());

return Fl::run();
} // main

/* End of File */

Dmitrij K

unread,
Jul 9, 2014, 9:47:24 AM7/9/14
to fltkg...@googlegroups.com
Ian, thank you very much again !
Reply all
Reply to author
Forward
0 new messages