AddThis Social Bookmark Button

Print
Programming With Cocoa

Creating Toolbars for Mac OS X

by Michael Beam
03/15/2002

Today we’re going to continue our parade through the new Aqua interface with a look at toolbars. Toolbars are a great addition to the Macintosh GUI. They provide a consistent interface across all applications and are highly customizable by users, taking some of the UI burden off the developer.

To learn about toolbars, we’re going to revisit an old application -- our trusty Address Book. If you haven’t gone through these columns yet, don’t worry, we’re just using it as a base for today’s events, and you should be able to follow along without any problems. You can download the starting project folder here, which we will use for today's work.

Overview

In the course of learning Cocoa, we’ve seen how many of the more complex user interface elements have objects working behind the scenes to manage them. Recall that tableviews had data source objects to provide them with their contents to display.

Comment on this articleMike covers a lot of ground in this tutorial. How has it gone for you, and what are your questions?
Post your comments

Toolbars also require an object to supply the toolbar with the actual controls to display, as well as provide a list of item identifiers so the toolbar knows what’s available. These controls are instances of the class NSToolbarItem, and are referred to as toolbar items. Each toolbar item has a unique string identifier that the toolbar uses to keep track of each item. This object is the toolbar delegate, which will be fulfilled faithfully by our existing NSController object.

If we stop for a moment to think about how toolbars behave, we come up with the following: Toolbars contain a set of controls. This set of controls is customizable by the user via a customization palette. Contained in the palette is a collection of all possible controls that may be placed in the toolbar, as well as a predefined set of controls which makes up the default toolbar.

The toolbar delegate implements the following three required methods to support the behavior described above:

  • -toolbarAllowedItemIdentifiers:
  • -toolbarDefaultItemIdentifiers:
  • -toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:

Our toolbar will have the following custom items, which we will make ourselves:

  • AddItem -- a button that will add a new record
  • RemoveItem -- a button that will remove the selected record
  • SearchItem -- a search field a la iTunes

Additionally our toolbar will contain the following standard toolbar items, provided free of charge by Cocoa:

  • NSToolbarSeparatorItemIdentifier
  • NSToolbarSpaceItemIdentifier
  • NSToolbarFlexibleSpaceItemIdentifier
  • NSToolbarCustomizeToolbarItemIdentifier

Three other standard toolbar items are available for use from NSToolbarItem:

  • NSToolbarShowColorsItemIdentifier
  • NSToolbarShowFontsItemIdentifier
  • NSToolbarPrintItemIdentifier

The image below shows these seven default items in a toolbar customization palette.

Categories

As I mentioned earlier, NSController will serve as the toolbar delegate, but we’re not going to put the delegate methods in Controller.m. Rather, we’re going to add a category to Controller. What is a category you say? Essentially, it's an extension to a class’ implementation. The syntax for a category is only slightly different from class syntax. For our category let’s create a new empty file and name it ToolbarDelegateCategory.h. Below is what the interface file for a category looks like:


#import <Cocoa/Cocoa.h>
#import "Controller.h"

@interface Controller (ToolbarDelegateCategory)

- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar
    itemForItemIdentifier:(NSString *)itemIdentifier
    willBeInsertedIntoToolbar:(BOOL)flag;
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar;
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar;

@end

Notice that the code block for instance variable declarations is absent. This is because categories cannot add instance variables to a class interface, only methods. Also notice how we define the category. The category name follows the class name in parentheses. Finally, when declaring a category you must import the class’ interface if you wish to use any of the class’ instance variables in your category's methods, which we will do.

Now create another file with the same name except with an "m" extension, whose contents are the following:


#import "ToolbarDelegateCategory.h"

@implementation Controller (ToolbarDelegateCategory)

- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar
    itemForItemIdentifier:(NSString *)itemIdentifier
    willBeInsertedIntoToolbar:(BOOL)flag
{
}

- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
{
}

- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
{
}

@end

Categories are useful for several reasons. The methods put in the category file are as good as being in the class implementation itself. Thus, we can extend any class’ behavior in a limited -- yet often times sufficient -- manner without going through the trouble of subclassing. As mentioned previously, categories are limited in the fact that they can’t add instance variables to a class definition. Like subclasses, categories can override methods declared in the class interface.

Categories are useful in breaking up large classes into more manageable files -- code reuse -- and they can save time in compilation. Additionally, if you make your categories right, there is no reason that you can’t reuse the files in another project with minimal changes. For more information on categories, check out Chapter Four of Object-Oriented Programming and the Objective-C Language entitled "More Objective-C."

Pages: 1, 2, 3, 4

Next Pagearrow