On 10.11.2011 21:30, Greg Ercolano wrote:
> On 11/10/11 08:53, Albrecht Schlosser wrote:
>> I tried with another class derived from Fl_Box instead of
>> Fl_Table(_Row) as in your test, and it didn't show the effect.
>
>       Albrecht: did the Fl_Box derived widget test involve
>       overloading handle() to post the menu?

Overloading handle(): yes, but only for displaying events as
a test mode. I used a simple overlay technique by putting the
(invisible) menu button above the box, so that it catches the
(right) mouse click event and displays the menu. This is, AFAICT,
the recommended way to use Fl_Menu_Button. I'll append my test
code below.

>       If so, that'd probably work fine with Fl_Table as well,
>       and would be different than OP's technique which uses
>       the table's event_callback() to post the menu (a technique
>       specific to Fl_Table that's meant to allow mouse events
>       to make changes to the table)

I don't know much about Fl_Table code, and I was also a little
surprised how the menu was handled. I just wanted to do a simple
test to make sure that the right mouse click doesn't "leak" through
the menu's handle() method, and this it what my test seems to confirm.

>       I think what's happening (not sure) is:
>       Fl_Table calls its event_callback() *during* it's handle()
>       method, and it's probably not expecting the event_callback()
>       code to start its own event loop.
>
>       I'm not sure it's technically possible for the event_callback()
>       to be used for doing its own event loop (which popping up a
>       blocking menu implies), so I think the below technique is
>       probably needed, and the docs for Fl_Table::event_callback()
>       should warn about this.

Again, I'm not sure what Fl_Table::event_callback() is designed to do,
but running one's own event loop in a callback to pop up a menu (or
fl_message() and friends) is standard. In fact, everything your program
does after starting Fl::run() is done in callbacks, isn't it?

>> I tested using an event display in handle(), and the box widget
>> didn't get the push event. However, I can see a difference with
>> your test program, but I don't know (yet?) what it is.
>>
>> More tests needed. Greg, if you have an idea...
>
>       Can I suggest the OP try this technique instead, which uses
>       handle() to post the menu instead of the event_callback()

Okay, I tested your code, and it seems to work well for me. No
unintended row selection.

With my test code you can see lots of FL_ENTER/FL_LEAVE events. These
are probably caused by overlaying the box and the menu in the same
area. It's partly only a cosmetic problem, but I believe this could
become a problem for widgets that handle FL_ENTER and FL_LEAVE, but
also want to have a Fl_Menu_Button to handle a popup menu. But this
is OT here...

Albrecht

-- popup_over_box.cxx --
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/fl_draw.H>
#include <FL/names.h>

// Derive a class from Fl_Box
class MyBox : public Fl_Box {
public:
   MyBox(int X, int Y, int W, int H, const char *L=0) : 
Fl_Box(X,Y,W,H,L) { }
   virtual int handle(int e);
   ~MyBox() { }
};

int MyBox::handle(int e) {
   static int n = 1;
   n++; if (n>999) n = 0;
   int ret = 0;
   switch (e) {
     case FL_MOVE:      // don't "print" -- too noisy!
       break;
     case FL_ENTER:
     case FL_LEAVE:
     case FL_FOCUS:
     case FL_PUSH:
       ret = 1;         // fall through ...
     default:
       printf("MyBox::handle(event[%3d] = %-20.20s",n,fl_eventnames[e]);
   }
   int ret2 = Fl_Box::handle(e);
   if (e != FL_MOVE) {
     if (ret2) printf(" <handled by Fl_Box>");
     printf("\n"); fflush(stdout);
   }
   return ret|ret2;
}

Fl_Menu_Item menu_popmenu[] = {
  {"Insert Before...", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
  {"Insert After...", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
  {"Delete", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
  {"Edit...", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
  {0,0,0,0,0,0,0,0,0}
};

int main(int argc, char **argv) {
   Fl_Double_Window win(240, 240, "Simple Menu Test");
   MyBox table(20,20,200,200);
   table.color(FL_YELLOW);
   table.box(FL_FLAT_BOX);
   Fl_Menu_Button popmenu (20,20,100,200);
   popmenu.menu(menu_popmenu);
   popmenu.type(Fl_Menu_Button::POPUP3);
   win.end();
   win.resizable(table);
   win.show(argc,argv);
   return(Fl::run());
}
-- snip --
_______________________________________________
fltk mailing list
fltk@easysw.com
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to