Copyright ©1995 by NeXT Computer, Inc.  All Rights Reserved.

PopUpList



Inherits From: Menu : Panel : Window : Responder : Object
Declared In: appkit/PopUpList.h



Class Description

A PopUpList is a type of Menu that's used to make choices from a limited set of options, usually in a specific context.  The PopUpList is usually triggered to pop up by a Button, and tracks the mouse like a Menu does until the user releases the mouse, at which time the PopUpList sends its action message to its target and disappears.  Depending on the type of the PopUpList (see below), the title of the trigger Button is set to the title of the item selected from the PopUpList.  Though a PopUpList is a user-interface device and sends an action message, it's not a Control class.  The trigger that pops it up, however, is a Control; it's nearly always a Button, but may be a Cell in a Matrix, or a subclass of View that responds to the setTitle: and title messages.

There are actually two types of PopUpList:  The pop-up list and the pull-down list.  The type is set with the changeButtonTitle: method.  A pop-up list's trigger always displays the item that was last selected, so a pop-up list is often used for selecting items from a small- to medium-sized set of options (like the zoom factor for a document Window).  It's a useful alternative to a Matrix of radio Buttons or an NXBrowser when screen space is at a premium; a zoom factor pop-up can easily be fit next to a scroll bar on the bottom of a Window, for example.  If there are very many items in the set of options, however, a pop-up list can nearly fill the height of the screen; in this case it would be better to use an NXBrowser, possibly in its own Panel.

A pull-down list is generally used for selecting actions in a very specific context, like the "Operations" pull-down list in Interface Builder's Classes browser.  It has a "title" item that is always displayed on the trigger.  When the actions only make sense in the context of a particular display, a pull-down list can be used in that display to keep the related actions nearby, and to keep them out of the way when that display isn't visible.  This also helps reduce clutter in Menus.



Using PopUpLists with Interface Builder

Interface Builder contains a palette item that looks like a pop-up list.  This item is actually a trigger Button for a PopUpList, which is the target of the Button.  You can change the list to be a pull-down list with Interface Builder's Button Inspector, which shows radio buttons for selecting a pop-up or pull-down list instead of the usual Button options.

If you create an outlet from some other object and connect it to the graphical PopUpList as shown on the screen, you're actually connecting the outlet to the trigger Button.  If you need a connection directly to the PopUpList, you should reset the outlet at run-time.  This can be done in your Application delegate's appDidInit: method, in the awake method of the object containing the outlet, or preferably in the awakeFromNib method of the interface module's "File's Owner" class (awakeFromNib is described in the NXNibNotification protocol specification).  For example, if the object has an outlet called popup:

- awakeFromNib
{
[super awakeFromNib];
if (![popup isKindOf:[PopUpList class]]) popup = [popup target];
/* other setup code */
return self;
}

If you need connections to both the trigger Button and the PopUpList itself, create outlets with names that distinguish the two, like popupButton and popupList, and only connect popupButton in Interface Builder.  The object's awakeFromNib or other such method can then set the popupList outlet from popupButton's target.



Creating a PopUpList Programmatically

To create a PopUpList programmatically, simply allocate an instance, send it an init message, and use the changeButtonTitle: method to configure the PopUpList as a pop-up or pull-down list.  Your code can then add whatever items are needed with the addItem: method, or configure the PopUpList in other ways.

Once a PopUpList has been built, it must be attached to a trigger, which is usually a Button (though it may also be a ButtonCell). There are two functions that attach a PopUpList to a Button, as well as making the Button look like a pop-up or pull-down list by adding the appropriate icon and setting other parameters.  NXAttachPopUpList() attaches the PopUpList to a Button or ButtonCell passed to the function.  NXCreatePopUpListButton() creates and returns a Button that triggers the PopUpList passed to it; your code can then add the Button to a View in your application.

Note:  If you use NXAttachPopUpList() with a Button whose title doesn't appear in the PopUpList, the PopUpList will add that title to the top of its list when the Button triggers it.  This is desirable for a pull-down list, since you won't have to add the title item to the list yourself, but it should be avoided for pop-up lists.  Specifically, this is not a reliable means of adding items to the PopUpList; use addItem: for that.



Working with a PopUpList

PopUpList is actually a subclass of Menu that contains a Matrix of MenuCells (Menu's itemList method can be used to get the Matrix from the PopUpList).  When the PopUpList's target is sent the action message, the sender of that message is actually the Matrix.  The trigger Button itself can't be accessed by the target of the PopUpList.  To get the PopUpList itself from the sending Matrix, the target can use View's window method (since PopUpList is a kind of Window).  If the target needs specific Cells, it can ask the Matrix directly for those with selectedCell, cellAt::, and other such methods.

If the title of a pull-down list needs to be changed, both the title of the trigger Button and the title item of the PopUpList itself need to be changed.  The easiest way to do this is to change the Button's title, and to remove the title item from the pull-down list with removeItemAt: (it's kept at position 0).  When the PopUpList is next triggered by the Button, it will add the Button's new title to the top of its list if that title isn't already in the list.

If you want to change the title of a pop-up list's trigger Button, be aware that this title represents the selected item to the user, so your code will have to also change the selected Cell in the PopUpList's Matrix.  It can do this either by scanning for the title, or by changing the selected Cell by position first, then getting that Cell's title to use as the title of the trigger Button.

For more information, see the class specifications for Matrix, MenuCell, and Button



Instance Variables

None declared in this class.



Method Types

Initializing a PopUpList init
Setting up the items addItem:
insertItem:at:
removeItem:
removeItemAt:
indexOfItem:
count
Interacting with the trigger Button
changeButtonTitle:
getButtonFrame:
Activating the PopUpList popUp:
Getting the user's selection selectedItem
Modifying the items setFont:
font
Target and action setAction:
action
setTarget:
target
Resizing the PopUpList sizeWindow::



Instance Methods

action
(SEL)action

Returns the action sent to the PopUpList's target when an item is selected from the list.  This is actually the action message of the PopUpList's Matrix.

See also:  setAction:, action (Matrix), target



addItem:
addItem:(const char *)title

Adds an item with the name title to the bottom of the PopUpList, and returns the MenuCell created for that item (so a key equivalent can be added, for example).  If an item with the name title already exists in the PopUpList, the MenuCell for that item is returned.

See also:  insertItem:at:, removeItem:



changeButtonTitle:
changeButtonTitle:(BOOL)flag

If flag is YES, then when a selection is made from the list, the title of the selected item becomes the title on the Cell of the trigger that sent the popUp: message (nearly always a Button, but sometimes a Matrix).  This makes the Button appear to the user as a pop-up list, with a small rectangular knob as the icon.  If flag is NO, then the Button's title doesn't change, so that it appears to the user as a pull-down list, with a small inverted triangular mark for an icon.  The default is YES (that is, a pop-up list).  Returns self.



count
(unsigned int)count

Returns the number of items in the PopUpList.  If the PopUpList is configured as a pull-down list, this number includes the MenuCell that holds the pull-down list's title.



font
font

Returns the Font used to draw the items in the PopUpList.

See also:  setFont:



getButtonFrame:
getButtonFrame:(NXRect *)bFrame

Returns self, and by reference in bFrame the frame for the trigger that last popped up the PopUpList.  The origin of the frame is set to (0.0, 0.0), so this method effectively returns the size of the trigger.



indexOfItem:
(int)indexOfItem:(const char *)title

Returns the index of the item with the name title, or 1 if no such item is in the PopUpList.



init
init

Initializes and returns the receiver, a new instance of PopUpList.  This method is the designated initializer for PopUpList. PopUpList does not override the designated initializers for Menu, Panel, or Window; your code should not use those methods with a PopUpList.  If you create a subclass of PopUpList that performs its own initialization, you must override this method.



insertItem:at:
insertItem:(const char *)title at:(unsigned int)index

Inserts an item with the name title at position index in the PopUpList.  The item with an index of 0 is the one at the top.  Returns the newly inserted MenuCell.

If an item with a title of title already exists in the PopUpList, it's removed and the new one is added.  This essentially moves title to a new position, though if the item removed was at a position before index, the new item will actually be inserted at index + 1.  If you want to move an item, it's better to invoke removeItem: explicitly and then send insertItem:at:.

See also:  addItem:, removeItemAt:



popUp:
popUp:trigger

Pops up the PopUpList over the location of trigger, after resizing the PopUpList to be as wide as trigger.  This is the action method sent by the trigger object to the target PopUpList.  If the mouse goes up in an item of the PopUpList, the Matrix that displays the PopUpList's entries sends the action message to the target.  If the PopUpList is a pop-up type list (set with changeButtonTitle:), trigger's title is set to the title of the selected item in the PopUpList; trigger's icon is not altered by this method.  Returns self.

This method works if and only if the following conditions are met.  The Application object's current event must be a mouse-down, and that mouse-down must have occurred within trigger's frame; this method can therefore be effectively invoked only as a result of a mouse-down occurring in triggertrigger must also be either a subclass of View that responds to the messages title and setTitle:, or a subclass of Matrix whose selected Cell responds to title and setTitle:.  If there are no items in the PopUpList and trigger's title is NULL, this method does nothing.

If trigger's title isn't in the PopUpList, it's added as an item at the top before the PopUpList pops up.  The list pops up with the item having the same title as trigger (either a pop-up list's selected item or the "title" item of a pull-down list) exactly over trigger if possible; if this would cause part of the list to be off the top or bottom of the screen, the entire list is shifted up or down so that it can fit on screen.

If any of the MenuCells in the PopUpList's Matrix bring up submenus (that is, have a Menu as a target and submenuAction: as the action message), they are changed to simply be title-displaying MenuCells, and will never bring up their submenus. Essentially, this means that you can't create a hierarchical PopUpList with this class unless you completely override this method.

See also:  setAction:, setTarget:, changeButtonTitle:



removeItem:
removeItem:(const char *)title

Removes and returns the MenuCell with the name title.  If there is no such MenuCell, returns nil.

See also:  removeItemAt:



removeItemAt:
removeItemAt:(unsigned int)index

Removes the MenuCell for the item at the specified index.  Returns the MenuCell at that location, or nil if there was no such MenuCell.

See also:  removeItem:



selectedItem
(const char *)selectedItem

Returns the title of the item last selected by the user (the item that was highlighted when the user released the mouse button), or NULL if for some reason there is no selected item.  It is possible for a pull-down list's selected item to be its title item.

The target of the PopUpList can get the title of the selected item in one of two ways.  Since the sender of the action message is actually the PopUpList's Matrix, the target can ask the Matrix for its selected Cell, and then ask that Cell for its title.  Also, the PopUpList is the Matrix's Window, so the target can retrieve that and then send selectedItem to the PopUpList.  These two methods can be coded as follows:

item = [[sender selectedCell] title];  // sender is actually a Matrix
item = [[sender window] selectedItem]; // PopUpList is Matrix's Window

The first example is the preferred way to get the title.

See also:  selectedCell: (Matrix), title (Cell)



setAction:
setAction:(SEL)aSelector

Sets the action sent to the PopUpList's target when an item is selected.  The action message is actually sent by the Matrix containing the MenuCells that make up the PopUpList.  Returns self.

A pull-down list does send its action if the mouse goes up in its title item.

See also:  action, setAction: (Matrix), setTarget:



setFont:
setFont:fontObject

Sets the Font used to draw the PopUpList's items.  The PopUpList does redraw itself, but since it normally won't be on the screen when it receives this message, this shouldn't cause any undesirable side-effects.  Returns self.

See also:  font (Matrix)



setTarget:
setTarget:anObject

Sets the object to which an action will be sent when an item is selected from the PopUpList.  The action is actually sent by the Matrix containing the MenuCells that make up the PopUpList.  Returns self.

See also:  target, setTarget: (Matrix), setAction:



sizeWindow::
sizeWindow:(NXCoord)width :(NXCoord)height

Your code should never invoke this method, though you're free to override it.  This method is overridden from Menu because PopUpList needs to surround itself with a dark gray border, and thus needs to be one pixel wider and taller than a Menu.  It simply adds 1.0 to each dimension and sends sizeWindow:: to super.  Returns self.



target
target

Returns the object to which the action will be sent when an item is selected from the list.  The default value is nil, which causes the action message to be sent up the responder chain.  The target is actually sent the action by the PopUpList's Matrix.

See also:  setTarget:, target (Matrix), action