RE: [fltk.general] How to put a menu window "on top"? - [General Use]

172 views
Skip to first unread message

MacArthur, Ian (Leonardo, UK)

unread,
Sep 18, 2017, 5:46:21 AM9/18/17
to fltkg...@googlegroups.com
> I'm trying to create a special menu, but run into some event
> propagation
> problems. In this example I could make sure the sub window got added as
> the last widget to the testWindow to be placed "on top" of them, but
> that's not something I have to do when using the standard fltk menu
> widgets. Is there something simple I just have missed?


Daniel,

I'm really not understanding what it is you are trying to do... The nesting of your window, sub-window and the widgets within the sub-window, is confusing to me.

What effect are you actually trying to achieve?



>
> The example below shows a red sub window which won't get events when
> moving the mouse in the areas where it lays on top of an Fl_Input and
> an
> Fl_Box widget.
>
> Ideally in my situation would be that the sub window would be first to
> get all events if the mouse cursor was located inside it, so it could
> handle them if interested and the widgets "below" wouldn't get the
> events since they're already handled.

Generally speaking (but I suspect this does not fit the use case you have in mind) if you want a window that's "on top" and gets first dibs on any events, but then will pass on any events it does not use; that would be a "non-modal" window (often used for toolbars and so forth.)

A window that is "on top" and gets all events, and does not propagate any whether it uses them or not, is a "modal" window (often used for pop-up dialogs and the like.)

And of course, and normal window is just a window...

But since I'm not really getting what it is you are trying to do, I'm not sure of any of that is relevant.


In other news: Hi! to Brian - been a while, how you getting on, etc.?


Cheers,
--
Ian



Leonardo MW 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.
********************************************************************

Daniel Polski

unread,
Sep 18, 2017, 6:03:46 AM9/18/17
to fltkg...@googlegroups.com
Den 2017-09-18 kl. 11:46, skrev MacArthur, Ian (Leonardo, UK):
> I'm really not understanding what it is you are trying to do... The nesting of your window, sub-window and the widgets within the sub-window, is confusing to me.
>
> What effect are you actually trying to achieve?

The example I posted is just meant to highlight a behaviour I wonder about.

What I try to achieve in a "clean way":

When the user types in an input field (in my case a custom input field
with some extra data), I have a callback doing database lookups for
hits. I want to display those hits in a popup list below the input
field, and if the user moves the cursor into the list I highlight the
entry below the mouse.
The focus is still on the input field so the user can keep on typing
which might change the items in the popup (according to the database
hits). The popup might cover other widgets, as it looks in the example
in my original post.

(Basically the input+popup should work similar to how web browsers
address field works when showing browsing history on the fly while typing).

If the user clicks on an item in the popup, that click sets the actual
value in the (custom) input field widget and it fires off its "changed"
callback if the item is different from the previously selected one.
(Nothing gets selected from just typing in the text field, the data is
only set when the user clicks in the popup list).

MacArthur, Ian (Leonardo, UK)

unread,
Sep 18, 2017, 11:03:24 AM9/18/17
to fltkg...@googlegroups.com
> > What effect are you actually trying to achieve?
>
> The example I posted is just meant to highlight a behaviour I wonder
> about.
>
> What I try to achieve in a "clean way":
>
> When the user types in an input field (in my case a custom input field
> with some extra data), I have a callback doing database lookups for
> hits. I want to display those hits in a popup list below the input
> field, and if the user moves the cursor into the list I highlight the
> entry below the mouse.
> The focus is still on the input field so the user can keep on typing
> which might change the items in the popup (according to the database
> hits). The popup might cover other widgets, as it looks in the example
> in my original post.
>
> (Basically the input+popup should work similar to how web browsers
> address field works when showing browsing history on the fly while
> typing).
>
> If the user clicks on an item in the popup, that click sets the actual
> value in the (custom) input field widget and it fires off its "changed"
> callback if the item is different from the previously selected one.
> (Nothing gets selected from just typing in the text field, the data is
> only set when the user clicks in the popup list).


OK, I think I see...

TBH, I don't think I’d use a Fl_Menu_Window for that, I think I'd probably start with a Fl_Menu_Button and rework that to my needs... Maybe.

Though, in the case I remember doing something similar, ISTR that what I *actually* did was use an Fl_Browser for my "dropdown list", that I then populated with text strings "on the fly" as stuff was entered.
The browser was show()/hide() to enact the "dropdown".

I think that worked OK, though it was a while ago, and I can't find the code I wrote for it...

MacArthur, Ian (Leonardo, UK)

unread,
Sep 18, 2017, 11:54:49 AM9/18/17
to fltkg...@googlegroups.com
>
> OK, I think I see...
>
> TBH, I don't think I’d use a Fl_Menu_Window for that, I think I'd
> probably start with a Fl_Menu_Button and rework that to my needs...
> Maybe.
>
> Though, in the case I remember doing something similar, ISTR that what
> I *actually* did was use an Fl_Browser for my "dropdown list", that I
> then populated with text strings "on the fly" as stuff was entered.
> The browser was show()/hide() to enact the "dropdown".
>
> I think that worked OK, though it was a while ago, and I can't find
> the code I wrote for it...
>

Meh, can't find my old code - here's a nasty hack to show the sort of thing I meant, though, just in case it is useful...



//
// Possible demo for a drop-down choice alternative
// fltk-config --compile dropdwon.cxx
//
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Browser.H>

//#include <stdio.h>

static Fl_Double_Window *main_win=(Fl_Double_Window *)0;
static Fl_Button *quit_bt=(Fl_Button *)0;

static Fl_Input *inp=(Fl_Input *)0;
static Fl_Browser *brows=(Fl_Browser *)0;

static void cb_inp(Fl_Input* o, void*) {
brows->show();
}

static void cb_brows(Fl_Browser* o, void*) {
int val = o->value();
inp->value(o->text(val));
o->hide();
}

static void cb_quit_bt(Fl_Button*, void*) {
main_win->hide();
}

int main(int argc, char **argv) {
main_win = new Fl_Double_Window(368, 333, "Drodown Test");
main_win->begin();

inp = new Fl_Input(115, 35, 150, 25, "Dropdown Input");
inp->callback((Fl_Callback*)cb_inp);
inp->when(FL_WHEN_CHANGED);

Fl_Box* bx = new Fl_Box(75, 125, 200, 25);
bx->box(FL_FLAT_BOX);
bx->color(FL_GREEN);

Fl_Input* ipt2 = new Fl_Input(75, 175, 200, 25);

brows = new Fl_Browser(inp->x(), inp->y() + 25, inp->w(), 175);
brows->type(FL_SELECT_BROWSER);
brows->box(FL_FLAT_BOX);
brows->callback((Fl_Callback*)cb_brows);
brows->hide();

// some sample entries in the dropdown list
for (int idx = 1; idx <= 18; ++idx) {
char line[32];
snprintf(line, 32, "Line %d", idx);
brows->add(line);
}

quit_bt = new Fl_Button(299, 303, 64, 26, "Quit");
quit_bt->callback((Fl_Callback*)cb_quit_bt);

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

// end of file

Daniel Polski

unread,
Sep 19, 2017, 5:12:07 AM9/19/17
to fltkg...@googlegroups.com

Aha. Yes, something like your example looks cleaner. Haven't tested it
yet, but a drawback seems to be that the browser needs to be added last
in the group to be placed on "top" in the group. That's not a big deal
though, just annoying that the widget needs special implementation to
work correctly.
..But wouldn't it run into drawing/event problems if the widget popping
up the browser is placed so the brower gets popped up outside the input
widgets group? (draw clipping? events?)

Thanks,

MacArthur, Ian (Leonardo, UK)

unread,
Sep 19, 2017, 5:42:22 AM9/19/17
to fltkg...@googlegroups.com
> Aha. Yes, something like your example looks cleaner. Haven't tested it
> yet, but a drawback seems to be that the browser needs to be added last
> in the group to be placed on "top" in the group. That's not a big deal
> though, just annoying that the widget needs special implementation to
> work correctly.
> ..But wouldn't it run into drawing/event problems if the widget popping
> up the browser is placed so the brower gets popped up outside the input
> widgets group? (draw clipping? events?)

True, but both issues (i.e. "must add widget last to get on top" and "clipping of widget if extended beyond parent area") can be addressed by placing the browser in a borderless non-modal Fl_Double_Window container, and show/hide that container rather than the browser itself.
Use window->resize(x,y,w,h) each time before you show the window, to make sure it appears in the right place below your input field, and if necessary to make it bigger if the browser list grows larger, and so forth.

I didn’t show that in my hack because it's a bit more hassle to hook together cleanly. Specifically, in the past when I did do a dropdown like that, I discovered a "side effect" that if a user moves the main window whilst the "dropdown" was displayed, the "dropdown" did not also move, leaving it "detached" from its input field. Annoying and looks bad.

In the end, I contrived to detect any moves of the main window and closed the "dropdown" any time that happened, which worked OK, users seemed to accept that as "normal behaviour".

--
Ian

MacArthur, Ian (Leonardo, UK)

unread,
Sep 19, 2017, 6:29:33 AM9/19/17
to fltkg...@googlegroups.com
> > Aha. Yes, something like your example looks cleaner. Haven't tested
> it
> > yet, but a drawback seems to be that the browser needs to be added
> > last in the group to be placed on "top" in the group. That's not a
> big
> > deal though, just annoying that the widget needs special
> > implementation to work correctly.
> > ..But wouldn't it run into drawing/event problems if the widget
> > popping up the browser is placed so the brower gets popped up
> > outside the input widgets group? (draw clipping? events?)
>
> True, but both issues (i.e. "must add widget last to get on top" and
> "clipping of widget if extended beyond parent area") can be addressed
> by placing the browser in a borderless non-modal Fl_Double_Window
> container, and show/hide that container rather than the browser itself.
> Use window->resize(x,y,w,h) each time before you show the window, to
> make sure it appears in the right place below your input field, and if
> necessary to make it bigger if the browser list grows larger, and so
> forth.


Coffee break hack - something like this (only do it better, of course!)


//
// Possible demo for a drop-down choice alternative
// fltk-config --compile dropdwon.cxx
//
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Browser.H>

static Fl_Double_Window *main_win=(Fl_Double_Window *)0;
static Fl_Double_Window *drop_win=(Fl_Double_Window *)0;

static Fl_Button *quit_bt=(Fl_Button *)0;
static Fl_Input *inp=(Fl_Input *)0;
static Fl_Browser *brows=(Fl_Browser *)0;

static void cb_inp(Fl_Input* o, void*) {
int root_x = main_win->x() + inp->x();
int root_y = main_win->y() + inp->y() + inp->h();
drop_win->position(root_x, root_y);
drop_win->show();
}

static void cb_brows(Fl_Browser* o, void*) {
int val = o->value();
inp->value(o->text(val));
drop_win->hide();
}

static void cb_quit_bt(Fl_Button*, void*) {
main_win->hide();
}

int main(int argc, char **argv) {
main_win = new Fl_Double_Window(368, 225, "Drodown Test");
main_win->begin();

inp = new Fl_Input(115, 35, 150, 25, "Dropdown Input");
inp->callback((Fl_Callback*)cb_inp);
inp->when(FL_WHEN_CHANGED);

Fl_Box* bx = new Fl_Box(75, 125, 200, 25);
bx->box(FL_FLAT_BOX);
bx->color(FL_GREEN);

Fl_Input* ipt2 = new Fl_Input(75, 175, 200, 25);

quit_bt = new Fl_Button(299, 303, 64, 26, "Quit");
quit_bt->callback((Fl_Callback*)cb_quit_bt);

main_win->end();
main_win->show(argc, argv);

// Now create the dropdown window
drop_win = new Fl_Double_Window(inp->x(), inp->y() + 25, inp->w(), 195);
drop_win->begin();

brows = new Fl_Browser(0, 0, inp->w(), 195);
brows->type(FL_SELECT_BROWSER);
brows->box(FL_FLAT_BOX);
brows->callback((Fl_Callback*)cb_brows);

drop_win->end();
drop_win->clear_border();
drop_win->set_non_modal();

// some sample entries in the dropdown list
for (int idx = 1; idx <= 28; ++idx) {
char line[32];
snprintf(line, 32, "Line %d", idx);
brows->add(line);
}


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

// end of file



Reply all
Reply to author
Forward
0 new messages