Next: XPopup Interaction, Up: XPopup [Contents][Index]
To define a new popup, use the following routines
int fl_newpup(Window parent); int fl_defpup(Window parent, const char *str, ...);
Both functions allocate and initialize a new popup menu and return the
XPopup identifier (or -1 on failure). fl_defpup()
in
addition accepts a pointer str
to the texts for menu items
(optionally also some more arguments, see below). More than one item
can be specified by using a vertical bar (|
) between the items,
e.g., "foo|bar"
adds two menu items. The parent
parameter specifies the window to which the XPopup belongs. In a
situation where the XPopup is used inside an object callback
FL_ObjWin(obj)
will do. If parent
is None
the
root window will be used.
Calling fl_defpup()
with the str
argument set to
NULL
is equivalent to calling fl_newpup()
.
It is possible to specify XPopup and item properties, such as
shortcuts, callbacks etc., together with the items texts using a
format string system similar as used for e.g., oprint(3)
. If
XPopup or item properties require arguments, they must be passed to
fl_defpup()
following the str
argument.
The following item properties are supported:
%t
Marks the item text as the XPopup title string.
%F
Binds a callback function to the XPopup as a whole that is called for
every selection made from this XPopup. You must specify the function
to be invoked in the parameters following str
. The value of the
selected item is passed as the only argument to the invoked callback
function. The callback function must return a non-negative integer. If
such a callback function has been registered for a XPopup and you
select its third item, in the simplest case 3 will be passed as a
parameter to the callback function (more complicated situations would
involve that the item had been assigned a different value. e.g., using
%x
, see below, or that there’s also a callback bound to the
item itself, in which case the global XPopup callback would receive
the return value of the items callback function).
%f
Binds a callback to this particular item which is invoked if the item
is selected. The routine must be supplied in the parameters following
str
. It has to return a non-negative integer. The value of the
selected item is passed as a parameter to this function. If you have
also bound the entire XPopup to a callback function via %F
,
then the function specified via %f
is called first with the
items value and its return value (if larger then 0
is then
passed as the parameter to to the function bound to the whole XPopup
(as set via %F
).
%i
Disables and greys-out the item. %d
can be used instead of %i
.
%l
Adds a line under the current entry. This is useful in providing visual clues to groups of entries
%m
Whenever this item is selected another (already defined) XPopup is
bound to the item so that the sub-XPopup is opened when the user moves
the mouse onto the item, This can be used to create cascading menus.
The identifier of the sub-XPopup to be shown must be provided in the
arguments following str
. It is the programmers responsibility
to make sure that the item values of the sub-XPopup don’t clash with
those of the higher-level XPopup or it may be impossible to determine
which item was selected.
%h
Specify a "hotkeys" that can be used to select this item. Hotkeys must
be given in the arguments following str
as a pointer to a
string. Use #
to specify that a key must be pressed together
with the <Alt>
key, ^
for simultaneous pressing of
<Ctrl>
and &n
for the function key Fn
.
%s
can be used instead of %h
.
%xn
Assigns a numerical value to this item. This value must be positive.
This new value overrides the default position-based value assigned to
this item. Different from most other flags, the value n
must be
entered as part of the text string (i.e., do not try to use the
arguments following str
to specify this value!) and must be
number larger than 0. It is the programmers responsibility to make
sure that the items value does not clash with those of other items of
the XPopup or determining which item was selected may be impossible.
%b
Indicates this item is "binary item" (toggle), currently in off state.
When displayed, binary items will be drawn with a small box to the
left. See also FL_PUP_BOX
.
%B
Same as %b
except that it also signifies that this item is in
on or "true" state and consequently is drawn with a checked box on the
left. See also FL_PUP_BOX | FL_PUP_CHECK
.
%rg
Specifies this menu item is a "radio item" belonging to group with
number g
, currently not being selected. The group number
g
, that must be part of the string directly following %r
(and not specified via the arguments following the string), must be a
non-zero, positive number. Radio items are drawn with a small diamond
box to the left (empty while not active). See also
FL_PUP_RADIO
.
%Rg
Same as %rg
except that it also sets the state of the radio
item as selected or "pushed", the item is drawn with a filled diamond
box to the left. See also fl_setpup_selection()
. See also
FL_PUP_RADIO | FL_PUP_CHECK
.
%%
Use this if you need a %
character in the string.
<Ctrl>H (\010
)
Same as %l
except that the character must precede the item
label, i.e., use "\010Abc"
and not "Abc\010"
.
Due to the use of variable arguments error checking can only be
minimal. Also note that if %x
is used to specify a value that
happens to be identical to a position-based value, the result is
unpredictable when subsequent references to these items are made.
There is currently a limit of
FL_MAXPUPI
(64) items per popup.
Tabs characters ('\t'
) can be embedded in the item string to
align different fields.
You can add more items to an existing XPopup using the following routine
int fl_addtopup(int popup_id, const char *str, ...);
where popup_id
is the value returned by
fl_newpup()
or fl_defpup()
for the XPopup.
Again, str
can contain information for one or more new items,
including the special sequences described earlier. The function
returns -1 if invalid arguments are detected (as far as possible for a
function with a variable number of arguments).
int fl_dopup(int popup_id);
This function displays the specified XPopup until the user makes a
selection or clicks somewhere outside of the XPopups box. The value
returned is the value of the item selected or -1 if no item (or a
disabled one) was selected. However, if there is a function bound to
the XPopup as a whole or to the selected item itself, this function is
invoked with the item value as the argument and the value returned by
fl_dopup()
is then the return value of this function. If
a callback function for both the selected item and the XPopup as a
whole exists, the callback function for the item is called first with
the item value as the argument and then the return value of this item
specific callback function is passed to the XPopups callback function.
fl_dopup()
then finally returns the return value of this
second function call.
Normally a XPopup get opened when the left mouse button has been pressed down and get closed again when the left mouse button is released. But there are a number of ways to achieve a "hanging" XPopup, i.e., that the XPopup that says open, even though the left mouse button isn’t pressed down anymore. This happens e.g., when the user releases the mouse button in the title area of the XPopup or when the XPopup was opened via a keyboard shortcut. In that case it’s also possible to navigate through the items and select via the keyboard.
A typical procedure may look as follows:
int item3_cb(int n) { return n + 7; } /* define the menu */ int menu = fl_newpup(parent); fl_addtopup(menu, "Title %t|Item1%rg1|Item2%Rg1|Item3%x10%f|Item4", item3_cb); switch (fl_dopup(menu)) { case 1: /* item1 is selected */ /* handle it */ break; case 2: /* handle it */ break; case 4: /* handle it */ case 17: /* item 3 call back has been executed */ }
Here callback function item3_cb()
is bound to the third item
and this item has been assigned the number 10. Thus, when it is
selected fl_dopup()
does not return 3 or 10. Instead the
callback function item3_cb()
is invoked with 10 as its
argument. And this function in turn returns 10 + 7
, which is
the value fl_dopup()
finally returns.
Note also that items 1 and 2 both are radio items, belonging to the same group (numbered 1). Item 2 is currently the active item of this group.
Sometimes it might be necessary to obtain the popup ID inside an item callback function. To this end, the following function available:
int fl_current_pup(void);
If no popup is active, the function returns -1. Until all callback functions have been run the function returns the ID of the XPopup the items belong to.
To destroy a popup menu and release all memory used, use the following routine
void fl_freepup(int popup_id);
For most applications, the following simplified API may be easier to use
void fl_setpup_entries(int popup_id, FL_PUP_ENTRIES *entries);
where popup_id
is the popup ID returned by
fl_newpup()
or fl_defpup()
and
entries
is an array of the following structures
typedef struct { const char * item_text; /* item text label */ FL_PUP_CB callback; /* item callback routine */ const char * shortcut; /* shortcut for this item */ unsigned int mode; /* item mode */ } FL_PUP_ENTRY;
The meaning of each member of the structure is as follows:
text
This is the text of a XPopup item. If text is NULL
, it
signifies the end of this popup menu. The first letter of the text
string may have a special meaning if it is one of the following:
'/'
This indicates the beginning of a sub-popup, starting with the next
item and ending with the next item with text
being NULL
.
'_'
Indicates that a line should be drawn below this item (typically as a visual reminder of logical groupings of items).
callback
This is the callback function that will be called when this particular
item is selected by the user. fl_dopup()
returns the
value returned by this callback. If the callback is NULL
, the
item number will be returned directly by fl_dopup()
.
shortcut
Specifies the keyboard shortcut.
mode
Specifies special attributes of this item. This can be one or a combination by bitwise OR of one of the following:
FL PUP NONE
FL_PUP_GREY
Item is greyed-out an can’t be selected. Trying to select it results
in fl_dopup()
returning -1.
FL_PUP_BOX
FL_PUP_RADIO
"Radio item", drawn with a little diamond-shaped box to its left. All radio items of the XPopup belong to the same group.
FL_PUP_CHECK
OR this value with FL_PUP_BOX
or FL_PUP_RADIO
to have
the box to the left drawn as checked or pushed.
With this simplified API, popup item values start from 1 and are the index in the entries array for the item plus 1. For example, the third element (with index 2) of the array of structure has an item value of 3. Please note that also elements of the array that end a submenu and thus don’t appear as visible items in the XPopup get counted. This way, the application can relate the value returned by fl_dopup() to the array easily. See demo program popup.c for an example use of the API.
To illustrate the usage of fl_setpup_entries()
, Fig 21.2
shows the popup created with the array of structures defined in the
following code example:
FL_PUP_ENTRY entries[ ] = { {"Top item1", callback}, /* item number 1 */ {"Top item2", callback}, {"Top item3", callback}, {"/Top item4", callback}, {"Sub1 item1", callback}, /* item number 5 */ {"Sub1 item2", callback}, {"Sub1 item3", callback}, {"Sub1 item4", callback}, {"/Sub1 item5", callback}, {"Sub2 item1", callback}, /* item number 10 */ {"Sub2 item2", callback}, {"Sub2 item3", callback}, {NULL, NULL }, /* end of level2, item number 13 */ {NULL, NULL }, /* end of sublevel1, item nuber 14 */ {"Top item5", callback}, /* item number 15 */ {NULL, NULL } /* end of popup */ };
Next: XPopup Interaction, Up: XPopup [Contents][Index]