GRAphical Programming for Eiffel index contents

Chapter VII. Menus

GROUP
   MENU
      SYSTEM_MENU

TILE
   MENU_ENTRY
      MENU_ITEM
      SUB_MENU_ITEM

A menu is one or more lists of application commands. Each command which is represented by a text string is called a menu item. By using your mouse or keyboard to choose a menu item, User directs the application to perform the command associated with that menu item. When User chooses a menu item, Windows sends to the application a command message that indicates which menu item User chose.

This chapter describes menus and explains how to use them in your applications. First we discuss the menus classes hierarchy and at the end include a complete example.


MENU_ENTRY

This class is a basic class implementing the general behavior of a menu entry. The kind of action to be done is determined in descendant classes. This class defines only some basic menu entry operations.

set_check_mark, remove_check_mark

Each menu item can be checked by a special mark as shown at the picture below. Using these two features you can trigger this property.

disable, enable

Each menu item can be disabled. In the disabled state a menu item does not respond on a user click. The disabled item appears as grayed. Using these two features you can trigger this property.

set_name (new_item_text : STRING)

Using this feature you can change the menu item text at any time.

make_separator

There is an additional creation procedure that produces a special kind of menu entries - separator. It looks like a delimiter line between the different groups of menu items. See the picture below.


Note You cannot check or disable a separator menu entry.




Figure 7.1 Menus classes.


MENU_ITEM

This class implements a basic menu item.

make (item_name : STRING, item_context : INTEGER, item_command : INTEGER)

Create a menu item with the text specified by the item_name parameter, the help context specified by item_context and the item command item_command. When an item is being checked it sends a message with code item_command to the owner. An item text can contain the ampersand character before any one character of the text e.g. "&New". It means that this item has a hotkey - Alt+N - and appears as "New" on the menu bar. The hotkey must be unique on the current submenu level.

command : INTEGER

This attribute contains the menu item command code.


SUBMENU_ITEM

This class implements a menu item, which response to its selection by activating another predefined popup menu. This class allows you to build multilevel menus.

make (sub_name : STRING, sub_context : INTEGER, sub_menu : MENU)

Create a submenu object with the specified name and context as a "head" for the sub_menu menu items group. See the example below.


MENU

Implements a pull down and pop-up menu structure. This class inherits from GROUP and is used as a container for the list of menu items.

make

Create an empty group.

add (entry : MENU_ENTRY)

Add a new entry into the group. It can be a separator, menu item, or submenu item (or anything else derived from class MENU_ENTRY). See the example below.

track (t : TILE; x, y : INTEGER)

This feature allows explicit displaying a popup menu in the specified location within the client area of the tile. The menu is centered horizontally.


Menu related features

There are special features which are used to support menus. Some of them we have already mentioned in the previous chapters. Here we assemble them together. Most of them are originally defined in class WINDOW.

make_menu : MENU

Redefine this function to build your own menu.

on_command( command_code : INTEGER ) : INTEGER

Each menu item has an associated command code. You are inspecting command_code to invoke the proper handler for the menu item selected inside this callback.

make_menu : MENU is
   do
     !!my_menu_item.make ("My item", IDM_MY_MENU_ITEM, 0)
     ...
   end
	
on_command ( cmd : INTEGER) is
   do 
     ...
     inspect cmd
       when IDM_MY_MENU_ITEM then
         ... Do something
on_menu_selection ( item_code : INTEGER )

This feature is called automatically by the GRAPE event manager when User is about to select an item from menu, which is attached to this WINDOW object.

In the example below this callback is used to show a proper item's hint on the application status line.

--
-- This application demonstrates how to use menu classes.
--
class MENUS_APPLICATION
   inherit
     APPLICATION
       redefine -- features dealed with menu:
         on_menu_selection, on_help_context_changed,
         on_command, make_menu, on_rbutton_down
       select
         on_menu_selection, on_help_context_changed,
         on_command, make_menu, on_rbutton_down, init
       end;

   creation
     make

   feature
     check_item : MENU_ITEM; -- this menu item will be checked
     disable_item : MENU_ITEM; -- this menu item will be disabled
----------------------------------------------------------------
     make_menu () : MENU is
         -- here we create main menu structure
       local
         popup : SUB_MENU_ITEM; -- for pull-down items
         menus : MENU; -- pull-down group
         level2: MENU; -- pull-down group
         entry : MENU_ENTRY; -- only for separator
         item : MENU_ITEM; -- for every menu item
       do

         !!Result.make_root; -- special creation proc for root menu

         !!menus.make; -- create new menu group
         !!item.make("E&xit", 0, IDM_QUIT ); -- create item
         menus.add(item); -- put it into group
         !!popup.make("&File", 0, menus ); -- create a submenu item
         Result.add(popup); -- add it to application menu

         !!menus.make; -- yet another group...
         !!check_item.make("Disable &next item", 0, IDM_CHECK );
         menus.add(check_item);
         !!entry.make_separator -- special entry - line separator
         menus.add(entry);
         !!disable_item.make("&Enabled", 0, IDM_DISABLE );
         menus.add(disable_item);
         !!entry.make_separator -- special entry - line separator
         menus.add(entry);

         !!level2.make;
         !!item.make("Yet", 0, IDM_NONE );
         level2.add(item);
         !!item.make("Another", 0, IDM_NONE );
         level2.add(item);
         !!item.make("Sub Menu", 0, IDM_NONE );
         level2.add(item);
         !!item.make("Level", 0, IDM_NONE );
         level2.add(item);
         !!popup.make("&Look it ", 0, level2 );
         menus.add( popup );

         !!popup.make("&Test me!", 0, menus );
         Result.add(popup);
       end;
     ----------------------------------------------------------------
     on_command ( cmd : INTEGER ) : INTEGER is
         -- This is a switch which responds to menu commands.
       local 
         de : EDIT_WINDOW ;
       do
         Result := processed;

         inspect cmd
           when IDM_NEW then
             !!de.make ( "Child" );
               desktop.add ( de );
           when IDM_CHECK then
             if check_item.checked then
               check_item.remove_check_mark
               check_item.enable -- ?
               disable_item.enable
               disable_item.set_name ("&Enabled")
             else
               check_item.set_check_mark
               disable_item.set_name ("&Disabled")
               disable_item.disable
             end
           when IDM_QUIT then
             terminate();
           else
                 Result := not_processed;
         end; -- inspect
       end; -- on_command
     ----------------------------------------------------------------
     on_rbutton_down ( xx, yy : INTEGER ) : INTEGER is
         -- build and display popup menu
       local
         menus : MENU;
         item : MENU_ITEM;
         entry : MENU_ENTRY;
       do
         !!menus.make;
         !!item.make("Popup", 0, IDM_NONE );
         menus.add(item);
         !!item.make("Menu", 0, IDM_NONE );
         menus.add(item);
         !!item.make("is &Simple", 0, IDM_NONE );
         menus.add(item);
         !!entry.make_separator
         menus.add(entry);
         !!item.make("E&xit", 0, IDM_QUIT );
         menus.add(item);
        
         menus.track( Current, xx, yy );
         
         Result := processed
       end -- on_rbutton_down

     ----------------------------------------------------------------
     on_menu_selection ( command_code : INTEGER ) : INTEGER is
         -- update application status line
       do
         on_help_context_changed ( command_code );
         Result := not_processed;
       end;
     ----------------------------------------------------------------
     on_help_context_changed ( new_context : INTEGER ) is
         -- update status line hint
       do
         if new_context /= context then
           context := new_context;
           inspect new_context
             when IDM_NONE then
               statusline.set_hint ( "Does nothing" );
             when IDM_QUIT then
               statusline.set_hint ( "Exit from the application" );
             else
               statusline.set_hint ( "" );
           end; -- inspect
         end; -- if 
       end; 

   feature -- commands

     IDM_NONE, IDM_CHECK, IDM_DISABLE, IDM_QUIT : INTEGER is unique;

   end -- class MENUS_APPLICATION

© Object Tools -- info@object-tools.com -- December 1999