All widgets that have a menu in fltk are subclassed off of the virtual base class Fl_Menu_. Currently Fltk provides you with Fl_Menu_Button, Fl_Menu_Bar, and Fl_Choice.
The Fl_Menu_ contains a pointer to an array
of structures of type Fl_Menu_Item.
These describe the contents of the menu. Usually the array is a large
initialization constant, but there are methods to build it
dynamically.
A sample menu defined by a C initialization constant:
struct Fl_Menu_Item
This structure is defined in <FL/Fl_Menu_Item.H>
struct Fl_Menu_Item {
const char* text; // label()
ulong shortcut_;
Fl_Callback* callback_;
void* user_data_;
int flags;
uchar labeltype_;
uchar labelfont_;
uchar labelsize_;
uchar labelcolor_;
};
enum { // values for flags:
FL_MENU_INACTIVE = 1,
FL_MENU_TOGGLE = 2,
FL_MENU_VALUE = 4,
FL_MENU_RADIO = 8,
FL_MENU_INVISIBLE = 0x10,
FL_SUBMENU_POINTER = 0x20,
FL_SUBMENU = 0x40,
FL_MENU_DIVIDER = 0x80,
FL_MENU_HORIZONTAL = 0x100
};
Fl_Menu_Item popup[] = { {"&alpha", FL_ALT+'a', the_cb, (void*)1}, {"&beta", FL_ALT+'b', the_cb, (void*)2}, {"gamma", FL_ALT+'c', the_cb, (void*)3, FL_MENU_DIVIDER}, {"&strange", 0, strange_cb}, {"&charm", 0, charm_cb}, {"&truth", 0, truth_cb}, {"b&eauty", 0, beauty_cb}, {"sub&menu", 0, 0, 0, FL_SUBMENU}, {"one"}, {"two"}, {"three"}, {0}, {"inactive", FL_ALT+'i', 0, 0, FL_MENU_INACTIVE|FL_MENU_DIVIDER}, {"invisible",FL_ALT+'i', 0, 0, FL_MENU_INVISIBLE}, {"check", FL_ALT+'i', 0, 0, FL_MENU_TOGGLE|FL_MENU_VALUE}, {"box", FL_ALT+'i', 0, 0, FL_MENU_TOGGLE}, {0}}; |
FL_SUBMENU
in
the flags field, and ends with a label() that is null. You can nest
menus to any depth. A pointer to the first item in the submenu can be
treated as an Fl_Menu array itself. It is also possible to make
seperate submenu arrays with FL_SUBMENU_POINTER
flags.
You should not use the member names to refer to the Fl_Menu_Item, instead use these methods:
const char* Fl_Menu_Item::label() const;
void Fl_Menu_Item::label(const char*);
void Fl_Menu_Item::label(Fl_Labeltype, const char*);
Fl_Labeltype Fl_Menu_Item::labeltype() const;
void Fl_Menu_Item::labeltype(Fl_Labeltype);
Fl_Color Fl_Menu_Item::labelcolor() const;
void Fl_Menu_Item::labelcolor(Fl_Color);
Fl_Font Fl_Menu_Item::labelfont() const;
void Fl_Menu_Item::labelfont(Fl_Font);
uchar Fl_Menu_Item::labelsize() const;
void Fl_Menu_Item::labelsize(uchar);
typedef void (Fl_Callback)(Fl_Widget*, void*);
Fl_Callback* Fl_Menu_Item::callback() const;
void Fl_Menu_Item::callback(Fl_Callback*, void* = 0);
void* Fl_Menu_Item::user_data() const;
void Fl_Menu_Item::user_data(void*);
void Fl_Menu_Item::callback(void (*)(Fl_Widget*, long), long = 0);
long Fl_Menu_Item::argument() const;
void Fl_Menu_Item::argument(long);
void Fl_Menu_Item::callback(void (*)(Fl_Widget*));
void Fl_Menu_Item::do_callback(Fl_Widget*);
void Fl_Menu_Item::do_callback(Fl_Widget*, void*);
void Fl_Menu_Item::do_callback(Fl_Widget*, long);
ulong Fl_Menu_Item::shortcut() const;
void Fl_Menu_Item::shortcut(ulong);
Sets exactly what key combination will trigger the menu item. The
value is a logical 'or' of a key and a set of shift flags, for
instance FL_ALT+'a'
or FL_ALT+FL_F+10
or
just 'a'. A value of zero disables the shortcut.
The key can be any value returned by Fl::event_key(), but will usually be an ascii letter. Use a lower-case letter unless you require the shift key to be held down.
The shift flags can be any set of values accepted by Fl::event_state(). If the bit is on that shift key must be pushed. Meta, Alt, Ctrl, and Shift must be off if they are not in the shift flags (zero for the other bits indicates a "don't care" setting).
int Fl_Menu_Item::submenu() const;
int Fl_Menu_Item::checkbox() const;
int Fl_Menu_Item::radio() const;
int Fl_Menu_Item::value() const;
void Fl_Menu_Item::set();
void Fl_Menu_Item::setonly();
void Fl_Menu_Item::clear();
int Fl_Menu_Item::visible() const;
void Fl_Menu_Item::show();
void Fl_Menu_Item::hide();
int Fl_Menu_Item::active() const;
void Fl_Menu_Item::activate();
void Fl_Menu_Item::deactivate();
const Fl_Menu_Item* Fl_Menu_Item::popup(
int X, int Y,
const char* title = 0,
const Fl_Menu_Item* picked = 0,
const Fl_Menu_* button = 0) const;
X,Y is the position of the mouse cursor, relative to the window that got the most recent event (usually you can pass Fl::event_x() and Fl::event_y() unchanged here).
title is a character string title for the menu. If non-zero a small box appears above the menu with the title in it.
The menu is positioned so the cursor is centered over the item picked. This will work even if picked is in a submenu. If picked is zero or not in the menu item table the menu is positioned with the cursor in the top-left corner.
button is a pointer to an Fl_Menu_ from which the color and boxtypes for the menu are pulled. If null then SGI-style defaults are used.
const Fl_Menu_Item* Fl_Menu_Item::pulldown(
int X, int Y, int W, int H,
const Fl_Menu_Item* picked = 0,
const Fl_Menu_* button = 0,
const Fl_Menu_Item* title = 0,
int menubar=0) const;
The title and menubar arguments are for internal use, don't use them.
const Fl_Menu_Item* Fl_Menu_Item::test_shortcut() const;
int Fl_Menu_Item::size();
const Fl_Menu_Item* Fl_Menu_Item::next(int=1) const;
Fl_Menu_Item* Fl_Menu_Item::next(int=1);
const Fl_Menu_Item* Fl_Menu_::menu() const ;
void Fl_Menu_::menu(const Fl_Menu_Item*);
int Fl_Menu_::value() const ;
const Fl_Menu_Item* Fl_Menu_::mvalue() const;
int Fl_Menu_::value(int);
int Fl_Menu_::value(const Fl_Menu_Item*);
int Fl_Widget::changed() const;
void Fl_Widget::set_changed();
void Fl_Widget::clear_changed();
Fl_When Fl_Widget::when() const;
void Fl_Widget::when(Fl_When);
FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED
. See Fl_Choice for a subclass that uses this.
See also Fl_Menu_Button::popup(void).
const Fl_Menu_Item* Fl_Menu_::test_shortcut();
void Fl_Menu_::global();
Currently there can be only one global() menu. Setting a new one will replace the old one. There is no way to remove the global() setting (including destroying the menu).
const char* Fl_Menu_::text() const ;
const char* Fl_Menu_::text(int i) const ;
int Fl_Menu_::size() const ;
int Fl_Menu_::add(const char *,const char *,Fl_Callback *,void
*v=0,int f=0);
Text is a string of the form "foo/bar/baz", this example will result in a submenu called "foo" and one in that called "bar" and and entry called "baz". The text is copied to new memory and can be freed. The other arguments are copied into the menu item unchanged.
If an item exists already with that name then it is replaced with this new one. Otherwise this new one is added to the end of the correct menu or submenu. The return value is the offset into the array that the new entry was placed at.
No bounds checking is done, the table must be big enough for all the entries you plan to add. Don't forget that there is a null terminator on the end, and the first time a item is added to a submenu three items are added (the title and the null terminator, as well as the actual menu item)
The return value is the index into the array that the entry was put.
int Fl_Menu_::add(const char *);
The return value is the index into the array that the last entry was put.
void Fl_Menu_::clear();
Delete all the menu items. Don't do this if you used menu(x) to set it to your own array. You should do this before destroying the Fl_Menu_ widget if it uses it's own array.
void Fl_Menu_::replace(int,const char *);
void Fl_Menu_::remove(int);
void Fl_Menu_::shortcut(int i, int n);
void Fl_Menu_::mode(int i,int x);
Fl_Font Fl_Menu_::textfont() const;
void Fl_Menu_::textfont(Fl_Font);
uchar Fl_Menu_::textsize() const;
void Fl_Menu_::textsize(uchar);
Fl_Color Fl_Menu_::textcolor() const;
void Fl_Menu_::textcolor(Fl_Color);
Fl_Boxtype Fl_Menu_::down_box() const;
void Fl_Menu_::down_box(Fl_Boxtype);
Normally any mouse button will pop up a menu and it is lined up below the button as shown in the picture. However an Fl_Menu_Button may also control a pop-up menu. This is done by setting the type(), see below.
The menu will also pop up in response to shortcuts indicated by putting a '&' character in the label(). See Fl_Button for a description of this.
Typing the shortcut() of any of the menu items will cause callbacks exactly the same as when you pick the item with the mouse. The '&' character in menu item names are only looked at when the menu is popped up, however.
When the user picks an item off the menu, the item's callback is done with the menu_button as the Fl_Widget* argument. If the item does not have a callback the menu_button's callback is done instead.
Fl_Menu_Button::Fl_Menu_Button(int,int,int,int,const char *
= 0);
void Fl_Widget::type(uchar);
Fl_Menu_Button::POPUP1, POPUP2, POPUP3, POPUP12, POPUP13,
POPUP23
, and POPUP123
are defined.
Fl_Menu_Button::POPUP3
is probably what you want.
A popup menu button is invisible and does not interfere with any events other than the mouse button specified (and any shortcuts). The widget can be stretched to cover all your other widgets, put it last in the hierarchy so it is "on top". Or you can make several widgets covering different areas for context-sensitive popup menus.
The popup menus appear with the cursor pointing at the previously selected item. This is a feature. If you don't like it, do value(0) after the menu items are picked to forget the current item.
const Fl_Menu* Fl_Menu_Button::popup();
The items on the bar and the menus they bring up are defined by a single Fl_Menu_Item array. Because a Fl_Menu_Item array defines a hierarchy, the top level menu defines the items in the menubar, while the submenus define the pull-down menus. Sub-sub menus and lower pop up to the right of the submenus.
If there is an item in the top menu that is not a title of a submenu, then it acts like a "button" in the menubar. Clicking on it will pick it.
When the user picks an item off the menu, the item's callback is done with the menubar as the Fl_Widget* argument. If the item does not have a callback the menubar's callback is done instead.
Submenus will also pop up in response to shortcuts indicated by putting a '&' character in the name field of the menu item. See Fl_Button for a description of this. If you put a '&' character in a top-level "button" then the shortcut picks it. The '&' character in submenus is ignored until the menu is popped up, to match Micro$oft behavior.
Typing the shortcut() of any of the menu items will cause callbacks exactly the same as when you pick the item with the mouse.
Currently the menu bar does not display as many attributes as a pop-up menu. Invisible and inactive items draw correctly. Checkboxes, divider lines, display of shortcuts, and perhaps other things are not drawn in the current version.
Fl_Menu_Bar::Fl_Menu_Bar(int, int, int, int, const char * =
0);
labelsize() and labelfont() and labelcolor() are used to control how the menubar items are drawn. They are initialized from the Fl_Menu static variables, but you can change them if desired.
label() is ignored unless you change the align() to put it outside the menubar.
The only difference between this and a Fl_Menu_Button is that the name of the most recent chosen menu item is displayed inside the box, while the label is displayed outside the box. However, since the use of this is most often to control a single variable rather than do individual callbacks, some of the Fl_Menu_Button methods are redescribed here in those terms.
When the user picks an item off the menu the value() is set to that item and then the callback is done.
All three mouse buttons pop up the menu. The Forms behavior of the first two buttons to increment/decrement the choice is not implemented. This could be added with a subclass, however.
The menu will also pop up in response to shortcuts indicated by putting a '&' character in the label(). See Fl_Button for a description of this.
Typing the shortcut() of any of the items will do exactly the same as when you pick the item with the mouse. The '&' character in item names are only looked at when the menu is popped up, however.
Fl_Choice::Fl_Choice(int,int,int,int,const char * =0);
int Fl_Choice::value() const ;
int Fl_Choice::value(int);
int Fl_Choice::value(const Fl_Menu *);
int Fl_Widget::changed() const;
void Fl_Widget::set_changed();
void Fl_Widget::clear_changed();
Fl_When Fl_Widget::when() const;
void Fl_Widget::when(Fl_When);
FL_WHEN_RELEASE
:0
: The callback is not done, instead changed() is
turned on.
FL_WHEN_RELEASE
: The callback is done when the user
picks an item.
FL_WHEN_RELEASE|FL_WHEN_NOT_CHANGED
: Does the callback
even if the user picks the same value.