On 13.04.2012 22:35, David Lopez wrote:
> Thanks Edzard and Greg for the answers, but I did not explained the issue 
> clearly.
> I wanted to give a simple example, but indeed the parent (window) may have 
> tens or hundreds of children (boxes). Each of the boxes must be redrawn at a 
> different time independently of the rest (for example to change its fill 
> color according to an asynchronous event).
> And in some cases, two (or more) of the boxes may be overlapped (the layer 
> order is static).
>
> So, a real situation could be:
> There are 100 boxes in the window (box #1 to box #100).
> The boxes #90 and #91 are overlapped.
> The box #91 is above the #90.
> The box #90 must be redrawn (because must change its color).
> It redraws OK but overwrites box #91.
> I would like to get boxes #90 and #91 to be redrawn but not the other 98 
> boxes.
>
> I think that there is no way to do this other than add to each widget a list 
> of references to the widgets that need to be redrawn if the current widget is 
> drawn (that is the boxes that are above it).
> Am I right?

FLTK is not designed to support such overlapping widgets. You
may experience (re)drawing problems if you create such widget
layouts. Of course, widgets must overlap their parents, but
that's it - child widgets shouldn't overlap each other.

That said, drawing always happens in the order of children in a
group, so that such overlapping widgets seem to work as intended,
but you're on your own if things like partial occlusion by other
windows happen, or redrawing as in your description.

So, the more specific answer to your question is: yes, you're on
your own with this, and if you really need it, you will have to
manage overlapping hierarchies in your code.

There are ways to use damage() with areas though, but I'm not very
familiar with this. Maybe this can help: if your box #90 (b90)
in Fl_Group g changed, try something like this:

   g->damage(FL_DAMAGE_ALL, b90->x(), b90->y(), b90->w(), b90->h());

instead of calling redraw(). This *should* have the same effect as
calling redraw() for the box, but should also redraw all other
overlapping widgets, if I'm right. You should give it a try and
report whether it helps (or not).

... well, I tested it myself, and it seems to work as intended.
Please see attached demo program. There are still cases where it
might not work. Look at box 3 (B3). Why does it stay "on top of
B2" if the damage() button is clicked ? It is as intended, but...

Albrecht

// overlap.cxx - overlapping widget demo.
// This shows how damage() can be used to redraw overlapping widgets.
// Use at your own risk. Usage:
// fltk-config --compile overlap.cxx && ./overlap
// Use both buttons to see the difference:
// button1_cb() redraws B1 only,
// button2_cb() redraws B1 and B2,
// resizing the window redraws all boxes.

#include <stdio.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>

Fl_Box *b1, *b2, *b3;
Fl_Color c = 0;

// This derived class is only to print which box is drawn.
class MyBox : public Fl_Box {
public:
   MyBox(int x, int y, int w, int h, const char *L) :
     Fl_Box(x,y,w,h,L) {
       align(FL_ALIGN_INSIDE|FL_ALIGN_LEFT|FL_ALIGN_TOP);
       box(FL_FLAT_BOX);
     }
   void draw() {
     printf("draw() box %s\n",label()); fflush(stdout);
     Fl_Box::draw();
   }
};

// Button 1 doesn't draw overlapping widgets
void button1_cb(Fl_Widget *, void *) {
   printf("button 1: redraw()\n");
   if (++c > 7) c = 1;
   b1->color(c);
   b1->redraw();
}

// Button 2 draws overlapping widgets
void button2_cb(Fl_Widget *, void *) {
   printf("button 2: damage()\n");
   if (++c > 7) c = 1;
   b1->color(c);
   b1->parent()->damage(FL_DAMAGE_ALL, b1->x(), b1->y(), b1->w(), b1->h());
}

int main(int argc, char **argv) {
   Fl_Window *window = new Fl_Window(500, 300, "Overlapping widget test");
     Fl_Group *g = new Fl_Group(0,0,300,300);
       b1 = new MyBox(10,10,200,200,"B1");
       b1->color(FL_WHITE);
       b2 = new MyBox(90,90,200,200,"B2");
       b2->color(fl_lighter(fl_lighter(FL_BLUE)));
       b3 = new MyBox(230,30,80,80,"B3");
       b3->color(FL_YELLOW);
     g->end();
     Fl_Button *button1 = new Fl_Button(350, 50,100,50,"redraw()");
     button1->callback(button1_cb);
     Fl_Button *button2 = new Fl_Button(350,150,100,50,"damage()");
     button2->callback(button2_cb);
   window->end();
   window->resizable(window);
   window->show();
   return Fl::run();
}

_______________________________________________
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to