File:  [mozdev] / chimera / PreferencePanes / MVPreferencesController.m
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 26 11:49:02 2002 UTC (17 years, 7 months ago) by macserv
Branches: MAIN
CVS tags: HEAD
Checking in the underlying prefs structure, and a prefPane, also fir structural integrity.  Also including a couple categories to extend a couple Cocoa objects, and some project changes to support building with the bundled prefPanes.  Also, added a contrib directory to house user contributed artifacts.  To come soon: more prefPanes, and the colorized icon store, with pref-generated notifications to be picked up by toolbars.

    1: #import <PreferencePanes/PreferencePanes.h>
    2: #import "MVPreferencesController.h"
    3: #import "MVPreferencesMultipleIconView.h"
    4: #import "MVPreferencesGroupedIconView.h"
    5: #import "NSToolbarAdditions.h"
    6: 
    7: // #import "Defines.h"
    8: 
    9: static MVPreferencesController *sharedInstance = nil;
   10: 
   11: static NSString *MVToolbarShowAllItemIdentifier = @"MVToolbarShowAllItem";
   12: static NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification";
   13: 
   14: @interface NSToolbar (NSToolbarPrivate)
   15: - (NSView *) _toolbarView;
   16: @end
   17: 
   18: @interface MVPreferencesController (MVPreferencesControllerPrivate)
   19: - (void) _doUnselect:(NSNotification *) notification;
   20: - (IBAction) _selectPreferencePane:(id) sender;
   21: - (void) _resizeWindowForContentView:(NSView *) view;
   22: - (NSImage *) _imageForPaneBundle:(NSBundle *) bundle;
   23: - (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle;
   24: - (NSString *) _labelForPaneBundle:(NSBundle *) bundle;
   25: @end
   26: 
   27: @implementation MVPreferencesController
   28: 
   29: + (MVPreferencesController *) sharedInstance {
   30: 	return ( sharedInstance ? sharedInstance : [[[self alloc] init] autorelease] );
   31: }
   32: 
   33: - (id) init {
   34: 	if( ( self = [super init] ) ) {
   35: 		unsigned i = 0;
   36: 		NSBundle *bundle = nil;
   37: 		NSString *bundlePath = [NSString stringWithFormat:@"%@/Contents/PreferencePanes", [[NSBundle mainBundle] bundlePath]];
   38: 		panes = [[[NSFileManager defaultManager] directoryContentsAtPath:bundlePath] mutableCopy];
   39: 		for( i = 0; i < [panes count]; i++ ) {
   40: 			bundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/%@", bundlePath, [panes objectAtIndex:i]]];
   41: 			[bundle load];
   42: 			if( bundle ) [panes replaceObjectAtIndex:i withObject:bundle];
   43: 			else {
   44: 				[panes removeObjectAtIndex:i];
   45: 				i--;
   46: 			}
   47: 		}
   48: 		loadedPanes = [[NSMutableDictionary dictionary] retain];
   49: 		paneInfo = [[NSMutableDictionary dictionary] retain];
   50: 		[NSBundle loadNibNamed:@"MVPreferences" owner:self];
   51: 
   52: 		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _doUnselect: ) name:NSPreferencePaneDoUnselectNotification object:nil];
   53: 	}
   54: 	return self;
   55: }
   56: 
   57: - (void) dealloc {
   58: 	[loadedPanes autorelease];
   59: 	[panes autorelease];
   60: 	[paneInfo autorelease];
   61: 	[[NSNotificationCenter defaultCenter] removeObserver:self];
   62: 	loadedPanes = nil;
   63: 	panes = nil;
   64: 	paneInfo = nil;
   65: 	[super dealloc];
   66: }
   67: 
   68: - (void) awakeFromNib {
   69: 	NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"preferences.toolbar"] autorelease];
   70: 	NSArray *groups = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneGroups" ofType:@"plist"]];
   71: 
   72: 	if( groups ) {
   73: 		[groupView setPreferencePanes:panes];
   74: 		[groupView setPreferencePaneGroups:groups];
   75: 		mainView = groupView;
   76: 	} else {
   77: 		[multiView setPreferencePanes:panes];
   78: 		mainView = multiView;
   79: 	}
   80: 	[self showAll:nil];
   81: 
   82: 	[window setDelegate:self];
   83: 
   84: 	[toolbar setAllowsUserCustomization:YES];
   85: 	[toolbar setAutosavesConfiguration:YES];
   86: 	[toolbar setDelegate:self];
   87: 	[toolbar setAlwaysCustomizableByDrag:YES];
   88: 	[toolbar setShowsContextMenu:NO];
   89:     [window setToolbar:toolbar];
   90: 	[toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel];
   91: 	[toolbar setIndexOfFirstMovableItem:2];
   92: }
   93: 
   94: - (NSWindow *) window {
   95: 	return [[window retain] autorelease];
   96: }
   97: 
   98: - (IBAction) showPreferences:(id) sender {
   99: 	[self showAll:nil];
  100: 	[window makeKeyAndOrderFront:nil];
  101: }
  102: 
  103: - (IBAction) showAll:(id) sender {
  104: 	if( [[window contentView] isEqual:mainView] ) return;
  105: 	if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) {
  106: 		/* more to handle later */
  107: 		NSLog( @"can't unselect current" );
  108: 		return;
  109: 	}
  110: 	[window setContentView:[[[NSView alloc] initWithFrame:[mainView frame]] autorelease]];
  111: 
  112: 	[window setTitle:[NSString stringWithFormat:NSLocalizedString( @"%@ Preferences", nil ), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]]];
  113: 	[self _resizeWindowForContentView:mainView];
  114: 
  115: 	[[loadedPanes objectForKey:currentPaneIdentifier] willUnselect];
  116: 	[window setContentView:mainView];
  117: 	[[loadedPanes objectForKey:currentPaneIdentifier] didUnselect];
  118: 
  119: 	[currentPaneIdentifier autorelease];
  120: 	currentPaneIdentifier = nil;
  121: 
  122: 	[window setInitialFirstResponder:mainView];
  123: 	[window makeFirstResponder:mainView];
  124: }
  125: 
  126: - (void) selectPreferencePaneByIdentifier:(NSString *) identifier {
  127: 	NSBundle *bundle = [NSBundle bundleWithIdentifier:identifier];
  128: 	if( bundle && ! [currentPaneIdentifier isEqualToString:identifier] ) {
  129: 		NSPreferencePane *pane = nil;
  130: 		NSView *prefView = nil;
  131: 		if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) {
  132: 			/* more to handle later */
  133: 			NSLog( @"can't unselect current" );
  134: 			closeWhenPaneIsReady = NO;
  135: 			[pendingPane autorelease];
  136: 			pendingPane = [identifier retain];
  137: 			return;
  138: 		}
  139: 		[pendingPane autorelease];
  140: 		pendingPane = nil;
  141: 		[loadingImageView setImage:[self _imageForPaneBundle:bundle]];
  142: 		[loadingTextFeld setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Loading %@...", nil ), [self _labelForPaneBundle:bundle]]];
  143: 		[window setTitle:[self _labelForPaneBundle:bundle]];
  144: 		[window setContentView:loadingView];
  145: 		[window display];
  146: 		if( ! ( pane = [loadedPanes objectForKey:identifier] ) ) {
  147: 			pane = [[[[bundle principalClass] alloc] initWithBundle:bundle] autorelease];
  148: 			if( pane ) [loadedPanes setObject:pane forKey:identifier];
  149: 		}
  150: 		if( [pane loadMainView] ) {
  151: 			[pane willSelect];
  152: 			prefView = [pane mainView];
  153: 
  154: 			[self _resizeWindowForContentView:prefView];
  155: 
  156: 			[[loadedPanes objectForKey:currentPaneIdentifier] willUnselect];
  157: 			[window setContentView:prefView];
  158: 			[[loadedPanes objectForKey:currentPaneIdentifier] didUnselect];
  159: 			[pane didSelect];
  160: 			[[NSNotificationCenter defaultCenter] postNotificationName:MVPreferencesWindowNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:window, @"window", nil]];
  161: 			[currentPaneIdentifier autorelease];
  162: 			currentPaneIdentifier = [identifier copy];
  163: 
  164: 			[window setInitialFirstResponder:[pane initialKeyView]];
  165: 			[window makeFirstResponder:[pane initialKeyView]];
  166: 		} else NSRunCriticalAlertPanel( NSLocalizedString( @"Preferences Error", nil ), [NSString stringWithFormat:NSLocalizedString( @"Could not load %@", nil ), [self _labelForPaneBundle:bundle]], nil, nil, nil );
  167: 	}
  168: }
  169: 
  170: - (BOOL) windowShouldClose:(id) sender {
  171: 	if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) {
  172: 		NSLog( @"can't unselect current" );
  173: 		closeWhenPaneIsReady = YES;
  174: 		return NO;
  175: 	}
  176: 	return YES;
  177: }
  178: 
  179: - (void) windowWillClose:(NSNotification *) notification {
  180: 	[[loadedPanes objectForKey:currentPaneIdentifier] willUnselect];
  181: 	[[loadedPanes objectForKey:currentPaneIdentifier] didUnselect];
  182: 	[currentPaneIdentifier autorelease];
  183: 	currentPaneIdentifier = nil;
  184: 	//[loadedPanes removeAllObjects];
  185: }
  186: 
  187: - (NSToolbarItem *) toolbar:(NSToolbar *) toolbar itemForItemIdentifier:(NSString *) itemIdentifier willBeInsertedIntoToolbar:(BOOL) flag {
  188: 	NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];
  189: 	if( [itemIdentifier isEqualToString:MVToolbarShowAllItemIdentifier] ) {
  190: 		[toolbarItem setLabel:NSLocalizedString( @"Show All", nil )];
  191: 		[toolbarItem setImage:[NSImage imageNamed:@"NSApplicationIcon"]];
  192: 		[toolbarItem setTarget:self];
  193: 		[toolbarItem setAction:@selector( showAll: )];
  194: 	} else {
  195: 		NSBundle *bundle = [NSBundle bundleWithIdentifier:itemIdentifier];
  196: 		if( bundle ) {
  197: 			[toolbarItem setLabel:[self _labelForPaneBundle:bundle]];
  198: 			[toolbarItem setPaletteLabel:[self _paletteLabelForPaneBundle:bundle]];
  199: 			[toolbarItem setImage:[self _imageForPaneBundle:bundle]];
  200: 			[toolbarItem setTarget:self];
  201: 			[toolbarItem setAction:@selector( _selectPreferencePane: )];
  202: 		} else toolbarItem = nil;
  203: 	}
  204: 	return toolbarItem;
  205: }
  206: 
  207: - (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *) toolbar {
  208: 	NSMutableArray *fixed = [NSMutableArray arrayWithObjects:MVToolbarShowAllItemIdentifier, NSToolbarSeparatorItemIdentifier, nil];
  209: 	NSArray *defaults = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneDefaults" ofType:@"plist"]];
  210: 	[fixed addObjectsFromArray:defaults];
  211: 	return fixed;
  212: }
  213: 
  214: - (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *) toolbar {
  215: 	NSMutableArray *items = [NSMutableArray array];
  216: 	NSEnumerator *enumerator = [panes objectEnumerator];
  217: 	id item = nil;
  218: 	while( ( item = [enumerator nextObject] ) )
  219: 		[items addObject:[item bundleIdentifier]];
  220: 	//[items addObject:MVToolbarShowAllItemIdentifier];
  221: 	[items addObject:NSToolbarSeparatorItemIdentifier];
  222: 	return items;
  223: }
  224: @end
  225: 
  226: @implementation MVPreferencesController (MVPreferencesControllerPrivate)
  227: - (IBAction) _selectPreferencePane:(id) sender {
  228: 	[self selectPreferencePaneByIdentifier:[sender itemIdentifier]];
  229: }
  230: 
  231: - (void) _doUnselect:(NSNotification *) notification {
  232: 	if( closeWhenPaneIsReady ) [window close];
  233: 	[self selectPreferencePaneByIdentifier:pendingPane];
  234: }
  235: 
  236: - (void) _resizeWindowForContentView:(NSView *) view {
  237: 	NSRect windowFrame, newWindowFrame;
  238: 	unsigned int newWindowHeight;
  239: 
  240: 	windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]];
  241: 	newWindowHeight = NSHeight( [view frame] );
  242: 	if( [[window toolbar] isVisible] )
  243: 		newWindowHeight += NSHeight( [[[window toolbar] _toolbarView] frame] );
  244: 	newWindowFrame = [NSWindow frameRectForContentRect:NSMakeRect( NSMinX( windowFrame ), NSMaxY( windowFrame ) - newWindowHeight, NSWidth( windowFrame ), newWindowHeight ) styleMask:[window styleMask]];
  245: 
  246: 	[window setFrame:newWindowFrame display:YES animate:[window isVisible]];
  247: }
  248: 
  249: - (NSImage *) _imageForPaneBundle:(NSBundle *) bundle {
  250: 	NSImage *image = nil;
  251: 	NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]];
  252: 	image = [[[cache objectForKey:@"MVPreferencePaneImage"] retain] autorelease];
  253: 	if( ! image ) {
  254: 		NSDictionary *info = [bundle infoDictionary];
  255: 		image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"NSPrefPaneIconFile"]]] autorelease];
  256: 		if( ! image ) image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"CFBundleIconFile"]]] autorelease];
  257: 		if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]];
  258: 		cache = [paneInfo objectForKey:[bundle bundleIdentifier]];
  259: 		if( image ) [cache setObject:image forKey:@"MVPreferencePaneImage"];
  260: 	}
  261: 	return image;
  262: }
  263: 
  264: - (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle {
  265: 	NSString *label = nil;
  266: 	NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]];
  267: 	label = [[[cache objectForKey:@"MVPreferencePanePaletteLabel"] retain] autorelease];
  268: 	if( ! label ) {
  269: 		NSDictionary *info = [bundle infoDictionary];
  270: 		label = NSLocalizedStringFromTableInBundle( @"NSPrefPaneIconLabel", @"InfoPlist", bundle, nil );
  271: 		if( [label isEqualToString:@"NSPrefPaneIconLabel"] ) label = [info objectForKey:@"NSPrefPaneIconLabel"];
  272: 		if( ! label ) label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil );
  273: 		if( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"];
  274: 		if( ! label ) label = [bundle bundleIdentifier];
  275: 		if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]];
  276: 		cache = [paneInfo objectForKey:[bundle bundleIdentifier]];
  277: 		if( label ) [cache setObject:label forKey:@"MVPreferencePanePaletteLabel"];
  278: 	}
  279: 	return label;
  280: }
  281: 
  282: - (NSString *) _labelForPaneBundle:(NSBundle *) bundle {
  283: 	NSString *label = nil;
  284: 	NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]];
  285: 	label = [[[cache objectForKey:@"MVPreferencePaneLabel"] retain] autorelease];
  286: 	if( ! label ) {
  287: 		NSDictionary *info = [bundle infoDictionary];
  288: 		label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil );
  289: 		if( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"];
  290: 		if( ! label ) label = [bundle bundleIdentifier];
  291: 		if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]];
  292: 		cache = [paneInfo objectForKey:[bundle bundleIdentifier]];
  293: 		if( label ) [cache setObject:label forKey:@"MVPreferencePaneLabel"];
  294: 	}
  295: 	return label;
  296: }
  297: @end
  298: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>