Adding FL_BEFORE_MENU event to classes derived from Fl_Menu_

This commit is contained in:
Matthias Melcher
2025-03-29 23:36:09 +01:00
parent b7189192e2
commit 5dd1062df5
13 changed files with 69 additions and 15 deletions

View File

@@ -418,7 +418,11 @@ enum Fl_Event { // events
/** A tooltip is about to pop up for this widget. The mouse coordinates are
available in Fl::event_x() and Fl::event_y(). Change the widget tooltip
as needed. */
FL_TOOLTIP_EVENT = 28
FL_BEFORE_TOOLTIP = 28,
/** Triggered just before a menu is displayed. Widgets derived from Fl_Menu_
receive this event right before the menu appears, providing an opportunity
to update menu item states and activation. */
FL_BEFORE_MENU = 29
// DEV NOTE: Keep this list in sync with FL/names.h
};

View File

@@ -100,6 +100,10 @@
}
\endcode
FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
displaying the menu. This event provides an opportunity to update menu
item states and activation. See `test/menubar.cxx`, class `Dynamic_Choice`
"Flip" and "Flop" for a usage example.
*/
class FL_EXPORT Fl_Choice : public Fl_Menu_ {
protected:

View File

@@ -61,6 +61,10 @@
Typing the shortcut() of any of the menu items will cause
callbacks exactly the same as when you pick the item with the mouse.
FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
displaying the menu. This event provides an opportunity to update menu
item states and activation.
*/
class FL_EXPORT Fl_Menu_Bar : public Fl_Menu_ {
friend class Fl_Sys_Menu_Bar_Driver;

View File

@@ -52,6 +52,10 @@
is done instead, along with any userdata configured for it.
The callback can determine which item was picked using
value(), mvalue(), item_pathname(), etc.
FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
displaying the menu. This event provides an opportunity to update menu
item states and activation.
*/
class FL_EXPORT Fl_Menu_Button : public Fl_Menu_ {
protected:

View File

@@ -95,7 +95,7 @@ public:
static void wrap_width(int v) { wrap_width_ = v; }
/** Returns the window that is used for tooltips */
static Fl_Window* current_window(void);
/** \brief Temporarily Override Tooltip Text during an FL_TOOLTIP_EVENT. */
/** \brief Temporarily Override Tooltip Text during an FL_BEFORE_TOOLTIP event. */
static int override_text(const char *new_text);
// These should not be public, but Fl_Widget::tooltip() needs them...

View File

@@ -73,10 +73,11 @@ const char * const fl_eventnames[] =
"FL_FULLSCREEN",
"FL_ZOOM_GESTURE",
"FL_ZOOM_EVENT",
"FL_TOOLTIP_EVENT",
"FL_EVENT_29", // not yet defined, just in case it /will/ be defined ...
"FL_BEFORE_TOOLTIP",
"FL_BEFORE_MENU",
"FL_EVENT_30", // not yet defined, just in case it /will/ be defined ...
"FL_EVENT_31" // not yet defined, just in case it /will/ be defined ...
"FL_EVENT_31", // not yet defined, just in case it /will/ be defined ...
"FL_EVENT_32" // not yet defined, just in case it /will/ be defined ...
};
/**

View File

@@ -195,6 +195,7 @@ int Fl_Choice::handle(int e) {
J1:
if (Fl::scheme()
|| fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) != textcolor()) {
handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
if (wp.deleted()) return 1;
} else {
@@ -202,6 +203,7 @@ int Fl_Choice::handle(int e) {
// temporarily override the color() of this widget...
Fl_Color c = color();
color(FL_BACKGROUND2_COLOR);
handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), mvalue(), this);
if (wp.deleted()) return 1;
color(c);

View File

@@ -54,6 +54,10 @@
- 1: the user picked a different item in the choice menu
- 0: the user typed or pasted directly into the input field
FLTK triggers an `FL_BEFORE_MENU` event for this widget right before
displaying the menu. This event provides an opportunity to update menu
item states and activation.
\par Example Use of Fl_Input_Choice
\code
#include <stdio.h>
@@ -152,6 +156,7 @@ void Fl_Input_Choice::InputMenuButton::draw() {
// Make pulldown menu appear under entire width of widget
const Fl_Menu_Item* Fl_Input_Choice::InputMenuButton::popup() {
handle(FL_BEFORE_MENU);
menu_end();
redraw();
Fl_Widget_Tracker mb(this);

View File

@@ -49,6 +49,7 @@ int Fl_Menu_Bar::handle(int event) {
case FL_PUSH:
v = 0;
J1:
handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
picked(v);
return 1;
@@ -71,6 +72,7 @@ Fl_Menu_Bar::Fl_Menu_Bar(int X, int Y, int W, int H,const char *l)
void Fl_Menu_Bar::play_menu(const Fl_Menu_Item *v) {
if (v) {
handle(FL_BEFORE_MENU);
v = menu()->pulldown(x(), y(), w(), h(), v, this, 0, 1);
picked(v);
}

View File

@@ -59,6 +59,7 @@ void Fl_Menu_Button::draw() {
\see Fl_Menu_::menu_end()
*/
const Fl_Menu_Item* Fl_Menu_Button::popup() {
handle(FL_BEFORE_MENU);
menu_end();
const Fl_Menu_Item* m;
pressed_menu_button_ = this;

View File

@@ -26,7 +26,7 @@
#include <stdio.h>
#define DEBUG
// #define DEBUG
float Fl_Tooltip::delay_ = 1.0f;
float Fl_Tooltip::hidedelay_ = 12.0f;
@@ -161,16 +161,16 @@ static void tooltip_hide_timeout(void*) {
/**
Use this method to temporarily change the tooltip text before it is displayed.
When FLTK sends an FL_TOOLTIP_EVENT to the widget under the mouse pointer,
you can handle this event to modify the tooltip text dynamically. The
provided text will be copied into a local buffer. To apply the override,
When FLTK sends an FL_BEFORE_TOOLTIP event to the widget under the mouse
pointer, you can handle this event to modify the tooltip text dynamically.
The provided text will be copied into a local buffer. To apply the override,
the event handler must return 1.
To disable the tooltip for the current event, set the override text to nullptr
or an empty string ("") and return 1.
\param[in] new_text a C string that will be copied into a buffer
\return always 1, so this call can finish the FL_TOOLTIP_EVENT handling.
\return always 1, so this call can finish the FL_BEFORE_TOOLTIP event handling.
\see void Fl_Widget::tooltip(const char *text).
@@ -198,7 +198,7 @@ void Fl_Tooltip::tooltip_timeout_(void*) {
recursion = 1;
if (!top_win_iconified_()) { // no tooltip if top win iconified (STR #3157)
if (Fl_Tooltip::current()) {
if (Fl_Tooltip::current()->handle(FL_TOOLTIP_EVENT))
if (Fl_Tooltip::current()->handle(FL_BEFORE_TOOLTIP))
tip = Fl_Tooltip::override_text_;
}
if (!tip || !*tip) {
@@ -394,7 +394,7 @@ void Fl_Tooltip::set_enter_exit_once_() {
the childs tooltip to an empty string ("").
Tooltips can be updated dynamically before they are displayed. When a tooltip
is about to be shown, FLTK sends an `FL_TOOLTIP_EVENT` to the widgets
is about to be shown, FLTK sends an `FL_BEFORE_TOOLTIP` event to the widgets
`handle()` method. Developers can override the tooltip text temporarily
using `Fl_Tooltip::override_text(const char* new_text)` and returning 1 from
`handle()` to apply the change.

View File

@@ -90,7 +90,7 @@ public:
Image_Box(int x, int y, int w, int h, const char *label = nullptr)
: Fl_Box(x, y, w, h, label) { }
int handle(int event) {
if (event == FL_TOOLTIP_EVENT) {
if (event == FL_BEFORE_TOOLTIP) {
const char *color_name_lut[] = { "blue", "green", "black", "red" };
int quadrant = (Fl::event_x() < x()+w()/2) + 2*(Fl::event_y() < y()+h()/2);
char buf[80];

View File

@@ -210,7 +210,7 @@ void menu_location_cb(Fl_Widget* w, void* data)
if (((Fl_Choice*)w)->value() == 1) { // switch to system menu bar
menubar->hide();
const Fl_Menu_Item *menu = menubar->menu();
smenubar = new Fl_Sys_Menu_Bar(0,0,0,30);
smenubar = new Fl_Sys_Menu_Bar(0,0,0,30);
smenubar->menu(menu);
smenubar->callback(test_cb);
}
@@ -236,6 +236,30 @@ void about_cb(Fl_Widget*, void*) {
fl_message("The menubar test app.");
}
class Dynamic_Choice: public Fl_Choice {
public:
Dynamic_Choice(int x, int y, int w, int h, const char *label=nullptr)
: Fl_Choice(x, y, w, h, label) { }
int handle(int event) {
static int flip_flop = 0;
if (event == FL_BEFORE_MENU) {
// The following line is legal because we used `copy()` to create a
// writable copy of the menu array when creating this Choice.
Fl_Menu_Item *mi = const_cast<Fl_Menu_Item*>(menu());
if (flip_flop == 1) {
mi[7].flags |= FL_MENU_INACTIVE;
mi[8].flags &= ~FL_MENU_INACTIVE;
flip_flop = 0;
} else {
mi[7].flags &= ~FL_MENU_INACTIVE;
mi[8].flags |= FL_MENU_INACTIVE;
flip_flop = 1;
}
}
return Fl_Choice::handle(event);
}
};
int main(int argc, char **argv) {
for (int i=0; i<99; i++) {
char buf[100];
@@ -256,7 +280,10 @@ int main(int argc, char **argv) {
mb1.tooltip("this is a menu button");
mb1.callback(test_cb);
menus[1] = &mb1;
Fl_Choice ch(300,100,80,25,"&choice:"); ch.menu(pulldown);
Dynamic_Choice ch(300,100,80,25,"&choice:");
ch.copy(pulldown);
ch.add("Flip");
ch.add("Flop");
ch.tooltip("this is a choice menu");
ch.callback(test_cb);
menus[2] = &ch;