home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / programming / vista_1 / !Manual_manual_menu < prev    next >
Encoding:
Text File  |  1996-01-25  |  16.1 KB  |  428 lines

  1. <html>
  2. <title>Menus</title>
  3. <h1>Menus</h1>
  4.  
  5.  
  6. This section describes how menus are used in Vista.  Vista provides a powerful and
  7. easy-to-use menu system.  The menu defintions are read from a file held in the
  8. Resources directory with filename 'Menus'.  This file contains a textual 
  9. description of the menus in a syntax specially written for menu definition.
  10. Each menu has a name.  This is an alphanumeric string by with the menu is known
  11. and can be referred to.  Interaction between the user application and menus is
  12. through use of the menu name.
  13. <p>
  14. A menu consists of a number of entries.  Each entry has a name and are numbered
  15. internally from 0 (at the top of the menu).  An entry also has a set of characteristics
  16. which tell the WIMP how to display it.
  17. <p>
  18. Vista will display the menu on the screen in response to the user clicking 'menu'
  19. over a window.  The menu displayed can either be set when the window is created, 
  20. or can be created dynamically as the program runs.  The simplest way
  21. to use menus is to supply default menus when creating windows.  If the name of
  22. a menu is supplied to the Window constructor then Vista will automatically display
  23. this menu when the user clicks 'menu' over the window.
  24. <p>
  25. The more complex (and flexible) way is not to supply a default menu, but
  26. provide a function called <a href="file:window#get_menu">get_menu</a> 
  27. which returns the name of a menu to use.
  28. This function will be called when the user clicks 'menu'.  The 'get_menu' function
  29. can either use a predefined menu (in the Menus file) or can build a new one.
  30. <p>
  31. In either case, the derived class can modify the menu to be displayed by providing
  32. a function called <a href="file:window#pre_menu">pre_menu</a>.  
  33. This is called just before Vista displays the
  34. menu on the screen.
  35. <p>
  36. When the user selects a menu item, the function <a href="file:window#menu">menu</a> is called.  
  37. By default in the
  38. Window class this does nothing, but a derived class can provide its own function to
  39. act on the user's selection.  The 'menu' function is called with an array <br>
  40. of <a href="file:menu#menuitem">MenuItem</a>
  41. classes.  Each element in this array holds information about the users's selection at
  42. that level in the menu hierarchy.  The first item holds information about the selection
  43. in the topmost menu, the second item holds information about its submenu, and so
  44. on until the end of the menu tree which is marked by the menuitem with index -1 and
  45. name NULL (NULL pointer that is).
  46. <p>
  47. <p>
  48. Each menu item can be converted to either an integer or a char *.  The integer conversion
  49. can be used in a switch statement and returns the index of the item into the menu.  The
  50. index starts at 0.  The char * conversion can be used to obtain the name of the 
  51. menu item.
  52.  
  53. <p>
  54. <a name="define"></a>
  55. <h2>Defining menus</h2>
  56.  
  57. Menus are defined in a file called 'Menus' held in the application's resources directory.
  58. This is a text file which contains all the menu definitions for the application.
  59. The definitions are written in a special syntax which allows all the the characteristics
  60. of the menu items to be specified.
  61. <p>
  62. In order to describe the menu definition syntax, we first need to define a few terms:
  63. <p>
  64. <ul>
  65. <li><b>Identifier:</b>  A sequence of alphanumeric characters beginning with a letter or
  66.                 underscore.  Examples: main_menu, m1, _my_menu_124
  67.                 
  68. <li><b>String:</b>      A sequence of any characters (excluding newline) enclosed in double
  69.                 quotes (").  The usual C language escapes may be used (\n, \r etc) and
  70.                 quotes themselves must be escaped.  Examples: "hello", "123\n456", 
  71.                 "item \"1\":"
  72.                 
  73. <li><b>Keyword:</b>     An identifier which means something special to the system.  Keywords
  74.                 may not be used as identifiers.  Examples: menu, writeable.
  75.  
  76. <li><b>Number:</b>      A sequence of digits representing a decimal number.  
  77.  
  78. <li><b>Braces:</b>      The characters sometimes known as "curly brackets": { and }
  79. </ul>
  80. <p>
  81.  
  82. A menu defintion file is free format (line breaks don't matter) and can contain
  83. any number of blank lines and comments.  A comment starts with a hash (#) and
  84. continues to the end of line.  It consists of a sequence of menu definitions the
  85. last of which must be followed by a newline.
  86. <p>
  87. A menu definition starts with the keyword 'menu' and is followed by an identifier 
  88. specifying the menu name.  This is followed by a string which contains
  89. the title which will be displayed on the menu.  Then follows an equals sign (=)
  90. and a brace enclosed set of menu items.
  91. <p>
  92. For example:
  93. <pre>
  94.  
  95. menu main_menu "Easy C++" = {
  96.    ...
  97.    }
  98.  
  99. </pre>
  100. Within the braces of the menu definition are the menu items.  A menu item starts with
  101. an identifier specifying the name of the item and it followed by a string which contains
  102. the characters which will be displayed in the menu on the screen.  This may be
  103. followed by a colon (:) and a set of characteristics for the item.  
  104. The characteristics specify how the item will appear on the screen.  If more than 
  105. one characteristic is needed, then they must be separated by commas.  A 
  106. characteristic starts with a keyword and may contain parameters (enclosed 
  107. in round brackets).  The end of a menu item is marked by a semicolon.
  108. <p>
  109. The following characteristics are available.
  110. <pre>
  111.  
  112.     Keyword    Parameters    Meaning
  113.     -------    ----------    -------
  114.  
  115.     ticked     none          The item will have a tick to the left
  116.     writeable  size, valid   The item is writeable.  The 'size' parameter
  117.                              is a number specifying the maximum buffer 
  118.                              size allocated to it.  The 'valid' parameter 
  119.                              is a string specifying the validation string
  120.     separator  none          The item will be followed by a separating 
  121.                              line in the menu.
  122.     message    none          The item will have an arrow displayed to the
  123.                              right and will generate a 
  124.                              Message_MenuWarning when the pointer 
  125.                              crosses this arrow
  126.     open       none                
  127.     window     none          Item has a submenu and it is a window
  128.                              handle.
  129.     menu       none          This item has a sub menu.  The keyword is
  130.                              followed either by a new menu definition 
  131.                              (without the menu name) or by a menu 
  132.                              name specifying a previous menu definition.                            
  133.  
  134. </pre>
  135. Of the above characteristics, the sub-menu one is the most complex and needs more
  136. explanation.  If you want a menu item to have a sub-menu off to the right, then use
  137. the 'menu' characteristic.  A few examples will help:
  138. <p>
  139. This example shows how a sub-menu for specifying quitting options can be done
  140. using an inline menu item definition:
  141. <pre>
  142.  
  143. menu fred "Fred" = {
  144.    item1 "Item 1" ;
  145.    quit "Quit": menu "Quit options" {        # note: no menu name or =
  146.                    all "All" ;
  147.                    front_end "Front end" ;
  148.                    } ;                       # note semicolon
  149.    }
  150.  
  151. </pre>
  152.  
  153. Note that the inline definition does not contain a menu name or equals sign and
  154. must be followed by a semicolon (to mark the end of the item).  Other than that
  155. the definition is exactly as a menu definition.
  156. <p>
  157. Alternatively, the following shows how a previous menu definition may be used:
  158. <pre>
  159.  
  160. # quit menu
  161.  
  162. menu quit "Quit options" = {
  163.    all "All" ;
  164.    front_end "Front end" ;
  165.    }   
  166.  
  167. menu joe "Joe" = {
  168.    item1 "Item 1" ;
  169.    quit "Quit": menu quit ;            # use previous quit menu
  170.    }   
  171.  
  172. </pre>
  173. There is no limit to the reuse of menus within menus.
  174. <p>
  175. Finally, here is an example of a menu using most of the above syntax:
  176. <pre>
  177.  
  178. #
  179. # Game iconbar menu
  180. #
  181.  
  182. menu quit "Quit options" = {
  183.    all "All" ;
  184.    front_end "Front end" ;
  185.    }   
  186.  
  187. menu iconbar "Game" = {
  188.    info "Info": message ;
  189.    new_game "New game" ;
  190.    level "Level": menu "Level" {
  191.                     trivial "Trivial": ticked ;
  192.                     easy "Easy" ;
  193.                     hard "Hard" ;
  194.                     custom "Custom": menu "Custom level" {
  195.                                         level "" : writeable (256, "") ;
  196.                                         } ;
  197.                     } ;
  198.    self "Self play": ticked ;
  199.    quit "Quit" : menu quit ;
  200.    }
  201.  
  202. </pre>
  203.  
  204. The layout of a menu file is up to you.  I have used a layout I liked, but you may
  205. do whatever you like.
  206. <p>
  207.  
  208. Another way of creating menus is to use the classes involved directly.  The menu
  209. handling code in Vista makes use of two classes: Menu and MenuItem.  These are
  210. shown below:
  211. <p>
  212. <a name="menuitem"></a>
  213. <pre>
  214.  
  215. class MenuItem
  216.    {
  217.    friend class Menu ;
  218.    public:
  219.       enum menu_item_flags
  220.          {
  221.          TICKED = 1,
  222.          SEPARATOR = 1 << 1,
  223.          WRITEABLE = 1 << 2,
  224.          MENUWARNING = 1 << 3,
  225.          OPENANYWAY = 1 << 4,
  226.          LAST = 1 << 7,
  227.          TITLEINDIRECTED = 1 << 8
  228.          } ;
  229.       MenuItem(char *name, Menu *menu, char *text, int length) ;                        //  text entry
  230.       MenuItem(char *name, Menu *menu, char *sprite, void *sprite_area) ;   // sprite entry
  231.       void tick() ;                 //  tick item
  232.       void untick() ;               // untick item
  233.       void fade() ;                 // grey out item
  234.       void unfade() ;               // ungrey out item
  235.       int flags(int f = 0, int m = 0) ;     // set and read flags
  236.       operator int() ;                 // convert to index
  237.       operator char*() ;               // convert to name
  238.       int is_ticked() ;                // is item ticked
  239.       int is_faded() ;                 // is item faded
  240.       void set_submenu (Menu *submenu) ;
  241.       void make_writeable (char *buffer, int length, char *valid) ;
  242.       void print (char *format ...) ;   // print to the menu item
  243.       void vprint (char *format, va_list ap) ;
  244.       void read (int &) ;               // read a number
  245.       void read (char *) ;              // read a string
  246.    private:
  247.       char *name ;
  248.       MenuItem *next ;                // next in list
  249.       Menu *menu ;                    // menu I am in
  250.       int index ;                     // index into menu
  251.       Menu *submenu ;                 // my submenu
  252.    } ;
  253.  
  254. class Menu
  255.    {
  256.    friend class MenuItem ;
  257.    friend class MenuSet ;
  258.    public:
  259.       Menu (char *name, char *title) ;                // create a new menu with name given
  260.       Menu (char *name, char *title, MenuItem *item) ; // create a sub menu
  261.       ~Menu() ;
  262.       MenuItem *selection(int *hits) ;         // translate a selection
  263.       MenuItem *item (char *iname) ;            // get an item from its name
  264.       void print (char *item, char *format ...) ;
  265.       void read (char *item, char *s) ;
  266.       void read (char *item, int &i) ;
  267.       void finish() ;                           // close off a menu
  268.       void open (int x, int y) ;                // open the menu on the screen
  269.       void close() ;                            // close the menu
  270.       void iconbar_adjust (int &x, int &y) ;    // adjust for iconbar display
  271.    private:
  272.       void init(char *name, char *title) ;     // initialisation
  273.       int add_item (MenuItem *item) ;    // add a new item and return its index
  274.       char *name ;          // name of menu
  275.       Menu *next ;          // next in list
  276.       MenuData *data ;      // actual menu data
  277.       MenuItem *items ;     // list of items
  278.       int num_items ;       // number of items
  279.       int max_items ;       // max space for items
  280.       int max_width ;
  281.    } ;
  282.  
  283. </pre>
  284.  
  285. A MenuItem is one of the items of a menu.  The class contains constructors which allow
  286. a new item to be constructed inside an existing menu.  It also contains methods
  287. which allow the item to be read and written to.
  288. <p>
  289. A Menu class represents one menu.  It contains a linked list of MenuItems which
  290. are the items of the menu.  It also contains methods which allow items to be
  291. created, written to and read from.  You can also obtain a pointer to a MenuItem
  292. when you have its name.
  293. <p>
  294. To create a menu from scratch you first need to create a new Menu object:
  295. <pre>
  296.  
  297. Menu *m = new Menu (name, title) ;
  298.  
  299. </pre>
  300. This creates a new Menu object given its name and title.
  301. <p>
  302. Once this is created you add the items to the menu.  To add an item you simply create
  303. it and pass the menu pointer to it as the second parameter.
  304. <pre>
  305.  
  306. MenuItem *i = new MenuItem (name, m, text, text_length) ;
  307.  
  308. </pre>
  309. This will create a new item with the name given and add it to the end of the menu 'm'.
  310. <p>
  311. When all the items have been added to the menu, finish off by calling the 'finish'
  312. function for the menu:
  313. <pre>
  314.  
  315. m->finish() ;
  316.  
  317. </pre>
  318. To create sub-menus you use the Menu constructor which takes a MenuItem pointer as its
  319. third parameter.  To this parameter you pass the address of the MenuItem for which 
  320. you wish to add a sub-menu.
  321. <pre>
  322.  
  323. MenuItem *item2 ;
  324. ...
  325. Menu *sub = new Menu (name, title, item2) ;
  326.  
  327. </pre>
  328. Creates a new menu which will be a sub-menu of the item pointed to by 'item2'.
  329. <p>
  330. The easiest way to see how to construct menus "from first principles" is to look
  331. at the Vista source in the file c.menu.  The functions parse_menu, parse_menu_details
  332. and parse_item are the main menu creation functions for menus created using the
  333. Menus file.
  334.  
  335.  
  336. <p>
  337. <a name="display"></a>
  338. <h2>Displaying menus</h2>
  339.  
  340.  
  341. Vista displays menus whenever the user clicks 'menu' over one of the windows known
  342. to Vista.  In order for Vista to display a menu it needs to know the name of the
  343. menu to display.  This can be obtained in 2 ways:
  344. <p>
  345. <ol>
  346.  
  347. <li>By using the name supplied in the constructor to the task or window.
  348. <li>By asking the task or window to supply one.
  349. </ol>
  350. <p>
  351. In the first case the action of Vista is trivial - it simply displays the menu
  352. given.  In the second case, it first calls a function called 
  353. <a href="file:task#get_iconbar_menu">get_iconbar_menu</a> for<br>
  354. a task or <a href="file:window#get_menu">get_menu</a> for a
  355. window (or Icon or Object)
  356. These functions take some parameters
  357. and return the name of the menu to display.  If you don't want to display
  358. any menu simple return NULL.  The parameters passed are sufficient to enable the
  359. task or window to decide on the menu.  The default action of the Task, Window, Object
  360. and Icon classes is to return NULL.
  361. <p>
  362. The 'get_iconbar_menu' and 'get_menu' functions may either return the name
  363. of a previously created menu or may create a new one.  In order to create a new
  364. menu, have a look at the previous section.  Creating new menus from
  365. scratch is non-trivial and should probably be avoided if possible.
  366. <p>
  367. <p>
  368.  
  369. Once Vista has obtained the name of a menu to display it calls a function <br>
  370. called
  371. <a href="file:task#pre_menu">pre_menu</a> to allow the task or window to modify the menu.  
  372. The 'pre_menu' function
  373. is passed a pointer to a Menu class and a set of parameters showing the current
  374. mouse position.  In the pre_menu function, the program may modify any of the menu
  375. items using the 'print' function which allows the contents of any item to be 
  376. written to.  This takes the following parameters:
  377. <pre>
  378.  
  379. void Menu::print (char *item, char *format ...)
  380.  
  381. </pre>
  382. The first parameter is the name of the item to print to.  The second is a printf
  383. style format string.  The rest of the paramaters depend in the contents of the
  384. format string.
  385.  
  386.  
  387. <p>
  388. <a name="act"></a>
  389. <h2>Acting on menu selections</h2>
  390.  
  391. When the user clicks on a menu selection the virtual function <a href="file:task#menu">menu</a> 
  392. is called for
  393. either the window, task, icon or object  If you override this function in your own derived class
  394. then this is called.
  395. <p>
  396. When in the 'menu' function, you are passed an array of MenuItems.  Each of these items
  397. can be converted to either an integer or a string (char *).  This lets you use a
  398. switch statement to find out which menu item is selected:
  399. <p>
  400. For example:
  401. <pre>
  402.  
  403. void MainWindow::menu(MenuItem items[])
  404.    {
  405.    switch (items[0])
  406.       {
  407.       case 1:
  408.          if (items[0].is_ticked())
  409.             items[0].untick() ;
  410.          else
  411.             items[0].tick() ;
  412.          break ;
  413.       case 4:
  414.          char str[256] ;
  415.          items[1].read (str) ;
  416.          char *s = items[1] ;
  417.          break ;
  418.       }
  419.    }
  420.  
  421. </pre>
  422.  
  423. You can read the value of an item (useful for writeable menu items) by use of the 'read'
  424. method.
  425.  
  426.  
  427.  
  428.