The command template is stored in the file gui/commands.c. The command structure is a tree-like hierarchical structure where each node has a list of subcommands (commands with nonempty lists are called command categories) and a pointer to the next command in the same category. The command definition structure is this:
struct cmd { char * title; char * description; uns type; uns flags; char * icon_path; GdkPixbuf * icon_pixbuf; int accel; GdkModifierType modifier; union { struct { uns request_mask; int request_cnt; uns request_type; void (*modify_state_f)(struct cmd *, GtkWidget * widget); void (*action_f)(void *); } func; struct { struct of_state * of_state; } op; struct { uns flags; struct cmd * first; struct cmd * selected; } ctg; } spec; struct cmd * parent; struct cmd * next; };
The type
can be one of CT_FUNC
, CT_FACTORY_OP
, CT_CATEGORY
,
CT_SEPARATOR
and defines which part of the union spec
is used.
Function commands
The function commands have type equal to CT_FUNC
.
They are the most common menu or toolbar items. They contain an action function
action_f
to be called, a context request defining when the function can be called (and the
command enabled) and a modify_state_f
function to modify the command state
additionally. The command state (enabled, visible, checked, etc.)
is stored in the flags
bitmask together with
the command location and other flags.
The command request consists of:
request_mask
of all object types
for which the command can be used. The command is enabled if no selected
object has a type which is not included in the mask.
request_cnt
. Any positive value
means that exactly the requested number of objects should be selected.
Zero means that any count is suitable, and minus one stands for any
nonzero object count.
request_type
, one of RT_META
, RT_GROUP
and RT_ANY
. The first one means that the request count applies only to
meta objects (not GOs). The second one means that the count applies to
the count of selected GOs in the context group and RT_ANY
means that
both selections are evaluated together.
For example, consider the following command:
{ "Save", "Save the file", CT_FUNC, CL_UB_MENU | CL_VIEW_MENU | CS_VIS_EN, 0, 0, GDK_S, GDK_CONTROL_MASK, { .func = { VTM_DOCUMENT | VTM_CT_DOC, 1, RT_META, NULL, &on_file_save } }, NULL, &file_save_as_cmd };
It requests exactly one document (in the meta selection or in the context), is located in the Universe Browser menu and in the View menu, and is visible and enabled before the context evaluations take effect.
Context Match Evaluation and Command Execution When a command state needs to be evaluated, the command request is compared with the current context using the following function:
int context_matches( struct cmd * cmd );
First, the context window, group, tlo and document are tried. If any of them
satisfies the request, the conditions are fulfilled and the object will be
passed as the void *
argument of the
command's action function action_f
later when the command is executed.
If it is not the case, the selection is tried (meta
selection or selection within a group, depending on the request type). If neither
the selection is suitable, then the context object (the last used object) is
tried and if matches, it will later be passed as the void *
argument of the action
function. The selection is not passed as any argument; in case that the
action function gets a NULL
as the argument, it uses the selection.
After the evaluation of the context_matches
function,
the modify_state_f
function is called (with the menu/tool item widget
as an additional argument) to alter the command state according to some
additional criteria.
To prevent possible errors, the context match is verified one more time,
just before the command execution. It might happen that the menu or toolbar
item has been activated but the request ceased to be fulfilled before
the activation signals were distributed to our callbacks. Or the modify_state_f
function just had violated the evaluated flags and re-enabled a disabled
command. Both cases are detected with an additional context check and if
the context does not match, the command execution is cancelled.
Factory Operation Commands
These commands (with type equal to CT_FACTORY_OP
)
switch the GO Factory (see The GO Factory) into the given
state stored in of_state
.
They have no context requests as the states of GO Factory commands are
evaluated in a special way.
Categories
Category commands (with type equal to CT_CATEGORY
)
are not actually commands, they are just branching nodes and have a list of subcommands
(starting with first
).
They create submenus in menus, in toolbars, they are just expanded. In the View
toolbar, some categories have their icons and can expand their contents
into the right View toolbar.
The additional flags
store the flags of the category contents.
Separators
The separators have type equal to CT_SEPARATOR
and
represent separator menu items (invisible in toolbars).