home *** CD-ROM | disk | FTP | other *** search
- <html>
- <title>Menus</title>
- <h1>Menus</h1>
-
-
- This section describes how menus are used in Vista. Vista provides a powerful and
- easy-to-use menu system. The menu defintions are read from a file held in the
- Resources directory with filename 'Menus'. This file contains a textual
- description of the menus in a syntax specially written for menu definition.
- Each menu has a name. This is an alphanumeric string by with the menu is known
- and can be referred to. Interaction between the user application and menus is
- through use of the menu name.
- <p>
- A menu consists of a number of entries. Each entry has a name and are numbered
- internally from 0 (at the top of the menu). An entry also has a set of characteristics
- which tell the WIMP how to display it.
- <p>
- Vista will display the menu on the screen in response to the user clicking 'menu'
- over a window. The menu displayed can either be set when the window is created,
- or can be created dynamically as the program runs. The simplest way
- to use menus is to supply default menus when creating windows. If the name of
- a menu is supplied to the Window constructor then Vista will automatically display
- this menu when the user clicks 'menu' over the window.
- <p>
- The more complex (and flexible) way is not to supply a default menu, but
- provide a function called <a href="file:window#get_menu">get_menu</a>
- which returns the name of a menu to use.
- This function will be called when the user clicks 'menu'. The 'get_menu' function
- can either use a predefined menu (in the Menus file) or can build a new one.
- <p>
- In either case, the derived class can modify the menu to be displayed by providing
- a function called <a href="file:window#pre_menu">pre_menu</a>.
- This is called just before Vista displays the
- menu on the screen.
- <p>
- When the user selects a menu item, the function <a href="file:window#menu">menu</a> is called.
- By default in the
- Window class this does nothing, but a derived class can provide its own function to
- act on the user's selection. The 'menu' function is called with an array <br>
- of <a href="file:menu#menuitem">MenuItem</a>
- classes. Each element in this array holds information about the users's selection at
- that level in the menu hierarchy. The first item holds information about the selection
- in the topmost menu, the second item holds information about its submenu, and so
- on until the end of the menu tree which is marked by the menuitem with index -1 and
- name NULL (NULL pointer that is).
- <p>
- <p>
- Each menu item can be converted to either an integer or a char *. The integer conversion
- can be used in a switch statement and returns the index of the item into the menu. The
- index starts at 0. The char * conversion can be used to obtain the name of the
- menu item.
-
- <p>
- <a name="define"></a>
- <h2>Defining menus</h2>
-
- Menus are defined in a file called 'Menus' held in the application's resources directory.
- This is a text file which contains all the menu definitions for the application.
- The definitions are written in a special syntax which allows all the the characteristics
- of the menu items to be specified.
- <p>
- In order to describe the menu definition syntax, we first need to define a few terms:
- <p>
- <ul>
- <li><b>Identifier:</b> A sequence of alphanumeric characters beginning with a letter or
- underscore. Examples: main_menu, m1, _my_menu_124
-
- <li><b>String:</b> A sequence of any characters (excluding newline) enclosed in double
- quotes ("). The usual C language escapes may be used (\n, \r etc) and
- quotes themselves must be escaped. Examples: "hello", "123\n456",
- "item \"1\":"
-
- <li><b>Keyword:</b> An identifier which means something special to the system. Keywords
- may not be used as identifiers. Examples: menu, writeable.
-
- <li><b>Number:</b> A sequence of digits representing a decimal number.
-
- <li><b>Braces:</b> The characters sometimes known as "curly brackets": { and }
- </ul>
- <p>
-
- A menu defintion file is free format (line breaks don't matter) and can contain
- any number of blank lines and comments. A comment starts with a hash (#) and
- continues to the end of line. It consists of a sequence of menu definitions the
- last of which must be followed by a newline.
- <p>
- A menu definition starts with the keyword 'menu' and is followed by an identifier
- specifying the menu name. This is followed by a string which contains
- the title which will be displayed on the menu. Then follows an equals sign (=)
- and a brace enclosed set of menu items.
- <p>
- For example:
- <pre>
-
- menu main_menu "Easy C++" = {
- ...
- }
-
- </pre>
- Within the braces of the menu definition are the menu items. A menu item starts with
- an identifier specifying the name of the item and it followed by a string which contains
- the characters which will be displayed in the menu on the screen. This may be
- followed by a colon (:) and a set of characteristics for the item.
- The characteristics specify how the item will appear on the screen. If more than
- one characteristic is needed, then they must be separated by commas. A
- characteristic starts with a keyword and may contain parameters (enclosed
- in round brackets). The end of a menu item is marked by a semicolon.
- <p>
- The following characteristics are available.
- <pre>
-
- Keyword Parameters Meaning
- ------- ---------- -------
-
- ticked none The item will have a tick to the left
- writeable size, valid The item is writeable. The 'size' parameter
- is a number specifying the maximum buffer
- size allocated to it. The 'valid' parameter
- is a string specifying the validation string
- separator none The item will be followed by a separating
- line in the menu.
- message none The item will have an arrow displayed to the
- right and will generate a
- Message_MenuWarning when the pointer
- crosses this arrow
- open none
- window none Item has a submenu and it is a window
- handle.
- menu none This item has a sub menu. The keyword is
- followed either by a new menu definition
- (without the menu name) or by a menu
- name specifying a previous menu definition.
-
- </pre>
- Of the above characteristics, the sub-menu one is the most complex and needs more
- explanation. If you want a menu item to have a sub-menu off to the right, then use
- the 'menu' characteristic. A few examples will help:
- <p>
- This example shows how a sub-menu for specifying quitting options can be done
- using an inline menu item definition:
- <pre>
-
- menu fred "Fred" = {
- item1 "Item 1" ;
- quit "Quit": menu "Quit options" { # note: no menu name or =
- all "All" ;
- front_end "Front end" ;
- } ; # note semicolon
- }
-
- </pre>
-
- Note that the inline definition does not contain a menu name or equals sign and
- must be followed by a semicolon (to mark the end of the item). Other than that
- the definition is exactly as a menu definition.
- <p>
- Alternatively, the following shows how a previous menu definition may be used:
- <pre>
-
- # quit menu
-
- menu quit "Quit options" = {
- all "All" ;
- front_end "Front end" ;
- }
-
- menu joe "Joe" = {
- item1 "Item 1" ;
- quit "Quit": menu quit ; # use previous quit menu
- }
-
- </pre>
- There is no limit to the reuse of menus within menus.
- <p>
- Finally, here is an example of a menu using most of the above syntax:
- <pre>
-
- #
- # Game iconbar menu
- #
-
- menu quit "Quit options" = {
- all "All" ;
- front_end "Front end" ;
- }
-
- menu iconbar "Game" = {
- info "Info": message ;
- new_game "New game" ;
- level "Level": menu "Level" {
- trivial "Trivial": ticked ;
- easy "Easy" ;
- hard "Hard" ;
- custom "Custom": menu "Custom level" {
- level "" : writeable (256, "") ;
- } ;
- } ;
- self "Self play": ticked ;
- quit "Quit" : menu quit ;
- }
-
- </pre>
-
- The layout of a menu file is up to you. I have used a layout I liked, but you may
- do whatever you like.
- <p>
-
- Another way of creating menus is to use the classes involved directly. The menu
- handling code in Vista makes use of two classes: Menu and MenuItem. These are
- shown below:
- <p>
- <a name="menuitem"></a>
- <pre>
-
- class MenuItem
- {
- friend class Menu ;
- public:
- enum menu_item_flags
- {
- TICKED = 1,
- SEPARATOR = 1 << 1,
- WRITEABLE = 1 << 2,
- MENUWARNING = 1 << 3,
- OPENANYWAY = 1 << 4,
- LAST = 1 << 7,
- TITLEINDIRECTED = 1 << 8
- } ;
- MenuItem(char *name, Menu *menu, char *text, int length) ; // text entry
- MenuItem(char *name, Menu *menu, char *sprite, void *sprite_area) ; // sprite entry
- void tick() ; // tick item
- void untick() ; // untick item
- void fade() ; // grey out item
- void unfade() ; // ungrey out item
- int flags(int f = 0, int m = 0) ; // set and read flags
- operator int() ; // convert to index
- operator char*() ; // convert to name
- int is_ticked() ; // is item ticked
- int is_faded() ; // is item faded
- void set_submenu (Menu *submenu) ;
- void make_writeable (char *buffer, int length, char *valid) ;
- void print (char *format ...) ; // print to the menu item
- void vprint (char *format, va_list ap) ;
- void read (int &) ; // read a number
- void read (char *) ; // read a string
- private:
- char *name ;
- MenuItem *next ; // next in list
- Menu *menu ; // menu I am in
- int index ; // index into menu
- Menu *submenu ; // my submenu
- } ;
-
- class Menu
- {
- friend class MenuItem ;
- friend class MenuSet ;
- public:
- Menu (char *name, char *title) ; // create a new menu with name given
- Menu (char *name, char *title, MenuItem *item) ; // create a sub menu
- ~Menu() ;
- MenuItem *selection(int *hits) ; // translate a selection
- MenuItem *item (char *iname) ; // get an item from its name
- void print (char *item, char *format ...) ;
- void read (char *item, char *s) ;
- void read (char *item, int &i) ;
- void finish() ; // close off a menu
- void open (int x, int y) ; // open the menu on the screen
- void close() ; // close the menu
- void iconbar_adjust (int &x, int &y) ; // adjust for iconbar display
- private:
- void init(char *name, char *title) ; // initialisation
- int add_item (MenuItem *item) ; // add a new item and return its index
- char *name ; // name of menu
- Menu *next ; // next in list
- MenuData *data ; // actual menu data
- MenuItem *items ; // list of items
- int num_items ; // number of items
- int max_items ; // max space for items
- int max_width ;
- } ;
-
- </pre>
-
- A MenuItem is one of the items of a menu. The class contains constructors which allow
- a new item to be constructed inside an existing menu. It also contains methods
- which allow the item to be read and written to.
- <p>
- A Menu class represents one menu. It contains a linked list of MenuItems which
- are the items of the menu. It also contains methods which allow items to be
- created, written to and read from. You can also obtain a pointer to a MenuItem
- when you have its name.
- <p>
- To create a menu from scratch you first need to create a new Menu object:
- <pre>
-
- Menu *m = new Menu (name, title) ;
-
- </pre>
- This creates a new Menu object given its name and title.
- <p>
- Once this is created you add the items to the menu. To add an item you simply create
- it and pass the menu pointer to it as the second parameter.
- <pre>
-
- MenuItem *i = new MenuItem (name, m, text, text_length) ;
-
- </pre>
- This will create a new item with the name given and add it to the end of the menu 'm'.
- <p>
- When all the items have been added to the menu, finish off by calling the 'finish'
- function for the menu:
- <pre>
-
- m->finish() ;
-
- </pre>
- To create sub-menus you use the Menu constructor which takes a MenuItem pointer as its
- third parameter. To this parameter you pass the address of the MenuItem for which
- you wish to add a sub-menu.
- <pre>
-
- MenuItem *item2 ;
- ...
- Menu *sub = new Menu (name, title, item2) ;
-
- </pre>
- Creates a new menu which will be a sub-menu of the item pointed to by 'item2'.
- <p>
- The easiest way to see how to construct menus "from first principles" is to look
- at the Vista source in the file c.menu. The functions parse_menu, parse_menu_details
- and parse_item are the main menu creation functions for menus created using the
- Menus file.
-
-
- <p>
- <a name="display"></a>
- <h2>Displaying menus</h2>
-
-
- Vista displays menus whenever the user clicks 'menu' over one of the windows known
- to Vista. In order for Vista to display a menu it needs to know the name of the
- menu to display. This can be obtained in 2 ways:
- <p>
- <ol>
-
- <li>By using the name supplied in the constructor to the task or window.
- <li>By asking the task or window to supply one.
- </ol>
- <p>
- In the first case the action of Vista is trivial - it simply displays the menu
- given. In the second case, it first calls a function called
- <a href="file:task#get_iconbar_menu">get_iconbar_menu</a> for<br>
- a task or <a href="file:window#get_menu">get_menu</a> for a
- window (or Icon or Object)
- These functions take some parameters
- and return the name of the menu to display. If you don't want to display
- any menu simple return NULL. The parameters passed are sufficient to enable the
- task or window to decide on the menu. The default action of the Task, Window, Object
- and Icon classes is to return NULL.
- <p>
- The 'get_iconbar_menu' and 'get_menu' functions may either return the name
- of a previously created menu or may create a new one. In order to create a new
- menu, have a look at the previous section. Creating new menus from
- scratch is non-trivial and should probably be avoided if possible.
- <p>
- <p>
-
- Once Vista has obtained the name of a menu to display it calls a function <br>
- called
- <a href="file:task#pre_menu">pre_menu</a> to allow the task or window to modify the menu.
- The 'pre_menu' function
- is passed a pointer to a Menu class and a set of parameters showing the current
- mouse position. In the pre_menu function, the program may modify any of the menu
- items using the 'print' function which allows the contents of any item to be
- written to. This takes the following parameters:
- <pre>
-
- void Menu::print (char *item, char *format ...)
-
- </pre>
- The first parameter is the name of the item to print to. The second is a printf
- style format string. The rest of the paramaters depend in the contents of the
- format string.
-
-
- <p>
- <a name="act"></a>
- <h2>Acting on menu selections</h2>
-
- When the user clicks on a menu selection the virtual function <a href="file:task#menu">menu</a>
- is called for
- either the window, task, icon or object If you override this function in your own derived class
- then this is called.
- <p>
- When in the 'menu' function, you are passed an array of MenuItems. Each of these items
- can be converted to either an integer or a string (char *). This lets you use a
- switch statement to find out which menu item is selected:
- <p>
- For example:
- <pre>
-
- void MainWindow::menu(MenuItem items[])
- {
- switch (items[0])
- {
- case 1:
- if (items[0].is_ticked())
- items[0].untick() ;
- else
- items[0].tick() ;
- break ;
- case 4:
- char str[256] ;
- items[1].read (str) ;
- char *s = items[1] ;
- break ;
- }
- }
-
- </pre>
-
- You can read the value of an item (useful for writeable menu items) by use of the 'read'
- method.
-
-
-
-