# The Interface Kit: BPopUpMenu

Derived from: public BMenu

Declared in: be/interface/PopUpMenu.h

Library: libbe.so

## Overview

A BPopUpMenu is a specialized menu that's typically used in isolation, rather than as part of an extensive menu hierarchy. By default, it operates in radio mode--the last item selected by the user, and only that item, is marked in the menu.

A menu of this kind can be used to choose one from among a limited set of mutually exclusive states--to pick a paper size or paragraph style, for example, or to select a category of information. It should not be used to group different kinds of choices (as other menus may), nor should it include items that initiate actions rather than set states, except in certain well-defined cases.

A pop-up menu can be used in any of three ways:

- It can be controlled by a BMenuBar object, often one that contains just a single item. The BMenuBar, in effect, functions as a button that pops up a list. The label of the marked item in the list can be displayed as the label of the controlling item in the BMenuBar. In this way, the BMenuBar is able to show the current state of the hidden menu. When this is the case, the menu pops up so its marked item is directly over the controlling item.

- A BPopUpMenu can also be controlled by a view other than a BMenuBar. It might be associated with a particular image the view displays, for example, and appear over the image when the user moves the cursor there and presses the mouse button. Or it might be associated with the view as a whole and come up under the cursor wherever the cursor happens to be. When the view is notified of a mouse-down event, it calls BPopUpMenu's `Go()` function to show the menu on-screen.

- The BPopUpMenu might also be controlled by a particular mouse button, typically the secondary mouse button. When the user presses the button, the menu appears at the location of the cursor. Instead of passing responsibility for the mouse-down event to a BView, the BWindow would intercept it and place the menu on-screen.

Other than `Go()` (and the constructor), this class implements no functions that you ever need to call from application code. In all other respects, a BPopUpMenu can be treated like any other BMenu.

## Constructor and Destructor

### BPopUpMenu()

          BPopUpMenu(const char *name, bool radioMode = true,
             bool labelFromMarked = true,
             menu_layout layout = B_ITEMS_IN_COLUMN)
          BPopUpMenu(BMessage *archive)

Initializes the BPopUpMenu object. If the object is added to a BMenuBar, its name also becomes the initial label of its controlling item (just as for other BMenus).

If the labelFromMarked flag is `true` (as it is by default), the label of the controlling item will change to reflect the label of the item that the user last selected. In addition, the menu will operate in radio mode (regardless of the value passed as the radioMode flag). When the menu pops up, it will position itself so that the marked item appears directly over the controlling item in the BMenuBar.

If labelFromMarked is `false`, the menu pops up so that its first item is over the controlling item.

If the radioMode flag is `true` (as it is by default), the last item selected by the user will always be marked. In this mode, one and only one item within the menu can be marked at a time. If radioMode is `false`, items aren't automatically marked or unmarked.

However, the radioMode flag has no effect unless the labelFromMarked flag is `false`. As long as labelFromMarked is `true`, radio mode will also be `true`.

The layout of the items in a BPopUpMenu can be either `B_ITEMS_IN_ROW` or the default `B_ITEMS_IN_COLUMN`. It should never be `B_ITEMS_IN_MATRIX`. The menu is resized so that it exactly fits the items that are added to it.

The new BPopUpMenu is empty; you add items to it by calling BMenu's `AddItem()` function.

See also: `BMenu::SetRadioMode()`, `BMenu::SetLabelFromMarked()`

### ~BPopUpMenu()

          virtual ~BPopUpMenu()

Does nothing. The BMenu destructor is sufficient to clean up after a BPopUpMenu.

## Static Functions

### Instantiate()

          static BPopUpMenu *Instantiate(BMessage *archive)

Returns a new BPopUpMenu object, allocated by `new` and created with the version of the constructor that takes a BMessage archive. However, if the archive message doesn't contain data for a BPopUpMenu, this function returns `NULL`.

See also: `BArchivable::Instantiate()`, `instantiate_object()`, `BMenu::Archive()`

## Member Functions

### Go()

          BMenuItem *Go(BPoint screenPoint,
             bool deliversMessage = false,
             bool openAnyway = false,
             bool asynchronous = false)
          BMenuItem *Go(BPoint screenPoint,
             bool deliversMessage,
             bool openAnyway,
             BRect clickToOpenRect,
             bool asynchronous = false)

Places the pop-up menu on-screen so that its left top corner is located at screenPoint in the screen coordinate system. If the asynchronous flag is `true`, `Go()` returns right away; the return value is `NULL`. Otherwise, it doesn't return until the user dismisses the menu from the screen. If the user invoked an item in the menu, it returns a pointer to the item. If no item was invoked, it returns `NULL`.

`Go()` is typically called from within the `MouseDown()` function of a BView. For example:

       void MyView::MouseDown(BPoint point)
       {
           BMenuItem *selected;
           BMessage *copy;
           . . .
           ConvertToScreen(&point);
           selected = myPopUp->Go(point);
           . . .
           if ( selected ) {
               BLooper *looper;
               BHandler *target = selected->Target(&looper);
               looper->PostMessage(selected->Message(), target);
           }
           . . .
       }

`Go()` operates in two modes:

- If the deliversMessage flag is `true`, the BPopUpMenu works just like a menu that's controlled by a BMenuBar. When the user invokes an item in the menu, the item posts a message to its target.

- If the deliversMessage flag is `false`, a message is not posted. Invoking an item doesn't automatically accomplish anything. It's up to the application to look at the returned BMenuItem and decide what to do. It can mimic the behavior of other menus and post the message--as shown in the example above--or it can take some other course of action.

`Go()` always puts the pop-up menu on-screen, but ordinarily keeps it there only as long as the user holds a mouse button down. When the user releases the button, the menu is hidden and `Go()` returns. However, the openAnyway flag and the clickToOpenRect arguments can alter this behavior so that the menu will stay open even when the user releases the mouse button (or even if a mouse button was never down). It will take another user action--such as invoking an item in the menu or clicking elsewhere--to dismiss the menu.

If the openAnyway flag is `true`, `Go()` keeps the menu on-screen even if no mouse buttons are held down. This permits a user to open and operate a pop-up menu from the keyboard. If openAnyway is `false`, mouse actions determine whether the menu stays on-screen.

If the user has the click-to-open menu preference turned on and releases the mouse button while the cursor lies inside the clickToOpenRect rectangle, `Go()` interprets the action as clicking to open the menu and keeps it on-screen. If the cursor is outside the rectangle when the mouse button goes up, the menu is removed from the screen and `Go()` returns. The rectangle should be stated in the screen coordinate system.

See also: `BMenuItem::SetMessage()`

### ScreenLocation()

          virtual BPoint ScreenLocation(void)

Determines where the pop-up menu should appear on-screen (when it's being run automatically, not by `Go()`). As explained in the description of the class constructor, this largely depends on whether the label of the superitem changes to reflect the item that's currently marked in the menu. The point returned is stated in the screen coordinate system.

This function is called only for BPopUpMenus that have been added to a menu hierarchy (a BMenuBar). You should not call it to determine the point to pass to `Go()`. However, you can override it to change where a customized pop-up menu defined in a derived class appears on-screen when it's controlled by a BMenuBar.

See also: `BMenu::SetLabelFromMarked()`, `BMenu::ScreenLocation()`, the BPopUpMenu constructor

The Be Book, in lovely HTML, for BeOS Release 3.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.