File: programming/cocoa/UKToolbarFactory.zip/UKToolbarFactory/UKToolbarFactory.m


//
//  UKToolbarFactory.m
//  UKToolbarFactory
//
//  Created by Uli Kusterer on Sat Jan 17 2004.
//  Copyright (c) 2004 M. Uli Kusterer. All rights reserved.
//
 
// -----------------------------------------------------------------------------
//	Headers:
// -----------------------------------------------------------------------------
 
#import "UKToolbarFactory.h"
#import "UKFirstResponder.h"
 
 
@interface UKToolbarFactory (UKToolbarFactoryPrivateMethods)
 
-(void)		setupToolbar: (id)sender;
-(void)		itemClicked: (NSToolbarItem*)sender;
//-(BOOL)		tryToPerform: (SEL)itemAction with: (id)sender onObject: (NSResponder*)resp;
 
@end
 
 
@implementation UKToolbarFactory
 
// -----------------------------------------------------------------------------
//	* DESTRUCTOR:
//		Get rid of the objects we created.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(void) dealloc
{
	[toolbarItems release];
	[toolbarIdentifier release];
	[super dealloc];
}
 
 
// -----------------------------------------------------------------------------
//	awakeFromNib:
//		We were created from a NIB file. Add the toolbar to our window.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(void) awakeFromNib
{
	[self setupToolbar: self];  // Create toolbar.
}
 
 
// -----------------------------------------------------------------------------
//	setToolbarIdentifier:
//		Lets you change the toolbar identifier at runtime. This will recreate
//		the toolbar from the item definition .plist file for that identifier.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(void)			setToolbarIdentifier: (NSString*)str
{
	[str retain];
	[toolbarIdentifier release];
	toolbarIdentifier = str;
	
	[self setupToolbar: nil];   // Recreate toolbar.
}
 
 
// -----------------------------------------------------------------------------
//	toolbarIdentifier:
//		Returns the toolbar identifier this object manages. Defaults to the
//		application's bundle identifier with the autosave name of the owning
//		window appended to it.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(NSString*)	toolbarIdentifier
{
	if( !toolbarIdentifier )
		toolbarIdentifier = [[NSString stringWithFormat: @"%@.%@", [[NSBundle mainBundle] bundleIdentifier], [owner frameAutosaveName]] retain];
	
	return toolbarIdentifier;
}
 
 
// -----------------------------------------------------------------------------
//	toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
//		Creates the appropriate toolbar item for the specified identifier.
//		This simply lets NSToolbarItem handle system-defined toolbar items,
//		while setting up all others according to the dictionaries from the
//		.plist file.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(NSToolbarItem*)   toolbar: (NSToolbar*)toolbar itemForItemIdentifier: (NSString*)itemIdentifier
						willBeInsertedIntoToolbar: (BOOL)flag;
{
	NSDictionary*	allItems = [toolbarItems objectForKey: @"Items"];
	NSDictionary*   currItem;
	NSToolbarItem*  tbi = nil;
		
	// One of the system-provided items?
	if( [itemIdentifier isEqualToString: NSToolbarSeparatorItemIdentifier]
		|| [itemIdentifier isEqualToString: NSToolbarSpaceItemIdentifier]
		|| [itemIdentifier isEqualToString: NSToolbarFlexibleSpaceItemIdentifier]
		|| [itemIdentifier isEqualToString: NSToolbarShowColorsItemIdentifier]
		|| [itemIdentifier isEqualToString: NSToolbarShowFontsItemIdentifier]
		|| [itemIdentifier isEqualToString: NSToolbarPrintItemIdentifier]
		|| [itemIdentifier isEqualToString: NSToolbarCustomizeToolbarItemIdentifier] )
		return [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
	
	// Otherwise, look it up in our list of custom items:
	currItem = [allItems objectForKey: itemIdentifier];
	if( currItem )
	{
		NSString*	theActionStr = [currItem objectForKey: @"Action"];
		NSString*   viewClassStr = [currItem objectForKey: @"ViewClass"];
		SEL			itemAction = @selector(itemClicked:);
		if( theActionStr && (viewClassStr || ![self isSelectable]) )
			itemAction = NSSelectorFromString(theActionStr);
		NSNumber*	maxw = [currItem objectForKey: @"MaxWidth"];
		NSNumber*	minw = [currItem objectForKey: @"MinWidth"];
		NSString*   itemLabel = [currItem objectForKey: @"Label"];
		NSString*   itemCustomLabel = [currItem objectForKey: @"CustomizationLabel"];
		NSString*   itemTooltip = [currItem objectForKey: @"ToolTip"];
		Class		viewClass = nil;
		if( viewClassStr )
			viewClass = NSClassFromString(viewClassStr);
		NSImage*	itemImage = [NSImage imageNamed: itemIdentifier];
		
		// ... and create an NSToolbarItem for it and set that up:
		tbi = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
		[tbi setAction: itemAction];
		if( !viewClassStr && [self isSelectable] )
			[tbi setTarget: self];
		if( viewClassStr )	// This isn't a regular item? It's a view?
		{
			NSView*	theView = (NSView*) [[[viewClass alloc] init] autorelease];
			[tbi setView: theView];
			if( theActionStr && [theView respondsToSelector: @selector(setAction:)] )
				[(id)theView setAction: itemAction];
			if( itemLabel && [theView respondsToSelector: @selector(cell)] )
			{
				NSCell*	theCell = [(id)theView cell];
				if( [theCell respondsToSelector: @selector(setPlaceholderString:)] )
					[(id)theCell setPlaceholderString: itemLabel];
			}
		}
		if( minw )
			[tbi setMinSize: NSMakeSize([minw floatValue], 32)];
		if( maxw )
			[tbi setMaxSize: NSMakeSize([maxw floatValue], 32)];
		[tbi setLabel: itemLabel];
		[tbi setImage: itemImage];
		if( itemCustomLabel )
			[tbi setPaletteLabel: itemCustomLabel];
		else
			[tbi setPaletteLabel: itemLabel];
		if( itemTooltip )
			[tbi setToolTip: itemTooltip];
	}
	
	return tbi;
}
    
 
// -----------------------------------------------------------------------------
//	toolbarDefaultItemIdentifiers:
//		Returns the list of item identifiers we want to be in this toolbar by
//		default. The list is loaded from the .plist file's "DefaultItems" array.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(NSArray*) toolbarDefaultItemIdentifiers: (NSToolbar*)toolbar
{
	return [toolbarItems objectForKey: @"DefaultItems"];
}
 
 
// -----------------------------------------------------------------------------
//	toolbarAllowedItemIdentifiers:
//		Returns the list of item identifiers that may be in the toolbar. This
//		simply returns the identifiers of all the items in our "Items"
//		dictionary, plus a few sensible defaults like separators and spacer
//		items the user may want to add as well.
//
//		If this function doesn't return the item identifier, it *can't* be in
//		the toolbar. Though if this returns it, that doesn't mean it currently
//		is in the toolbar.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(NSArray*) toolbarAllowedItemIdentifiers: (NSToolbar*)toolbar
{
	NSDictionary*	allItems = [toolbarItems objectForKey: @"Items"];
	int				icount = [allItems count];
	NSMutableArray*	allowedItems = [NSMutableArray arrayWithCapacity: icount +4];
	NSEnumerator*   allItemItty;
	NSString*		currItem;
	
	for( allItemItty = [allItems keyEnumerator]; currItem = [allItemItty nextObject]; )
		[allowedItems addObject: currItem];
	
	[allowedItems addObject: NSToolbarSeparatorItemIdentifier];
	[allowedItems addObject: NSToolbarSpaceItemIdentifier];
	[allowedItems addObject: NSToolbarFlexibleSpaceItemIdentifier];
	[allowedItems addObject: NSToolbarCustomizeToolbarItemIdentifier];
	
	return allowedItems;
}
 
 
-(NSArray*) toolbarSelectableItemIdentifiers: (NSToolbar*)toolbar
{
	if( [self isSelectable] )
	{
		NSDictionary*	allItems = [toolbarItems objectForKey: @"Items"];
		int				icount = [allItems count];
		NSMutableArray*	allowedItems = [NSMutableArray arrayWithCapacity: icount];
		NSEnumerator*   allItemItty;
		NSString*		currItem;
		
		for( allItemItty = [allItems keyEnumerator]; currItem = [allItemItty nextObject]; )
		{
			// View items aren't selectable, but make all others selectable:
			if( [[allItems objectForKey: currItem] objectForKey: @"ViewClass"] == nil )
				[allowedItems addObject: currItem];
		}
		
		return allowedItems;
	}
	else
		return [NSArray array];
}
 
 
-(BOOL)	isSelectable
{
	NSNumber*	n = [[toolbarItems objectForKey: @"Options"] objectForKey: @"Selectable"];
	return n && [n boolValue];
}
 
 
-(NSString*)	selectedItemIdentifier
{
	return [[owner toolbar] selectedItemIdentifier];
}
 
-(void)	setSelectedItemIdentifier: (NSString*)str
{
	[[owner toolbar] setSelectedItemIdentifier: str];
}
 
@end
 
@implementation UKToolbarFactory (UKToolbarFactoryPrivateMethods)
 
// -----------------------------------------------------------------------------
//	setupToolbar:
//		(Re)create our toolbar. This loads the .plist file whose name is the
//		toolbar identifier and loads it. Then it adds the toolbar to our
//		window.
//
//	REVISIONS:
//		2004-01-19	witness Documented.
// -----------------------------------------------------------------------------
 
-(void)			setupToolbar: (id)sender
{
	// Load list of items:
	NSString*   toolbarItemsPlistPath = [[NSBundle mainBundle] pathForResource: [self toolbarIdentifier] ofType: @"plist"];
	if( toolbarItems )
		[toolbarItems release];
	toolbarItems = [[NSDictionary dictionaryWithContentsOfFile: toolbarItemsPlistPath] retain];
 
	// (Re-) create toolbar:
	NSToolbar*  tb = [[[NSToolbar alloc] initWithIdentifier: [self toolbarIdentifier]] autorelease];
	[tb setDelegate: self];
	[tb setAllowsUserCustomization: YES];
	[tb setAutosavesConfiguration: YES];
	[owner setToolbar: tb];
	
	if( [self isSelectable] )
		[self setSelectedItemIdentifier: [[toolbarItems objectForKey: @"DefaultItems"] objectAtIndex: 0]];
}
 
 
// -----------------------------------------------------------------------------
//	itemClicked:
//		Toolbar action if we have selectable items. This selects the item, then
//		sends the actual action that the item has.
//
//	REVISIONS:
//		2004-10-03	witness Documented.
// -----------------------------------------------------------------------------
 
-(void)	itemClicked: (NSToolbarItem*)sender
{
	[self setSelectedItemIdentifier: [sender itemIdentifier]];
	
	NSDictionary*	dict = [[toolbarItems objectForKey: @"Items"] objectForKey: [sender itemIdentifier]];
	NSString*		theActionStr = [dict objectForKey: @"Action"];
	if( theActionStr )
	{
		SEL		itemAction = NSSelectorFromString(theActionStr);
		[[UKFirstResponder firstResponder] performSelector: itemAction withObject: sender];
	}
}
 
 
@end
 

This code uses the PclZip Zip File reading code, which is subject to the GNU LGPL. It also uses the GeSHi syntax highlighter, subject to the GPL. Ask if you want this for your own web site, it's free.