home *** CD-ROM | disk | FTP | other *** search
- POP-UP MENU MODULE DOCUMENTATION
-
- Introduction
-
- It has been perceived by some that Intuition's requirement that menus be
- attached to the very top of screens is a flaw. Many windowing systems
- provide "pop-up" menus which can appear anywhere on the screen, typically
- for context-specific input of a multiple-choice selection. In the
- interests of experimenting with the Amiga's user interface (in this case
- extending it to include pop-up menus), the code bundled with this document
- is placed in the public domain for use, alteration, discussion, and
- enhancement. I hope someone somewhere finds it useful.
-
- Derek Zahn (my Amiga hat -- Gambit Software, Madison WI)
- USENET: ...!{allegra,heurikon,ihnp4,seismo,ucbvax}!uwvax!derek
-
- Files
-
- makefile: constructs the demonstration program 'demo' with 'make'.
- The command 'make pop.o' will just make the pop-up menu object module
- pop.c: source file for the pop-up menu module
- popmenu.h: include file containing essential constant definitions;
- should be included by any program using pop-up menus
- demo.c: example program making use of the pop-up menu module
-
- 1. Features
-
- This small chunk of code provides pop-up menu functionality that utilizes
- data structures compatible with the existing methods for specifying
- conventional Intuition menus. As will be described in sections 3 and 4 of
- this document, some flag values have been added to provide control
- useful for pop-up menus, some flag values are not meaningful here, some
- are unsupported, and some fields of the Menu structure are used in ways
- different from Intuition's. A potential user of the code should read and
- understand this document and examine the simple sample cases provided in
- the demonstration program.
-
- The interface, as will be seen in section 2, is a very simple blocking
- function call that will retrieve a pop-up menu selection from the specified
- menu. This interface differs considerably from the normal Intuition menu
- interface which sends messages to the user's IDCMP message port. The reason
- for this difference is as follows: The standard Intuition menu strip
- associated with a particular window is available for use any time the
- window is active (unless specifically shut off). The physical mechanism
- allowing the user to communicate her desire to make a menu choice, and then
- to do so, is built into Intuition at a fundamental level. This is not the
- case for an application-level pop-up menu facility. There is no clear
- universally acceptable method for removing from the application program the
- responsibility for recognizing the need to invoke the pop-up menu function.
-
- I had considered writing another level of interface to this code that would
- spawn off a Task which would be responsible for rendering and handling the
- pop-up menus in response to recognized human interaction, and then notify
- the program via the IDCMP port with a new set of IntuiMessage Classes (such
- as POPMENUVERIFY, POPMENUHIT, etc). However, I became bogged down in trying
- to devise a good scheme for registering pop-up menus and then detecting an
- appropriate time to bring up them up. I would welcome discussion on this
- point.
-
- Despite the lack of procedural alignment with Intuition menus (these pop-up
- menus are much more like AutoRequests), clearly there are instances where the
- interface is reasonably natural anyway. For instance, pop-up menus might be
- very handy for providing a quick way, in a word processing program, to change
- the font of a selected bunch of text -- using a pop-up menu saves the mouse
- movement required to make an Intuition menu selection, allows conservation
- of space that would be taken up by window gadgets to perform similar
- operations, and requires less memorization than keyboard-command equivalents
- (although Power Users may very well migrate there as they become familiar
- with the program).
-
- These pop-up menus are constructed with standard Intuition Menu and MenuItem
- structures. Most of the features provided by Intuition menus are supported
- in nearly identical fashion, as is described in sections 3 and 4.
-
- There are several notable exceptions, however; I do feel that this code is
- incomplete. The facility for providing sub-items is not supported, nor
- are multiple menus in a single pop-up menu. There is also no scheme for
- supporting extended selection. See the Appendix for a discussion of these
- lacks and other qualms I have about the code in its current form.
-
- 2. PopChoose
-
- The user interface:
-
- #include <intuition/intuition.h>
- #include "popmenu.h"
-
- LONG
- PopChoose(menu, win)
- struct Menu *menu;
- struct Window *win;
-
- The argument 'win' specifies the window that is to act as the "parent"
- of the the pop-up menu to be rendered. If this value is NULL, the currently
- active window is used. The argument 'menu' is a specification for the
- pop-up menu, as described in sections 3 and 4 below.
-
- If an error is detected or no valid selection is made by the user, -1 is
- returned. If a selection is made, a non-negative value corresponding to
- the choice is returned, and is computed as follows: The first MenuItem
- in the Menu is numbered zero; thereafter, each is numbered one higher than
- the last as the list of MenuItems is traversed. This is the same scheme
- Intuition uses for the Code field of the class MENUHIT IntuiMessages.
-
- PopChoose() creates a new window in which it renders the menu. It is up to
- the caller to be sure that nobody is scribbling indiscriminately on the
- screen where the menu is to go.
-
- IMPORTANT POINT: In order to link the pop.o module into an application
- program, somewhere in that application the following global variables
- MUST be declared:
-
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
-
- Then, before PopChoose is called, IntuitionBase MUST be set to the result of
- successfully opening the intuition.library, and GfxBase MUST be set to the
- result of successfully opening the graphics.library. The potential for
- disaster if these steps are not properly taken is great indeed.
-
- If you do not understand exactly what is required, examine the code in the
- supplied demonstration program, 'demo.c'.
-
- 3. The Menu structure
-
- This section describes how the fields of the Menu structure are interpreted
- by PopChoose(). Some of the fields are interpreted differently than they
- are by Intuition; understand the differences before using the code.
-
- LeftEdge, TopEdge
-
- These fields contain the upper left corner values for the menu. Their
- meaning (and perhaps even value) is modified by the Flags POPPOINTREL,
- POPWINREL, POPTIDY, and POPREMEMBER, as described below.
-
- Width, Height
-
- The use of these fields differs considerably from Intuition. Here, they
- give the TOTAL size of the menu -- all of the MenuItems (and the title,
- if present) must fit inside the rectangle defined by these variables.
-
- MenuNext
-
- This field is ignored.
-
- MenuName
-
- Use of this field is confusing, as it affects the positioning of the
- MenuItems in the menu. If this field is NULL, there is no title present
- and the offsets in the MenuItem structures represent true offsets from
- the UL corner of the menu. If the field is non-null, it is assumed to
- point to a null-terminated character string which will be rendered in the
- top of the menu as the title. In this case, POPTITLEHEIGHT (defined in
- "popmenu.h") will be silently added to the the TopEdge of each of the
- MenuItems to take the title into account. This confusing behavior is the
- result of providing optional menu titles and still retaining compatibility
- with Intuition's notions about what the TopEdge field in a MenuItem means.
-
- FirstItem
-
- As with Intuition, this points to the list of MenuItem structures that make
- up the choices in the menu. This list may be empty.
-
- Flags
-
- Flags for Menus mentioned in the Intuition Reference Manual:
-
- MENUENABLED
- If this flag is not set in the menu passed to PopChoose(), -1 will be
- returned immediately.
-
- MIDRAWN
- This flag is unused.
-
- Menu flags (defined in "popmenu.h") added for use by the pop-up menus:
-
- By default, the values in LeftEdge and TopEdge are absolute offsets from
- the upper left corner of the screen. The following flags alter this.
-
- POPPOINTREL
- This flag, if set, specifies that the LeftEdge and TopEdge fields are
- to represent offsets from the pointer position when PopChoose() was
- called.
-
- POPWINREL
- This flag, if set, specifies that the LeftEdge and TopEdge fields
- represent offsets from the upper left corner of the "parent"
- window. The POPPOINTREL flag takes priority over POPWINREL if both
- are set.
-
- POPREMEMBER
- This flag, if set, takes effect if the menu passed to PopChoose() has
- previously been used to make a successful selection. Once this has
- happened and if the POPREMEMBER flag is set, the TopEdge and LeftEdge
- fields will be altered so that on the next call, the menu will appear
- relative to the pointer in such a manner that the last-selected item
- will be pre-selected.
-
- POPTIDY
- This flag, if set, makes sure that the whole menu appears on the screen
- by adjusting its location if part of it would not appear on the screen.
- It should be noted that this process can frustrate the intentions of
- the POPPOINTREL, POPWINREL, and POPREMEMBER flags by making the menu
- appear in an "unexpected" place; however, it does assure that the
- menu will be rendered and that all its items are on-screen.
-
- POPUSED
- This flag is for internal use by PopChoose() -- it indicates
- whether the next call to PopChoose() should treat the POPREMEMBER
- flag as being in effect.
-
- These next flags determine the conditions under which a menu selection is
- considered made. Note that it is ABSOLUTELY REQUIRED that at least one
- of { POPLEFTBUTTON, POPRIGHTBUTTON } be set AND at least one of
- { POPTRIGGERUP, POPTRIGGERDOWN } be set -- if these conditions are not met,
- the call to PopChoose() will never return!
-
- POPLEFTBUTTON
- Treat the left mouse button as "important" in determining when the user
- is through with the menu. Both this and POPRIGHTBUTTON may be set, in
- which case, both buttons are important.
-
- POPRIGHTBUTTON
- Treat the right mouse button as "important" in determining when the user
- is through with the menu.
-
- POPTRIGGERUP
- Send the menu away, making a selection if the pointer is over an item,
- and not if not, when the "important" button or buttons is/are released.
- Both this and POPTRIGGERDOWN may be set, in which case both are in
- effect.
-
- POPTRIGGERDOWN
- Send the menu away, making a selection if the pointer is over an item,
- and not if not, when the "important" button or buttons is/are depressed.
-
- 4. The MenuItem structure
-
- This section describes how the fields of the MenuItem structure are
- interpreted by PopChoose(). Their use is nearly identical to their use
- under Intuition.
-
- NextItem
-
- The next MenuItem in the list
-
- LeftEdge, TopEdge
-
- These values hold the coordinates of the upper left hand corner of the
- select box for the item, relative to the upper left hand corner of the
- menu itself. If the menu has a title, TopEdge will be silently
- incremented by POPTITLEHEIGHT for rendering purposes to make room for the
- title. This will be transparent to you (except when specifying the
- Height field of the Menu structure, as noted above).
-
- Width, Height
-
- These fields are the height and width of the select box for this item.
-
- MutualExclude
-
- Items with the the CHECKIT flag set (see below) may form mutual exclusion
- groups. If this item is not CHECKED and is selected, all items designated
- with the MutualExclude field will be un-CHECKED. This field is a bitmask
- where each bit refers to a single MenuItem in the list attached to the
- Menu. The first MenuItem corresponds to bit zero, the second to bit one,
- and so on. Setting a bit in this mask puts the corresponding MenuItem
- into a mutual exclusion group with this item. If you place an item in
- its own mutual exclusion group, it will never be CHECKED. In most cases
- this is not what you want, but who knows?
-
- ItemFill, SelectFill
-
- Exactly as described in the Intuition Reference Manual.
-
- Command
-
- This field is ignored - there are no keyboard equivalents for pop-up menus.
-
- SubItem
-
- In the current implementation, this field is ignored; menu sub-items are
- unsupported.
-
- NextSelect
-
- This field is unused -- extended selections are not supported.
-
- Flags
-
- There are no pop-up-menu-specific flags for the MenuItem structure. The
- following are the flags defined in the Intuition Reference Manual along
- with descriptions of how their use relates to pop-up menus.
-
- CHECKIT, CHECKED
- These flags provide checkmarking functionality identical to that of
- Intuition's menus. If the user tries to select a MenuItem that is
- CHECKED, -1 will ALWAYS be returned; that is the nature of checkmarking.
-
- HIGHCOMP, HIGHBOX, HIGHIMAGE, HIGHNONE
- Just as with Intuition, these specify the highlighting mode desired. If
- none of these are set, HIGHIMAGE is the default (because of the screwy
- way Intuition defines the flag values); if no alternate imagery is
- supplied in the SelectFill field, the effect will be the same as if
- HIGHNONE was chosen.
-
- ITEMTEXT
- This flag's function is identical to that explained in the Intuition
- Reference Manual.
-
- ITEMENABLED
- As in Intuition, if this flag is not set, the item is "ghosted" and
- unavailable for selection. An attempt by the user to select an item
- that is not ITEMENABLED will result in a return of -1.
-
- ISDRAWN, HIGHITEM, COMMSEQ
- These flags are unused.
-
- Appendix: Problems
-
- This code is not nearly perfect, although I confess my inability to provide
- either clearly better solutions to the problems that make me fidget or
- reasonably simple implementation schemes for the missing features. This
- Appendix details to some extent the concerns with which I send this code
- into the Amiga community.
-
- First, the inconsistencies in user interface. Although it still seems to me
- that the consistent way to do these menus would have involved the delivery
- of IntuiMessages, the current scheme seems workable in nearly all scenarios
- I have imagined; in fact, PopChoose() seems simpler to use the way it is now.
- Suggestions or enhancements for the interface would be welcome.
-
- Second, the POPREMEMBER business makes me a little nervous; altering the
- LeftEdge and TopEdge fields seems like a kludge.
-
- Third, the way the optional menu title is handled seems too strange. If
- the offsets of the MenuItems are going to be increased, it seems like
- the size of the window should be as well, in the interest of "transparency".
- But I couldn't bring myself to go around altering the window size....
-
- Fourth, the code could probably be improved in a couple of ways: there is
- altogether too much looping through MenuItem lists, and as always there may
- be bugs lurking in the code somewhere. (clipping???)
-
- Fifth, there are several crucial features missing, with no clue how they
- might be added: subitems, extended select. In addition, the keyboard
- equivalents for Intuition menu items would be nice to support, but it is
- not at all clear to me how this would even be possible.
-
- Sixth, bugs. There are two that I know of. 1: although the case where
- the POPTIDY flag is not set and the menu extends past the bottom and/or
- right edge of the screen is supported (the window is altered in size), the
- case where the screen's top and/or left border(s) is/are violated is not
- handled; the menu will not be placed if this happens, and -1 returned
- (at least under 1.2 this is what happens -- I am not sure if the
- OpenWindow() call behaves the same under 1.1). Speaking of which, I just
- examined how the X window system (or at least the 'xterm' application)
- handles pop-up menus that fly off the screen. It appears to use the
- equivalent of my POPTIDY flag, except when the menu would violate the bottom
- edge of the screen. In this case, the menu is moved up as expected and THE
- POINTER IS MOVED so that it is where it should be in relation to the menu.
- A little voice in my head gasped and said, "Never, Ever, move the user's
- pointer!!!", but is this wrong or what? Should I add a POPMOVEPOINTER flag
- to work in conjunction with POPTIDY?
- 2: it is possible for the user to do the mouse operation that would
- end the menu request before the window is rendered. In this case, the
- event is not noticed and must be repeated. This could be remedied if I
- could figure out how to query the state of the mouse buttons just after
- the window is opened.
-