Browse Source

Adding the FL_MENU_CHATTY flag to Fl_Menu_Item.

If set, menu items will also call the callback when highlighting changes.
The reason is given with Fl::callback_reason(). #941
pull/1246/head
Matthias Melcher 2 months ago
parent
commit
f4978a0149
  1. 28
      FL/Fl_Menu_Item.H
  2. 2
      src/Fl_MacOS_Sys_Menu_Bar.mm
  3. 21
      src/Fl_Menu.cxx
  4. 7
      src/Fl_Menu_.cxx
  5. 16
      test/menubar.cxx

28
FL/Fl_Menu_Item.H

@ -34,7 +34,8 @@ enum { // values for flags:
FL_SUBMENU_POINTER = 0x20, ///< Indicates user_data() is a pointer to another menu array FL_SUBMENU_POINTER = 0x20, ///< Indicates user_data() is a pointer to another menu array
FL_SUBMENU = 0x40, ///< Item is a submenu to other items FL_SUBMENU = 0x40, ///< Item is a submenu to other items
FL_MENU_DIVIDER = 0x80, ///< Creates divider line below this item. Also ends a group of radio buttons FL_MENU_DIVIDER = 0x80, ///< Creates divider line below this item. Also ends a group of radio buttons
FL_MENU_HORIZONTAL = 0x100 ///< ??? -- reserved, internal (do not use) FL_MENU_HORIZONTAL = 0x100, ///< reserved, do not use
FL_MENU_CHATTY = 0x200 ///< Menu Item receives additional callbacks
///< Note: \b ALL other bits in \p flags are reserved: do not use them for your own purposes! ///< Note: \b ALL other bits in \p flags are reserved: do not use them for your own purposes!
}; };
@ -67,7 +68,8 @@ class Fl_Menu_;
FL_SUBMENU_POINTER = 0x20, // Indicates user_data() is a pointer to another menu array FL_SUBMENU_POINTER = 0x20, // Indicates user_data() is a pointer to another menu array
FL_SUBMENU = 0x40, // This item is a submenu to other items FL_SUBMENU = 0x40, // This item is a submenu to other items
FL_MENU_DIVIDER = 0x80, // Creates divider line below this item. Also ends a group of radio buttons. FL_MENU_DIVIDER = 0x80, // Creates divider line below this item. Also ends a group of radio buttons.
FL_MENU_HORIZONTAL = 0x100 // ??? -- reserved, internal (do not use) FL_MENU_HORIZONTAL = 0x100 // reserved, do not use
FL_MENU_CHATTY = 0x200 ///< Menu Item receives additional callbacks
}; };
\endcode \endcode
@ -120,6 +122,16 @@ class Fl_Menu_;
variants copies the entire menu to internal storage. Using the variants copies the entire menu to internal storage. Using the
memory of a static menu array after that would access unused (but not memory of a static menu array after that would access unused (but not
released) memory and thus have no effect. released) memory and thus have no effect.
When a menu item is selected by the user and a callback is set, the callback
will be called with FL_REASON_SELECTED. The Fl_Widget pointer is set to the
widget that opened the menu, a copy of the menu item's user data. If no menu
item callback is set, the callback of the managing widget is called instead.
If the FL_MENU_CHATTY flag is set, the menu item callback may be called for
additional reasons. When a menu item is highlighted, the callback is called
with FL_REASON_GOT_FOCUS. If it is no longer highlighted,
FL_REASON_LOST_FOCUS is sent.
*/ */
struct FL_EXPORT Fl_Menu_Item { struct FL_EXPORT Fl_Menu_Item {
const char *text; ///< menu item text, returned by label() const char *text; ///< menu item text, returned by label()
@ -490,14 +502,18 @@ struct FL_EXPORT Fl_Menu_Item {
The callback is called with the stored user_data() as its second argument. The callback is called with the stored user_data() as its second argument.
You must first check that callback() is non-zero before calling this. You must first check that callback() is non-zero before calling this.
*/ */
void do_callback(Fl_Widget* o) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, user_data_);} void do_callback(Fl_Widget* o, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) const {
Fl::callback_reason_ = reason; callback_(o, user_data_);
}
/** /**
Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument. Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument.
This call overrides the callback's second argument with the given value \p arg. This call overrides the callback's second argument with the given value \p arg.
You must first check that callback() is non-zero before calling this. You must first check that callback() is non-zero before calling this.
*/ */
void do_callback(Fl_Widget* o,void* arg) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, arg);} void do_callback(Fl_Widget* o, void* arg, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) const {
Fl::callback_reason_ = reason; callback_(o, arg);
}
/** /**
Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument. Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument.
@ -506,7 +522,9 @@ struct FL_EXPORT Fl_Menu_Item {
the callback. the callback.
You must first check that callback() is non-zero before calling this. You must first check that callback() is non-zero before calling this.
*/ */
void do_callback(Fl_Widget* o,long arg) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, (void*)(fl_intptr_t)arg);} void do_callback(Fl_Widget* o, long arg, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) const {
Fl::callback_reason_ = FL_REASON_SELECTED; callback_(o, (void*)(fl_intptr_t)arg);
}
/** Back compatibility only. /** Back compatibility only.
\deprecated \deprecated

2
src/Fl_MacOS_Sys_Menu_Bar.mm

@ -167,7 +167,7 @@ const char *Fl_Mac_App_Menu::quit = "Quit %@";
{ {
fl_lock_function(); fl_lock_function();
Fl_Menu_Item *item = (Fl_Menu_Item *)[(NSData*)[self representedObject] bytes]; Fl_Menu_Item *item = (Fl_Menu_Item *)[(NSData*)[self representedObject] bytes];
if ( item && item->callback() ) item->do_callback(NULL); if ( item && item->callback() ) item->do_callback(NULL, FL_REASON_SELECTED);
fl_unlock_function(); fl_unlock_function();
} }
- (void) setKeyEquivalentModifierMask:(int)value - (void) setKeyEquivalentModifierMask:(int)value

21
src/Fl_Menu.cxx

@ -146,6 +146,7 @@ class menuwindow : public window_with_items {
public: public:
menutitle* title; menutitle* title;
int handle(int) FL_OVERRIDE; int handle(int) FL_OVERRIDE;
void hide() override;
int itemheight; // zero == menubar int itemheight; // zero == menubar
int numitems; int numitems;
int selected; int selected;
@ -480,6 +481,11 @@ menuwindow::~menuwindow() {
delete title; delete title;
} }
void menuwindow::hide() {
set_selected(-1);
window_with_items::hide();
}
void menuwindow::position(int X, int Y) { void menuwindow::position(int X, int Y) {
if (title) {title->position(X, title->y()+Y-y());} if (title) {title->position(X, title->y()+Y-y());}
Fl_Menu_Window::position(X, Y); Fl_Menu_Window::position(X, Y);
@ -592,7 +598,20 @@ void menuwindow::draw() {
} }
void menuwindow::set_selected(int n) { void menuwindow::set_selected(int n) {
if (n != selected) {selected = n; damage(FL_DAMAGE_CHILD);} if (n != selected) {
if ((selected!=-1) && (menu)) {
const Fl_Menu_Item *mi = menu->next(selected);
if ((mi) && (mi->callback_) && (mi->flags & FL_MENU_CHATTY))
mi->do_callback(this, FL_REASON_LOST_FOCUS);
}
selected = n;
if ((selected!=-1) && (menu)) {
const Fl_Menu_Item *mi = menu->next(selected);
if ((mi) && (mi->callback_) && (mi->flags & FL_MENU_CHATTY))
mi->do_callback(this, FL_REASON_GOT_FOCUS);
}
damage(FL_DAMAGE_CHILD);
}
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

7
src/Fl_Menu_.cxx

@ -401,8 +401,11 @@ const Fl_Menu_Item* Fl_Menu_::picked(const Fl_Menu_Item* v) {
value_ = v; value_ = v;
if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) { if (when()&(FL_WHEN_CHANGED|FL_WHEN_RELEASE)) {
if (changed() || when()&FL_WHEN_NOT_CHANGED) { if (changed() || when()&FL_WHEN_NOT_CHANGED) {
if (value_ && value_->callback_) value_->do_callback((Fl_Widget*)this); if (value_ && value_->callback_) {
else do_callback(); value_->do_callback((Fl_Widget*)this, value_->user_data(), FL_REASON_SELECTED);
} else {
do_callback(FL_REASON_SELECTED);
}
} }
} }
} }

16
test/menubar.cxx

@ -61,7 +61,19 @@ void test_cb(Fl_Widget* w, void*) {
G_tty->printf("%s\n", m->label()); G_tty->printf("%s\n", m->label());
} }
void quit_cb(Fl_Widget*, void*) {exit(0);} void quit_cb(Fl_Widget*, void*) {
switch (Fl::callback_reason()) {
case FL_REASON_SELECTED:
exit(0);
case FL_REASON_GOT_FOCUS:
G_tty->printf("Selecting this menu item will quit this application!\n");
break;
case FL_REASON_LOST_FOCUS:
G_tty->printf("Risk of quitting averted.\n");
break;
default: break;
}
}
Fl_Menu_Item hugemenu[100]; Fl_Menu_Item hugemenu[100];
@ -70,7 +82,7 @@ Fl_Menu_Item menutable[] = {
{"&File",0,0,0,FL_SUBMENU}, {"&File",0,0,0,FL_SUBMENU},
{"&Open", FL_ALT+'o', 0, 0, FL_MENU_INACTIVE}, {"&Open", FL_ALT+'o', 0, 0, FL_MENU_INACTIVE},
{"&Close", 0, 0}, {"&Close", 0, 0},
{"&Quit", FL_ALT+'q', quit_cb, 0, FL_MENU_DIVIDER}, {"&Quit", FL_ALT+'q', quit_cb, 0, FL_MENU_DIVIDER|FL_MENU_CHATTY},
#if (OVERRIDE_SCALING_SHORTCUTS) #if (OVERRIDE_SCALING_SHORTCUTS)
{"CTRL/0", FL_COMMAND+'0', 0}, {"CTRL/0", FL_COMMAND+'0', 0},

Loading…
Cancel
Save