The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

FLTK::Menu - Utility functions for Menu type widgets

Description

The Menu base class is used by Browser, Choice, MenuBar, PopupMenu, ComboBox, and other widgets. It is simply a Group and each item is a child Widget, but it provides functions to select and identify one of the widgets in the hierarchy below it and do that widget's callback directly, and functions to create and add Item and ItemGroup widgets to a hierarchy.

A Menu can take a pointer to a List object, which allows the user program to dynamically provide the items as they are needed. This is much easier than trying to maintain an array of Widgets in parallel with your own data structures.

It also provides several convienence functions for creating, rearranging, and deleting child Item and ItemGroup widgets.

Functions

add

my $item = $menu->add( $label, $shortcut, \&callback, $data, $flags );

Split label at / characters and add a hierachial Item.

Adds new items and hierarchy to a Menu or Browser.

$label

The label is split at / characters to automatically produce submenus. The submenus are created if they do not exist yet, and a new Item widget is added to the end of it.

A trailing / can be used to create an empty submenu (useful for forcing a certain ordering of menus before you know what items are in them).

Backslashes in the string "quote" the next character, which allows you to put forward slashes into a menu item.

$shortcut

0 for no shortcut, FLTK::CTRL | ord 'a' for Ctrl-a, etc.

$callback

Function to call when item picked. If undef, the callback for the Menu widget itself is called.

data

Second argument passed to the callback.

flags

Useful flags are:

INACTIVE makes the item grayed out and unpickable
INVISIBLE makes it not visible to the user, as though it was not there. This is most useful for making extra shortcuts that do the same thing.
RAW_LABEL stops it from interpreting & and @ characters in the label.

Import these with the :flags label.

Returns a pointer to the new Item. You can further modify it to get results that can't be gotten from these function arguments.

my $item = $menu->add( $label, $data );

Create a new Item and add it to the top-level of the hierarchy.

Unlike the add() with more arguments, this one does *not* split the label at / characters. The label is used unchanged.

$menu->add( $widget );

Add a widget to the menu.

add_group

my $newgroup = $menu->add_group( $label, $parent, $data );

Add a parent widget to a (possibly) lower level of the hierarchy, such as returned by add_group().

add_leaf

my $widget = $menu->add_leaf( $label, $parent, $data );

Add a non-parent widget to a (possibly) lower level of the hierarchy, such as returned by add_group(). If parent is null or this then this is the same as add(label,data).

add_many

my $last = $menu->add_many( $string );

This is a Forms (and SGI GL library) compatable add function, it adds many menu items, with | seperating the menu items, and tab seperating the menu item names from an optional shortcut string.

char * label

my $item = $menu->char * label( );

Returns the item with the given label.

This searches both the top level for an exact match, and splits the label at '/' to find an item in a hierarchy. Thus it matches the strings passed to both the long and short forms of add().

If the item is found, a pointer to it is returned, otherwise undef is returned.

child

my $kid = $menu->child( @indexes, $level );

! Calls list()->child(this, indexes, level). If an fltk::List is used, the returned widget may be a temporary data structure and may be overwritten by another call to child() in this <i>or any other Menu</i>!

my $kid = $menu->child( $index );

Returns the given top-level child. Same as child($index, 0).

This overrides the method of the same name on FLTK::Group. This is so that an FLTK::List can be used. However if no FLTK::List is specified the action is identical to FLTK::Group::child( $index ).

children

my $total = $menu->children( @indexes, $level );

Calls "$self->list()->child($self, $indexes, $level)"|FLTK::Menu/"list">. If an FLTK::List is used, the returned widget may be a temporary data structure and may be overwritten by another call to child( ) in this or any other Menu!

my $total = $menu->children( $index );

Returns the number of children of some child. Same as children([$i], 1).

my $total = $menu->children( );

Returns the number of children at the top level. Same as children(0,0).

This overrides the method of the same name on FLTK::Group. This is so that an FLTK::List can be used. However if no FLTK::List is specified the action is identical to FLTK::Group::children( ).

default_callback

$menu->default_callback( $widget, $data );

The default callback for Menu calls item()-do_callback()|FLTK::Widget/"do_callback"> but if user_data() is not null it is used instead of the item's user_data().

default_style

my $style = $menu->default_style( );

Get the style

$menu->default_style( $style );

Set the style.

draw_in

$menu->draw_in( $widget, @indexes, $level, $selected, $drawn_selected );

Draw the menu items inside the widget.

The widget's box() is drawn and the items are laid out exactly the same as for layout().

If $selected is greater or equal to zero then that item is drawn in a selected manner.

If $widget-damage()==DAMAGE_CHILD> then it is assummed that only the items indicated by $selected and $drawn_selected need to be redrawn. This is used for minimal update to move the selection from one item to the next.

execute

$menu->execute( $widget );

Calls do_callback(). First it sets item() to the given widget, so the callback code can see it.

Notice that this calls the callback on the Menu widget itself, not on the menu item. However the default callback for Menu widget does item()-do_callback()|FLTK::Widget/"do_callback"> so by default the callback for each menu item is done.

Callbacks for items can be disabled, so item()-when(WHEN_NEVER)|FLTK::Widget/"when"> will disable it for named item, but calling when(WHEN_NEVER) with menu instance will disable callbacks for all menu items (but not for the menu itself).

find_selected

my $index = $menu->find_selected( $widget, @indexes, $level, $mx, $my );

Return the index of the item that is under the location $mx, $my in the given widget, if the draw() method had been used to draw the items into the widget.

get_item

my $item = $menu->get_item( );

Sets and returns item() based on the focus_index() in this and each child group, thus restoring the value saved with set_item().

This either returns a non-group node, or child group that has an illegal Group::focus_index(), or undef if this focus_index() is illegal.

If an FLTK::List is used this will probably only go to the first child and not descend any further.

get_location

my $location = $menu->get_location( $widget, @indexes, $level, $index );

Return the bounding box of the given item inside the widget, if the draw() method had been used to draw the items into the widget.

global

$menu->global( );

Make the shortcuts for this menu work no matter what window has the focus when you type it (as long as FLTK::modal() is off). This is done by using FLTK::add_handler(). This FLTK::Menu widget does not have to be visible (ie the window it is in can be hidden, or it does not have to be put in a window at all).

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, and you cannot destroy the Menu!

This should probably also put the items on the the Mac menubar.

handle_shortcut

my $handled = $menu->handle_shortcut( );

Respond to the current FLTK::SHORTCUT or FLTK::KEY event by finding a menu item it matches and calling execute() on it. True is returned if a menu item is found, false if none. Items are searched for a matching shortcut() value. &x shortcuts are ignored, they are used only for navigating when the menu is visible.

If you use a List, only the top-most level items are searched for shortcuts. Recursion is done only if the children are Group widgets, and then only the actual children of that Group (not any List it may contain if it is another Menu) are searched. This is necessary because some Lists are infinite in size, and usually they don't have shortcuts anyway.

This will return invisible (but active) items, even though it is impossible to select these items with the gui. This is done so that more than one shortcut for an action may be given by putting multiple copies of the item in, where only the first is visible.

insert

my $item = $menu->insert( $index, $label, $shortcut, \&callback, $args, $flags );

Split label at / characters and add a hierachial Item.

Same rules as add() except the item is inserted at $index of the final menu. Use 0 to put it at the start. Any number larger or equal to the current item count adds the new item to the end.

my $item = $menu->insert( $index, $label, $data );

Create a new Item and add it to the top-level of the hierarchy.

Unlike the insert() with more arguments, this one does not split the label at / characters. The label is used unchanged.

$menu->insert( $widget, $index );

Insert a widget into the menu.

item

my $current = $menu->item( );

The "current item". In callbacks, this is the item the user clicked on. Otherwise you probably can't make any assumptions about it's value.

Browser::goto_index() sets this to the current item.

Since this may be the result of calling child() the returned structure may be short-lived if an FLTK::List is used.

my $item = $menu->item( $value );

You can set item() with the second call, useful for outwitting the callback. This does not produce any visible change for the user.

layout_in

$menu->layout_in( $widget, @indexes, $level );

Resize the widget to contain the menu items that are the children of the item indicated by indexes and level (use 0 for the immediate children).

If the widget has vertical() true the menu items are laid out one above the other, as is usally done in the pull-down menu below a menubar. w() is set to the widest item, and h() to the sum of all the heights.

If the widget has horizontal() true then the items are laid out in rows, wrapping only when w() is exceeded. w() is changed only if it is too small to contain the smallest item. h() is set to the total height of all the rows.

The box(), leading(), textfont(), textsize(), and perhaps other style attributes of the widget are used when figuring out the total size and the size of each item.

list

my $lst = $menu->list( );

Returns the List that generates widgets for the menu.

$menu->list( $list );

Set the List that generates widgets for the menu. By default this is a dummy List that returns the child widgets of the Menu.

new

my $self = $menu->new( $x, $y, $w, $h, $label, $begin );
my $selected = $menu->popup( $rect, $title, $menubar );

Create and display a pop-up menu (or hierarchy of menus) showing the children of this Menu, then wait until the user picks an item or dismisses the menu. If the user picks an item then execute() is called for it and true is returned. False is returned if the user cancels the menu.

If there is a selected item in the menu (as determined by get_item()) then submenus are opened and all of them are positioned intitially so the mouse cursor is pointing at the selected item. This is incredibly useful and one of the main features of fltk that is missing from other toolkits.

rect describes a rectangle ($x, $y, $w, $h) that the current menu item should be centered over, and the menu is widened horizontally to $w if it is narrower. The coordinates are measured relative to the widget whose handle() method is being executed now.

$title is a widget (usually an FLTK::Item) that is used to make a title atop the menu, in the style of SGI's popup menus. You cannot use a List child, as the drawing of the menu may navigate that list to other children, overwriting the original widget.

$menubar is for internal use by menubars and should be left false.

remove

$menu->remove( $label );

Does "$menu-find( $label )"|FLTK::Menu/"find"> and then deletes that widget.

$menu->remove( $index );

Deletes the $indexth widget.

$menu->remove( $widget );

Deletes $widget.

replace

my $widget = $menu->replace( $label, $shortcut, \&callback, $data, $flags );

Split label at / characters and add or replace a hierachial Item.

Same rules as add() except if the item already exists it is changed to this new data, instead of a second item with the same label being created.

If the $label has any @ or & commands in any portion, that portion is relabelled, thus you can use this to change the appearance of existing menu items. However if the new label does not have any such commands, the label remains as before, with any older @-commands.

my $widget = $menu->replace( $label, $shortcut );

Create or replace an Item at the top-level of the hierarchy.

The top level is searched for an item that matches the given label. If found it's data is changed to the passed data, if not found a new Item is created and added at the end.

$menu->replace( $index, $widget );

Replace the $indexth item with $widget.

$menu->replace( $old, $new );

Replace the $old widget with the $new widget.

set_item

my $changed = $menu->set_item( @indexes, $level );

Remembers a currently selected item in a hierarchy by setting the focus_index() of each group to point to the next one. The widget can then be recovered with get_item(). A redraw(DAMAGE_VALUE) is done so pulldown menus redraw their display.

value

my $index = $menu->value( );

Same as FLTK::Group::focus_index.

my $changed = $menu->value( $index );

Convienence function to do set_item() when there is only one level of hierarchy. In this case you can consider the menu items to be indexes starting at zero.

Author

Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/

License and Legal

Copyright (C) 2008-2010 by Sanko Robinson <sanko@cpan.org>

This program is free software; you can redistribute it and/or modify it under the terms of The Artistic License 2.0. See the LICENSE file included with this distribution or notes on the Artistic License 2.0 for clarification.

When separated from the distribution, all original POD documentation is covered by the Creative Commons Attribution-Share Alike 3.0 License. See the clarification of the CCA-SA3.0.