diff --git a/mozilla/camino/English.lproj/MVPreferencePaneGroups.strings b/mozilla/camino/English.lproj/MVPreferencePaneGroups.strings new file mode 100644 index 00000000000..b410cd0bc55 Binary files /dev/null and b/mozilla/camino/English.lproj/MVPreferencePaneGroups.strings differ diff --git a/mozilla/camino/English.lproj/MVPreferences.nib/classes.nib b/mozilla/camino/English.lproj/MVPreferences.nib/classes.nib new file mode 100644 index 00000000000..aeac16577ff --- /dev/null +++ b/mozilla/camino/English.lproj/MVPreferences.nib/classes.nib @@ -0,0 +1,32 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {showAll = id; showPreferences = id; }; + CLASS = MVPreferencesController; + LANGUAGE = ObjC; + OUTLETS = { + groupView = id; + loadingImageView = id; + loadingTextFeld = id; + loadingView = id; + multiView = id; + window = id; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = MVPreferencesGroupedIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + }, + { + CLASS = MVPreferencesMultipleIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/camino/English.lproj/MVPreferences.nib/info.nib b/mozilla/camino/English.lproj/MVPreferences.nib/info.nib new file mode 100644 index 00000000000..d6140876225 --- /dev/null +++ b/mozilla/camino/English.lproj/MVPreferences.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 19 36 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBSystem Version + 5Q45 + + diff --git a/mozilla/camino/English.lproj/MVPreferences.nib/objects.nib b/mozilla/camino/English.lproj/MVPreferences.nib/objects.nib new file mode 100644 index 00000000000..92598fe1cf1 Binary files /dev/null and b/mozilla/camino/English.lproj/MVPreferences.nib/objects.nib differ diff --git a/mozilla/camino/PreferencePanes/MVPreferencePaneDefaults.plist b/mozilla/camino/PreferencePanes/MVPreferencePaneDefaults.plist new file mode 100644 index 00000000000..e1574407fcb --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferencePaneDefaults.plist @@ -0,0 +1,7 @@ +( Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane +) diff --git a/mozilla/camino/PreferencePanes/MVPreferencePaneGroups.plist b/mozilla/camino/PreferencePanes/MVPreferencePaneGroups.plist new file mode 100644 index 00000000000..ad5199ee34b --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferencePaneGroups.plist @@ -0,0 +1,14 @@ +( + { + identifier = chimera; + panes = ( + Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane, + Chimera.AdvancedPrefPane + ); + } +) \ No newline at end of file diff --git a/mozilla/camino/PreferencePanes/MVPreferencePaneGroups.strings b/mozilla/camino/PreferencePanes/MVPreferencePaneGroups.strings new file mode 100644 index 00000000000..b410cd0bc55 Binary files /dev/null and b/mozilla/camino/PreferencePanes/MVPreferencePaneGroups.strings differ diff --git a/mozilla/camino/PreferencePanes/MVPreferences.nib/classes.nib b/mozilla/camino/PreferencePanes/MVPreferences.nib/classes.nib new file mode 100644 index 00000000000..aeac16577ff --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferences.nib/classes.nib @@ -0,0 +1,32 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {showAll = id; showPreferences = id; }; + CLASS = MVPreferencesController; + LANGUAGE = ObjC; + OUTLETS = { + groupView = id; + loadingImageView = id; + loadingTextFeld = id; + loadingView = id; + multiView = id; + window = id; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = MVPreferencesGroupedIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + }, + { + CLASS = MVPreferencesMultipleIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/camino/PreferencePanes/MVPreferences.nib/info.nib b/mozilla/camino/PreferencePanes/MVPreferences.nib/info.nib new file mode 100644 index 00000000000..d6140876225 --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferences.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 19 36 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBSystem Version + 5Q45 + + diff --git a/mozilla/camino/PreferencePanes/MVPreferences.nib/objects.nib b/mozilla/camino/PreferencePanes/MVPreferences.nib/objects.nib new file mode 100644 index 00000000000..92598fe1cf1 Binary files /dev/null and b/mozilla/camino/PreferencePanes/MVPreferences.nib/objects.nib differ diff --git a/mozilla/camino/PreferencePanes/MVPreferencesController.m b/mozilla/camino/PreferencePanes/MVPreferencesController.m new file mode 100644 index 00000000000..77f6c82113e --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferencesController.m @@ -0,0 +1,298 @@ +#import +#import "MVPreferencesController.h" +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesGroupedIconView.h" +#import "CHToolbarAdditions.h" + +// #import "Defines.h" + +static MVPreferencesController *sharedInstance = nil; + +static NSString *MVToolbarShowAllItemIdentifier = @"MVToolbarShowAllItem"; +static NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; + +@interface NSToolbar (NSToolbarPrivate) +- (NSView *) _toolbarView; +@end + +@interface MVPreferencesController (MVPreferencesControllerPrivate) +- (void) _doUnselect:(NSNotification *) notification; +- (IBAction) _selectPreferencePane:(id) sender; +- (void) _resizeWindowForContentView:(NSView *) view; +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; +@end + +@implementation MVPreferencesController + ++ (MVPreferencesController *) sharedInstance { + return ( sharedInstance ? sharedInstance : [[[self alloc] init] autorelease] ); +} + +- (id) init { + if( ( self = [super init] ) ) { + unsigned i = 0; + NSBundle *bundle = nil; + NSString *bundlePath = [NSString stringWithFormat:@"%@/Contents/PreferencePanes", [[NSBundle mainBundle] bundlePath]]; + panes = [[[NSFileManager defaultManager] directoryContentsAtPath:bundlePath] mutableCopy]; + for( i = 0; i < [panes count]; i++ ) { + bundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/%@", bundlePath, [panes objectAtIndex:i]]]; + [bundle load]; + if( bundle ) [panes replaceObjectAtIndex:i withObject:bundle]; + else { + [panes removeObjectAtIndex:i]; + i--; + } + } + loadedPanes = [[NSMutableDictionary dictionary] retain]; + paneInfo = [[NSMutableDictionary dictionary] retain]; + [NSBundle loadNibNamed:@"MVPreferences" owner:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _doUnselect: ) name:NSPreferencePaneDoUnselectNotification object:nil]; + } + return self; +} + +- (void) dealloc { + [loadedPanes autorelease]; + [panes autorelease]; + [paneInfo autorelease]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + loadedPanes = nil; + panes = nil; + paneInfo = nil; + [super dealloc]; +} + +- (void) awakeFromNib { + NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"preferences.toolbar"] autorelease]; + NSArray *groups = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneGroups" ofType:@"plist"]]; + + if( groups ) { + [groupView setPreferencePanes:panes]; + [groupView setPreferencePaneGroups:groups]; + mainView = groupView; + } else { + [multiView setPreferencePanes:panes]; + mainView = multiView; + } + [self showAll:nil]; + + [window setDelegate:self]; + + [toolbar setAllowsUserCustomization:YES]; + [toolbar setAutosavesConfiguration:YES]; + [toolbar setDelegate:self]; + [toolbar setAlwaysCustomizableByDrag:YES]; + [toolbar setShowsContextMenu:NO]; + [window setToolbar:toolbar]; + [toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; + [toolbar setIndexOfFirstMovableItem:2]; +} + +- (NSWindow *) window { + return [[window retain] autorelease]; +} + +- (IBAction) showPreferences:(id) sender { + [self showAll:nil]; + [window makeKeyAndOrderFront:nil]; +} + +- (IBAction) showAll:(id) sender { + if( [[window contentView] isEqual:mainView] ) return; + if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { + /* more to handle later */ + NSLog( @"can't unselect current" ); + return; + } + [window setContentView:[[[NSView alloc] initWithFrame:[mainView frame]] autorelease]]; + + [window setTitle:[NSString stringWithFormat:NSLocalizedString( @"%@ Preferences", nil ), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]]]; + [self _resizeWindowForContentView:mainView]; + + [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; + [window setContentView:mainView]; + [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; + + [currentPaneIdentifier autorelease]; + currentPaneIdentifier = nil; + + [window setInitialFirstResponder:mainView]; + [window makeFirstResponder:mainView]; +} + +- (void) selectPreferencePaneByIdentifier:(NSString *) identifier { + NSBundle *bundle = [NSBundle bundleWithIdentifier:identifier]; + if( bundle && ! [currentPaneIdentifier isEqualToString:identifier] ) { + NSPreferencePane *pane = nil; + NSView *prefView = nil; + if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { + /* more to handle later */ + NSLog( @"can't unselect current" ); + closeWhenPaneIsReady = NO; + [pendingPane autorelease]; + pendingPane = [identifier retain]; + return; + } + [pendingPane autorelease]; + pendingPane = nil; + [loadingImageView setImage:[self _imageForPaneBundle:bundle]]; + [loadingTextFeld setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Loading %@...", nil ), [self _labelForPaneBundle:bundle]]]; + [window setTitle:[self _labelForPaneBundle:bundle]]; + [window setContentView:loadingView]; + [window display]; + if( ! ( pane = [loadedPanes objectForKey:identifier] ) ) { + pane = [[[[bundle principalClass] alloc] initWithBundle:bundle] autorelease]; + if( pane ) [loadedPanes setObject:pane forKey:identifier]; + } + if( [pane loadMainView] ) { + [pane willSelect]; + prefView = [pane mainView]; + + [self _resizeWindowForContentView:prefView]; + + [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; + [window setContentView:prefView]; + [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; + [pane didSelect]; + [[NSNotificationCenter defaultCenter] postNotificationName:MVPreferencesWindowNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:window, @"window", nil]]; + [currentPaneIdentifier autorelease]; + currentPaneIdentifier = [identifier copy]; + + [window setInitialFirstResponder:[pane initialKeyView]]; + [window makeFirstResponder:[pane initialKeyView]]; + } else NSRunCriticalAlertPanel( NSLocalizedString( @"Preferences Error", nil ), [NSString stringWithFormat:NSLocalizedString( @"Could not load %@", nil ), [self _labelForPaneBundle:bundle]], nil, nil, nil ); + } +} + +- (BOOL) windowShouldClose:(id) sender { + if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { + NSLog( @"can't unselect current" ); + closeWhenPaneIsReady = YES; + return NO; + } + return YES; +} + +- (void) windowWillClose:(NSNotification *) notification { + [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; + [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; + [currentPaneIdentifier autorelease]; + currentPaneIdentifier = nil; + //[loadedPanes removeAllObjects]; +} + +- (NSToolbarItem *) toolbar:(NSToolbar *) toolbar itemForItemIdentifier:(NSString *) itemIdentifier willBeInsertedIntoToolbar:(BOOL) flag { + NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease]; + if( [itemIdentifier isEqualToString:MVToolbarShowAllItemIdentifier] ) { + [toolbarItem setLabel:NSLocalizedString( @"Show All", nil )]; + [toolbarItem setImage:[NSImage imageNamed:@"NSApplicationIcon"]]; + [toolbarItem setTarget:self]; + [toolbarItem setAction:@selector( showAll: )]; + } else { + NSBundle *bundle = [NSBundle bundleWithIdentifier:itemIdentifier]; + if( bundle ) { + [toolbarItem setLabel:[self _labelForPaneBundle:bundle]]; + [toolbarItem setPaletteLabel:[self _paletteLabelForPaneBundle:bundle]]; + [toolbarItem setImage:[self _imageForPaneBundle:bundle]]; + [toolbarItem setTarget:self]; + [toolbarItem setAction:@selector( _selectPreferencePane: )]; + } else toolbarItem = nil; + } + return toolbarItem; +} + +- (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *) toolbar { + NSMutableArray *fixed = [NSMutableArray arrayWithObjects:MVToolbarShowAllItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; + NSArray *defaults = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneDefaults" ofType:@"plist"]]; + [fixed addObjectsFromArray:defaults]; + return fixed; +} + +- (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *) toolbar { + NSMutableArray *items = [NSMutableArray array]; + NSEnumerator *enumerator = [panes objectEnumerator]; + id item = nil; + while( ( item = [enumerator nextObject] ) ) + [items addObject:[item bundleIdentifier]]; + //[items addObject:MVToolbarShowAllItemIdentifier]; + [items addObject:NSToolbarSeparatorItemIdentifier]; + return items; +} +@end + +@implementation MVPreferencesController (MVPreferencesControllerPrivate) +- (IBAction) _selectPreferencePane:(id) sender { + [self selectPreferencePaneByIdentifier:[sender itemIdentifier]]; +} + +- (void) _doUnselect:(NSNotification *) notification { + if( closeWhenPaneIsReady ) [window close]; + [self selectPreferencePaneByIdentifier:pendingPane]; +} + +- (void) _resizeWindowForContentView:(NSView *) view { + NSRect windowFrame, newWindowFrame; + unsigned int newWindowHeight; + + windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]]; + newWindowHeight = NSHeight( [view frame] ); + if( [[window toolbar] isVisible] ) + newWindowHeight += NSHeight( [[[window toolbar] _toolbarView] frame] ); + newWindowFrame = [NSWindow frameRectForContentRect:NSMakeRect( NSMinX( windowFrame ), NSMaxY( windowFrame ) - newWindowHeight, NSWidth( windowFrame ), newWindowHeight ) styleMask:[window styleMask]]; + + [window setFrame:newWindowFrame display:YES animate:[window isVisible]]; +} + +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle { + NSImage *image = nil; + NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + image = [[[cache objectForKey:@"MVPreferencePaneImage"] retain] autorelease]; + if( ! image ) { + NSDictionary *info = [bundle infoDictionary]; + image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"NSPrefPaneIconFile"]]] autorelease]; + if( ! image ) image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"CFBundleIconFile"]]] autorelease]; + if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; + cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + if( image ) [cache setObject:image forKey:@"MVPreferencePaneImage"]; + } + return image; +} + +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle { + NSString *label = nil; + NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + label = [[[cache objectForKey:@"MVPreferencePanePaletteLabel"] retain] autorelease]; + if( ! label ) { + NSDictionary *info = [bundle infoDictionary]; + label = NSLocalizedStringFromTableInBundle( @"NSPrefPaneIconLabel", @"InfoPlist", bundle, nil ); + if( [label isEqualToString:@"NSPrefPaneIconLabel"] ) label = [info objectForKey:@"NSPrefPaneIconLabel"]; + if( ! label ) label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); + if( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; + if( ! label ) label = [bundle bundleIdentifier]; + if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; + cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + if( label ) [cache setObject:label forKey:@"MVPreferencePanePaletteLabel"]; + } + return label; +} + +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle { + NSString *label = nil; + NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + label = [[[cache objectForKey:@"MVPreferencePaneLabel"] retain] autorelease]; + if( ! label ) { + NSDictionary *info = [bundle infoDictionary]; + label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); + if( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; + if( ! label ) label = [bundle bundleIdentifier]; + if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; + cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + if( label ) [cache setObject:label forKey:@"MVPreferencePaneLabel"]; + } + return label; +} +@end + diff --git a/mozilla/camino/PreferencePanes/MVPreferencesGroupedIconView.m b/mozilla/camino/PreferencePanes/MVPreferencesGroupedIconView.m new file mode 100644 index 00000000000..f7ec7819515 --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferencesGroupedIconView.m @@ -0,0 +1,157 @@ +#import "MVPreferencesGroupedIconView.h" +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (unsigned int) _numberOfRows; +@end + +@interface MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups; +- (void) _sizeToFit; +- (NSRect) _rectForGroupAtIndex:(unsigned int) index; +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index; +- (void) _generateGroupViews; +- (void) _generateGroupViewAtIndex:(unsigned int) index; +@end + +@implementation MVPreferencesGroupedIconView +const unsigned int groupViewHeight = 95; +const unsigned int multiIconViewYOffset = 18; +const unsigned int sideGutterWidths = 15; +const unsigned int extraRowHeight = 69; + +- (id) initWithFrame:(NSRect) frame { + if( ( self = [super initWithFrame:frame] ) ) { + groupMultiIconViews = [[NSMutableArray array] retain]; + } + return self; +} + +- (void) drawRect:(NSRect) rect { + [self _generateGroupViews]; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setPreferencePaneGroups:(NSArray *) newPreferencePaneGroups { + [preferencePaneGroups autorelease]; + preferencePaneGroups = [newPreferencePaneGroups retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePaneGroups { + return preferencePaneGroups; +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + [[self window] makeFirstResponder:[self viewWithTag:0]]; + return YES; +} + +- (BOOL) resignFirstResponder { + return YES; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} +@end + +@implementation MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups { + return [[self preferencePaneGroups] count]; +} + +- (void) _sizeToFit { + if( ! [self _numberOfGroups] ) return; + [self _generateGroupViews]; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _rectForGroupAtIndex:[self _numberOfGroups] - 1] ) ) ]; +} + +- (NSRect) _rectForGroupAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( 0., (index * groupViewHeight ) + multiIconViewYOffset + index + extra, NSWidth( [self frame] ), groupViewHeight ); +} + +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + if( ! index ) return NSZeroRect; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( sideGutterWidths, ((index + 1) * groupViewHeight) - groupViewHeight + index + extra, NSWidth( [self frame] ) - (sideGutterWidths * 2), 1 ); +} + +- (void) _generateGroupViews { + unsigned int groupIndex, groupCount; + + groupCount = [self _numberOfGroups]; + for( groupIndex = 0; groupIndex < groupCount; groupIndex++ ) + [self _generateGroupViewAtIndex:groupIndex]; +} + +- (void) _generateGroupViewAtIndex:(unsigned int) index { + MVPreferencesMultipleIconView *multiIconView = nil; + NSString *identifier = [[preferencePaneGroups objectAtIndex:index] objectForKey:@"identifier"]; + NSString *name = NSLocalizedStringFromTable( identifier, @"MVPreferencePaneGroups", nil ); + NSDictionary *attributesDictionary; + unsigned nameHeight = 0; + + if( ! ( multiIconView = [self viewWithTag:index] ) ) { + NSMutableArray *panes = [NSMutableArray array]; + NSBox *sep = [[[NSBox alloc] initWithFrame:[self _rectForGroupSeparatorAtIndex:index]] autorelease]; + NSEnumerator *enumerator = [[[preferencePaneGroups objectAtIndex:index] objectForKey:@"panes"] objectEnumerator]; + id pane = nil, bundle = 0; + + multiIconView = [[[MVPreferencesMultipleIconView alloc] initWithFrame:[self _rectForGroupAtIndex:index]] autorelease]; + while( ( pane = [enumerator nextObject] ) ) { + bundle = [NSBundle bundleWithIdentifier:pane]; + if( bundle ) [panes addObject:bundle]; + } + + [multiIconView setPreferencesController:preferencesController]; + [multiIconView setPreferencePanes:panes]; + [multiIconView setTag:index]; + + [sep setBoxType:NSBoxSeparator]; + [sep setBorderType:NSBezelBorder]; + + [self addSubview:multiIconView]; + [self addSubview:sep]; +// if( ! index ) [[self window] makeFirstResponder:multiIconView]; + if( index - 1 >= 0 ) [[self viewWithTag:index - 1] setNextKeyView:multiIconView]; + if( index == [self _numberOfGroups] - 1 ) [multiIconView setNextKeyView:[self viewWithTag:0]]; + } + + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:13.], NSFontAttributeName, nil]; + nameHeight = [[NSFont boldSystemFontOfSize:13.] ascender]; + [name drawAtPoint:NSMakePoint( sideGutterWidths - 1, NSMinY( [multiIconView frame] ) - nameHeight - 1 ) withAttributes:attributesDictionary]; +} +@end diff --git a/mozilla/camino/PreferencePanes/MVPreferencesMultipleIconView.m b/mozilla/camino/PreferencePanes/MVPreferencesMultipleIconView.m new file mode 100644 index 00000000000..571f1f80192 --- /dev/null +++ b/mozilla/camino/PreferencePanes/MVPreferencesMultipleIconView.m @@ -0,0 +1,393 @@ +#import +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" +#import "CHImageAdditions.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst; +- (void) _focusLast; +- (unsigned int) _iconsWide; +- (unsigned int) _numberOfIcons; +- (unsigned int) _numberOfRows; +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index; +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index; +- (NSRect) _boundsForIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index; +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect; +- (void) _sizeToFit; +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event; +@end + +@interface MVPreferencesController (MVPreferencesControllerPrivate) +- (IBAction) _selectPreferencePane:(id) sender; +- (void) _resizeWindowForContentView:(NSView *) view; +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; +@end + +@implementation MVPreferencesMultipleIconView +const NSSize buttonSize = { 81., 75. }; +const NSSize iconSize = { 32., 32. }; +const unsigned int titleBaseline = 15; +const unsigned int iconBaseline = 30; +const unsigned int bottomBorder = 15; + +- (id) initWithFrame:(NSRect) rect { + if( ( self = [super initWithFrame:rect] ) ) { + pressedIconIndex = NSNotFound; + focusedIndex = NSNotFound; + selectedPane = nil; + } + return self; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setSelectedPane:(NSBundle *) newSelectedPane { + selectedPane = newSelectedPane; + [self setNeedsDisplay:YES]; +} + +- (void) mouseDown:(NSEvent *) event { + NSPoint eventLocation; + NSRect slopRect; + const float dragSlop = 4.; + unsigned int index; + NSRect buttonRect; + BOOL mouseInBounds = NO; + + eventLocation = [self convertPoint:[event locationInWindow] fromView:nil]; + slopRect = NSInsetRect( NSMakeRect( eventLocation.x, eventLocation.y, 1., 1. ), -dragSlop, -dragSlop ); + + index = floor( eventLocation.x / buttonSize.width ) + ( floor( eventLocation.y / buttonSize.height ) * [self _iconsWide] ); + buttonRect = [self _boundsForIndex:index]; + if( index >= ( [self _iconsWide] * ( floor( eventLocation.y / buttonSize.height ) + 1 ) ) ) return; + if( ! NSWidth( buttonRect ) ) return; + + pressedIconIndex = index; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + while( 1 ) { + NSEvent *nextEvent; + NSPoint nextEventLocation; + unsigned int newPressedIconIndex; + + nextEvent = [NSApp nextEventMatchingMask:NSLeftMouseDraggedMask|NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]; + + nextEventLocation = [self convertPoint:[nextEvent locationInWindow] fromView:nil]; + mouseInBounds = NSMouseInRect(nextEventLocation, buttonRect, [self isFlipped]); + newPressedIconIndex = ( mouseInBounds ? index : NSNotFound ); + if( newPressedIconIndex != pressedIconIndex ) { + pressedIconIndex = newPressedIconIndex; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + } + + if( [nextEvent type] == NSLeftMouseUp ) break; + else if( ! NSMouseInRect( nextEventLocation, slopRect, NO ) ) { + if( [self _dragIconIndex:index event:event] ) { + mouseInBounds = NO; + break; + } + } + } + + pressedIconIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + if( mouseInBounds ) + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:index] bundleIdentifier]]; +} + +#define kTabCharCode 9 +#define kShiftTabCharCode 25 +#define kSpaceCharCode 32 + +- (void) keyDown:(NSEvent *) theEvent { + NSView *nextView = nil; + if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = 0; + else if( ! ( [theEvent modifierFlags] & NSShiftKeyMask ) ) focusedIndex++; + if( focusedIndex >= [self _numberOfIcons] ) { + if( ( nextView = [self nextValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusFirst]; + } else focusedIndex = 0; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kShiftTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = [self _numberOfIcons] - 1; + else if( [theEvent modifierFlags] & NSShiftKeyMask ) focusedIndex--; + if( (signed) focusedIndex < 0 && [self _numberOfIcons] ) { + if( ( nextView = [self previousValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusLast]; + } else focusedIndex = [self _numberOfIcons] - 1; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kSpaceCharCode ) { + if( focusedIndex != NSNotFound && focusedIndex < [self _numberOfIcons] && focusedIndex >= 0 ) { + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:focusedIndex] bundleIdentifier]]; + focusedIndex = NSNotFound; + } + } +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + focusedIndex = NSNotFound; + return YES; +} + +- (BOOL) resignFirstResponder { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + focusedIndex = NSNotFound; + return YES; +} + +- (void) drawRect:(NSRect) rect { + unsigned int paneIndex, paneCount; + + paneCount = [self _numberOfIcons]; + for( paneIndex = 0; paneIndex < paneCount; paneIndex++ ) + [self _drawIconAtIndex:paneIndex drawRect:rect]; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} + +- (int) tag { + return tag; +} + +- (void) setTag:(int) newTag { + tag = newTag; +} + +- (NSDragOperation) draggingSourceOperationMaskForLocal:(BOOL) flag { + return NSDragOperationMove; +} + +- (void) draggedImage:(NSImage *)image endedAt:(NSPoint) screenPoint operation:(NSDragOperation) operation { +} + +- (BOOL) ignoreModifierKeysWhileDragging { + return YES; +} +@end + +@implementation MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst { + focusedIndex = 0; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (void) _focusLast { + focusedIndex = [self _numberOfIcons] - 1; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (unsigned int) _iconsWide { + return NSWidth( [self bounds] ) / buttonSize.width; +} + +- (unsigned int) _numberOfIcons { + return [[self preferencePanes] count]; +} + +- (unsigned int) _numberOfRows { + unsigned int row = 0, column = 0; + if( ! [self _column:&column andRow:&row forIndex:[self _numberOfIcons] - 1] ) return 0; + return row; +} + +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index { + return [[self preferencePanes] objectAtIndex:index] == selectedPane; +} + +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index { + if( index >= [self _numberOfIcons] ) return NO; + + *row = index / [self _iconsWide]; + *column = index % [self _iconsWide]; + + return YES; +} + +- (NSRect) _boundsForIndex:(unsigned int) index { + unsigned int row = 0, column = 0, leftEdge = 0; + + if( ! [self _column:&column andRow:&row forIndex:index] ) return NSZeroRect; + + leftEdge = ( NSWidth( _bounds ) - ( [self _iconsWide] * buttonSize.width ) ) / 2. ; + + return NSMakeRect( ( column * buttonSize.width ) + leftEdge, row * buttonSize.height - (row * 6), buttonSize.width, buttonSize.height ); +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index { + NSString *unused; + return [self _iconImage:image andName:name andIdentifier:&unused forIndex:index]; +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index { + NSDictionary *info = nil; + NSBundle *pane = nil; + + if( index >= [self _numberOfIcons] ) return NO; + + pane = [[self preferencePanes] objectAtIndex:index]; + info = [pane infoDictionary]; + *image = [preferencesController _imageForPaneBundle:pane]; + *name = [preferencesController _paletteLabelForPaneBundle:pane]; + *identifier = [pane bundleIdentifier]; + + return YES; +} + +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect { + NSImage *image; + NSString *name; + unsigned int row, column; + NSPoint drawPoint; + float nameHeight; + NSRect buttonRect, destinationRect; + NSDictionary *attributesDictionary; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; + + buttonRect = [self _boundsForIndex:index]; + if( ! NSIntersectsRect( buttonRect, drawRect ) ) return; + if( ! [self _iconImage:&image andName:&name forIndex:index] ) return; + if( ! [self _column:&column andRow:&row forIndex:index] ) return; + + // Draw dark gray rectangle around currently selected icon (for MultipleIconView) + if( [self _isIconSelectedAtIndex:index] ) { + [[NSColor colorWithCalibratedWhite:0.8 alpha:0.75] set]; + NSRectFillUsingOperation(buttonRect, NSCompositeSourceOver); + } + + if( focusedIndex == index ) { + CGContextSaveGState( context ); + NSSetFocusRingStyle( NSFocusRingAbove ); + } + + // Draw icon, dark if it is currently being pressed + destinationRect = NSIntegralRect( NSMakeRect( NSMidX( buttonRect) - iconSize.width / 2., NSMaxY( buttonRect ) - iconBaseline - iconSize.height, iconSize.width, iconSize.height ) ); + destinationRect.size = iconSize; + if( index != pressedIconIndex && image ) [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + else if( image ) { + NSImage *darkImage; + NSSize darkImageSize; + + darkImage = [image copy]; + darkImageSize = [darkImage size]; + [darkImage lockFocus]; { + [[NSColor blackColor] set]; + NSRectFillUsingOperation( NSMakeRect( 0., 0., darkImageSize.width, darkImageSize.height ), NSCompositeSourceIn ); + [darkImage unlockFocus]; + } + + [darkImage drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:.6666667]; + [darkImage release]; + } + if( focusedIndex == index ) CGContextRestoreGState( context ); + + // Draw text + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + drawPoint = NSMakePoint( rint( buttonSize.width + 2 * NSMinX( buttonRect ) - NSWidth( _bounds ) - 1 ), rint( NSMaxY( buttonRect ) - titleBaseline - nameHeight ) ); + [name drawAtPoint:drawPoint withAttributes:attributesDictionary]; +} + +- (void) _sizeToFit { + if( ! [self preferencePanes] ) return; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _boundsForIndex:[self _numberOfIcons] - 1] ) + bottomBorder ) ]; +} + +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event { + NSImage *iconImage; + NSString *name; + NSString *identifier; + + if( ! [self _iconImage:&iconImage andName:&name andIdentifier:&identifier forIndex:index] ) + return YES; + + return [self _dragIconImage:iconImage andName:name andIdentifier:identifier event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event { + return [self _dragIconImage:iconImage andName:name andIdentifier:name event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event { + NSImage *dragImage; + NSPasteboard *pasteboard; + NSPoint dragPoint, startPoint; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + + dragImage = [[NSImage alloc] initWithSize:buttonSize]; + [dragImage lockFocus]; { + float nameHeight; + NSSize nameSize; + NSDictionary *attributesDictionary; + + [iconImage drawInRect:NSMakeRect( buttonSize.width / 2. - iconSize.width / 2., iconBaseline, iconSize.width, iconSize.height ) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:.5]; + + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, [[NSColor blackColor] colorWithAlphaComponent:.5], NSForegroundColorAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameSize = [name sizeWithAttributes:attributesDictionary]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + [name drawAtPoint:NSMakePoint( 0., nameHeight + titleBaseline - nameSize.height ) withAttributes:attributesDictionary]; + [dragImage unlockFocus]; + } + + pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:@"NSToolbarIndividualItemDragType"] owner:nil]; + [pasteboard setString:identifier forType:@"NSToolbarItemIdentiferPboardType"]; + + dragPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + startPoint = [self _boundsForIndex:[preferencePanes indexOfObject:[NSBundle bundleWithIdentifier:identifier]]].origin; + startPoint.y += buttonSize.height; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + pressedIconIndex = NSNotFound; + [self dragImage:dragImage at:startPoint offset:NSZeroSize event:event pasteboard:pasteboard source:self slideBack:YES]; + + return YES; +} +@end \ No newline at end of file diff --git a/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib b/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib new file mode 100644 index 00000000000..dc75f9a235a --- /dev/null +++ b/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib @@ -0,0 +1,55 @@ +{ + IBClasses = ( + { + ACTIONS = { + displayFontPanel = id; + restoreDefaultColors = id; + revertColors = id; + setAlsoUseForIncoming = id; + setColors = id; + setDontShowDisconnected = id; + setDontShowZero = id; + setOverrideColors = id; + setShowOnlineBuddiesInDock = id; + setShowServiceStatusInDock = id; + setShowUserStatusInDock = id; + setSmileyType = id; + setUseAquaServiceIcons = id; + setUseGraphicalSmilies = id; + }; + CLASS = AppearancePane; + LANGUAGE = ObjC; + OUTLETS = { + actionWell = id; + alsoUseForIncomingCheck = id; + backgroundWell = id; + dontShowDisconnectedCheck = id; + dontShowZeroCheck = id; + fontSampleText = id; + foregroundWell = id; + myFont = id; + overrideColorsCheck = id; + showOnlineBuddiesInDockCheck = id; + showServiceStatusInDockCheck = id; + showUserStatusInDockCheck = id; + smileyTypeChoice = id; + systemNameWell = id; + theirNameWell = id; + translationNameWell = id; + useAquaServiceIconsCheck = id; + useGraphicalSmiliesCheck = id; + yourNameWell = id; + }; + SUPERCLASS = NSPreferencePane; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = NSPreferencePane; + LANGUAGE = ObjC; + OUTLETS = {_firstKeyView = id; _initialKeyView = id; _lastKeyView = id; _window = id; }; + SUPERCLASS = NSObject; + }, + {CLASS = PersonalPane; LANGUAGE = ObjC; SUPERCLASS = NSPreferencePane; } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib b/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib new file mode 100644 index 00000000000..a0052e409ef --- /dev/null +++ b/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib @@ -0,0 +1,26 @@ + + + + + IBDocumentLocation + 372 4 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBGroupedObjects + + 3 + + 153 + 155 + + + IBLastGroupID + 4 + IBOpenObjects + + 5 + + IBSystem Version + 5Q125 + + diff --git a/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib b/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib new file mode 100644 index 00000000000..26d0953e8a2 Binary files /dev/null and b/mozilla/camino/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib differ diff --git a/mozilla/camino/PreferencePanes/Personal/Personal.nib/classes.nib b/mozilla/camino/PreferencePanes/Personal/Personal.nib/classes.nib new file mode 100644 index 00000000000..dc75f9a235a --- /dev/null +++ b/mozilla/camino/PreferencePanes/Personal/Personal.nib/classes.nib @@ -0,0 +1,55 @@ +{ + IBClasses = ( + { + ACTIONS = { + displayFontPanel = id; + restoreDefaultColors = id; + revertColors = id; + setAlsoUseForIncoming = id; + setColors = id; + setDontShowDisconnected = id; + setDontShowZero = id; + setOverrideColors = id; + setShowOnlineBuddiesInDock = id; + setShowServiceStatusInDock = id; + setShowUserStatusInDock = id; + setSmileyType = id; + setUseAquaServiceIcons = id; + setUseGraphicalSmilies = id; + }; + CLASS = AppearancePane; + LANGUAGE = ObjC; + OUTLETS = { + actionWell = id; + alsoUseForIncomingCheck = id; + backgroundWell = id; + dontShowDisconnectedCheck = id; + dontShowZeroCheck = id; + fontSampleText = id; + foregroundWell = id; + myFont = id; + overrideColorsCheck = id; + showOnlineBuddiesInDockCheck = id; + showServiceStatusInDockCheck = id; + showUserStatusInDockCheck = id; + smileyTypeChoice = id; + systemNameWell = id; + theirNameWell = id; + translationNameWell = id; + useAquaServiceIconsCheck = id; + useGraphicalSmiliesCheck = id; + yourNameWell = id; + }; + SUPERCLASS = NSPreferencePane; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = NSPreferencePane; + LANGUAGE = ObjC; + OUTLETS = {_firstKeyView = id; _initialKeyView = id; _lastKeyView = id; _window = id; }; + SUPERCLASS = NSObject; + }, + {CLASS = PersonalPane; LANGUAGE = ObjC; SUPERCLASS = NSPreferencePane; } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/camino/PreferencePanes/Personal/Personal.nib/info.nib b/mozilla/camino/PreferencePanes/Personal/Personal.nib/info.nib new file mode 100644 index 00000000000..a0052e409ef --- /dev/null +++ b/mozilla/camino/PreferencePanes/Personal/Personal.nib/info.nib @@ -0,0 +1,26 @@ + + + + + IBDocumentLocation + 372 4 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBGroupedObjects + + 3 + + 153 + 155 + + + IBLastGroupID + 4 + IBOpenObjects + + 5 + + IBSystem Version + 5Q125 + + diff --git a/mozilla/camino/PreferencePanes/Personal/Personal.nib/objects.nib b/mozilla/camino/PreferencePanes/Personal/Personal.nib/objects.nib new file mode 100644 index 00000000000..26d0953e8a2 Binary files /dev/null and b/mozilla/camino/PreferencePanes/Personal/Personal.nib/objects.nib differ diff --git a/mozilla/camino/resources/localized/English.lproj/MVPreferencePaneGroups.strings b/mozilla/camino/resources/localized/English.lproj/MVPreferencePaneGroups.strings new file mode 100644 index 00000000000..b410cd0bc55 Binary files /dev/null and b/mozilla/camino/resources/localized/English.lproj/MVPreferencePaneGroups.strings differ diff --git a/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/classes.nib b/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/classes.nib new file mode 100644 index 00000000000..aeac16577ff --- /dev/null +++ b/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/classes.nib @@ -0,0 +1,32 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {showAll = id; showPreferences = id; }; + CLASS = MVPreferencesController; + LANGUAGE = ObjC; + OUTLETS = { + groupView = id; + loadingImageView = id; + loadingTextFeld = id; + loadingView = id; + multiView = id; + window = id; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = MVPreferencesGroupedIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + }, + { + CLASS = MVPreferencesMultipleIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/info.nib b/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/info.nib new file mode 100644 index 00000000000..d6140876225 --- /dev/null +++ b/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 19 36 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBSystem Version + 5Q45 + + diff --git a/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/objects.nib b/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/objects.nib new file mode 100644 index 00000000000..92598fe1cf1 Binary files /dev/null and b/mozilla/camino/resources/localized/English.lproj/MVPreferences.nib/objects.nib differ diff --git a/mozilla/camino/src/preferences/MVPreferencePaneDefaults.plist b/mozilla/camino/src/preferences/MVPreferencePaneDefaults.plist new file mode 100644 index 00000000000..e1574407fcb --- /dev/null +++ b/mozilla/camino/src/preferences/MVPreferencePaneDefaults.plist @@ -0,0 +1,7 @@ +( Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane +) diff --git a/mozilla/camino/src/preferences/MVPreferencePaneGroups.plist b/mozilla/camino/src/preferences/MVPreferencePaneGroups.plist new file mode 100644 index 00000000000..ad5199ee34b --- /dev/null +++ b/mozilla/camino/src/preferences/MVPreferencePaneGroups.plist @@ -0,0 +1,14 @@ +( + { + identifier = chimera; + panes = ( + Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane, + Chimera.AdvancedPrefPane + ); + } +) \ No newline at end of file diff --git a/mozilla/camino/src/preferences/MVPreferencesGroupedIconView.m b/mozilla/camino/src/preferences/MVPreferencesGroupedIconView.m new file mode 100644 index 00000000000..f7ec7819515 --- /dev/null +++ b/mozilla/camino/src/preferences/MVPreferencesGroupedIconView.m @@ -0,0 +1,157 @@ +#import "MVPreferencesGroupedIconView.h" +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (unsigned int) _numberOfRows; +@end + +@interface MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups; +- (void) _sizeToFit; +- (NSRect) _rectForGroupAtIndex:(unsigned int) index; +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index; +- (void) _generateGroupViews; +- (void) _generateGroupViewAtIndex:(unsigned int) index; +@end + +@implementation MVPreferencesGroupedIconView +const unsigned int groupViewHeight = 95; +const unsigned int multiIconViewYOffset = 18; +const unsigned int sideGutterWidths = 15; +const unsigned int extraRowHeight = 69; + +- (id) initWithFrame:(NSRect) frame { + if( ( self = [super initWithFrame:frame] ) ) { + groupMultiIconViews = [[NSMutableArray array] retain]; + } + return self; +} + +- (void) drawRect:(NSRect) rect { + [self _generateGroupViews]; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setPreferencePaneGroups:(NSArray *) newPreferencePaneGroups { + [preferencePaneGroups autorelease]; + preferencePaneGroups = [newPreferencePaneGroups retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePaneGroups { + return preferencePaneGroups; +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + [[self window] makeFirstResponder:[self viewWithTag:0]]; + return YES; +} + +- (BOOL) resignFirstResponder { + return YES; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} +@end + +@implementation MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups { + return [[self preferencePaneGroups] count]; +} + +- (void) _sizeToFit { + if( ! [self _numberOfGroups] ) return; + [self _generateGroupViews]; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _rectForGroupAtIndex:[self _numberOfGroups] - 1] ) ) ]; +} + +- (NSRect) _rectForGroupAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( 0., (index * groupViewHeight ) + multiIconViewYOffset + index + extra, NSWidth( [self frame] ), groupViewHeight ); +} + +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + if( ! index ) return NSZeroRect; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( sideGutterWidths, ((index + 1) * groupViewHeight) - groupViewHeight + index + extra, NSWidth( [self frame] ) - (sideGutterWidths * 2), 1 ); +} + +- (void) _generateGroupViews { + unsigned int groupIndex, groupCount; + + groupCount = [self _numberOfGroups]; + for( groupIndex = 0; groupIndex < groupCount; groupIndex++ ) + [self _generateGroupViewAtIndex:groupIndex]; +} + +- (void) _generateGroupViewAtIndex:(unsigned int) index { + MVPreferencesMultipleIconView *multiIconView = nil; + NSString *identifier = [[preferencePaneGroups objectAtIndex:index] objectForKey:@"identifier"]; + NSString *name = NSLocalizedStringFromTable( identifier, @"MVPreferencePaneGroups", nil ); + NSDictionary *attributesDictionary; + unsigned nameHeight = 0; + + if( ! ( multiIconView = [self viewWithTag:index] ) ) { + NSMutableArray *panes = [NSMutableArray array]; + NSBox *sep = [[[NSBox alloc] initWithFrame:[self _rectForGroupSeparatorAtIndex:index]] autorelease]; + NSEnumerator *enumerator = [[[preferencePaneGroups objectAtIndex:index] objectForKey:@"panes"] objectEnumerator]; + id pane = nil, bundle = 0; + + multiIconView = [[[MVPreferencesMultipleIconView alloc] initWithFrame:[self _rectForGroupAtIndex:index]] autorelease]; + while( ( pane = [enumerator nextObject] ) ) { + bundle = [NSBundle bundleWithIdentifier:pane]; + if( bundle ) [panes addObject:bundle]; + } + + [multiIconView setPreferencesController:preferencesController]; + [multiIconView setPreferencePanes:panes]; + [multiIconView setTag:index]; + + [sep setBoxType:NSBoxSeparator]; + [sep setBorderType:NSBezelBorder]; + + [self addSubview:multiIconView]; + [self addSubview:sep]; +// if( ! index ) [[self window] makeFirstResponder:multiIconView]; + if( index - 1 >= 0 ) [[self viewWithTag:index - 1] setNextKeyView:multiIconView]; + if( index == [self _numberOfGroups] - 1 ) [multiIconView setNextKeyView:[self viewWithTag:0]]; + } + + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:13.], NSFontAttributeName, nil]; + nameHeight = [[NSFont boldSystemFontOfSize:13.] ascender]; + [name drawAtPoint:NSMakePoint( sideGutterWidths - 1, NSMinY( [multiIconView frame] ) - nameHeight - 1 ) withAttributes:attributesDictionary]; +} +@end diff --git a/mozilla/camino/src/preferences/MVPreferencesMultipleIconView.m b/mozilla/camino/src/preferences/MVPreferencesMultipleIconView.m new file mode 100644 index 00000000000..571f1f80192 --- /dev/null +++ b/mozilla/camino/src/preferences/MVPreferencesMultipleIconView.m @@ -0,0 +1,393 @@ +#import +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" +#import "CHImageAdditions.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst; +- (void) _focusLast; +- (unsigned int) _iconsWide; +- (unsigned int) _numberOfIcons; +- (unsigned int) _numberOfRows; +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index; +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index; +- (NSRect) _boundsForIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index; +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect; +- (void) _sizeToFit; +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event; +@end + +@interface MVPreferencesController (MVPreferencesControllerPrivate) +- (IBAction) _selectPreferencePane:(id) sender; +- (void) _resizeWindowForContentView:(NSView *) view; +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; +@end + +@implementation MVPreferencesMultipleIconView +const NSSize buttonSize = { 81., 75. }; +const NSSize iconSize = { 32., 32. }; +const unsigned int titleBaseline = 15; +const unsigned int iconBaseline = 30; +const unsigned int bottomBorder = 15; + +- (id) initWithFrame:(NSRect) rect { + if( ( self = [super initWithFrame:rect] ) ) { + pressedIconIndex = NSNotFound; + focusedIndex = NSNotFound; + selectedPane = nil; + } + return self; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setSelectedPane:(NSBundle *) newSelectedPane { + selectedPane = newSelectedPane; + [self setNeedsDisplay:YES]; +} + +- (void) mouseDown:(NSEvent *) event { + NSPoint eventLocation; + NSRect slopRect; + const float dragSlop = 4.; + unsigned int index; + NSRect buttonRect; + BOOL mouseInBounds = NO; + + eventLocation = [self convertPoint:[event locationInWindow] fromView:nil]; + slopRect = NSInsetRect( NSMakeRect( eventLocation.x, eventLocation.y, 1., 1. ), -dragSlop, -dragSlop ); + + index = floor( eventLocation.x / buttonSize.width ) + ( floor( eventLocation.y / buttonSize.height ) * [self _iconsWide] ); + buttonRect = [self _boundsForIndex:index]; + if( index >= ( [self _iconsWide] * ( floor( eventLocation.y / buttonSize.height ) + 1 ) ) ) return; + if( ! NSWidth( buttonRect ) ) return; + + pressedIconIndex = index; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + while( 1 ) { + NSEvent *nextEvent; + NSPoint nextEventLocation; + unsigned int newPressedIconIndex; + + nextEvent = [NSApp nextEventMatchingMask:NSLeftMouseDraggedMask|NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]; + + nextEventLocation = [self convertPoint:[nextEvent locationInWindow] fromView:nil]; + mouseInBounds = NSMouseInRect(nextEventLocation, buttonRect, [self isFlipped]); + newPressedIconIndex = ( mouseInBounds ? index : NSNotFound ); + if( newPressedIconIndex != pressedIconIndex ) { + pressedIconIndex = newPressedIconIndex; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + } + + if( [nextEvent type] == NSLeftMouseUp ) break; + else if( ! NSMouseInRect( nextEventLocation, slopRect, NO ) ) { + if( [self _dragIconIndex:index event:event] ) { + mouseInBounds = NO; + break; + } + } + } + + pressedIconIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + if( mouseInBounds ) + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:index] bundleIdentifier]]; +} + +#define kTabCharCode 9 +#define kShiftTabCharCode 25 +#define kSpaceCharCode 32 + +- (void) keyDown:(NSEvent *) theEvent { + NSView *nextView = nil; + if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = 0; + else if( ! ( [theEvent modifierFlags] & NSShiftKeyMask ) ) focusedIndex++; + if( focusedIndex >= [self _numberOfIcons] ) { + if( ( nextView = [self nextValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusFirst]; + } else focusedIndex = 0; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kShiftTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = [self _numberOfIcons] - 1; + else if( [theEvent modifierFlags] & NSShiftKeyMask ) focusedIndex--; + if( (signed) focusedIndex < 0 && [self _numberOfIcons] ) { + if( ( nextView = [self previousValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusLast]; + } else focusedIndex = [self _numberOfIcons] - 1; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kSpaceCharCode ) { + if( focusedIndex != NSNotFound && focusedIndex < [self _numberOfIcons] && focusedIndex >= 0 ) { + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:focusedIndex] bundleIdentifier]]; + focusedIndex = NSNotFound; + } + } +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + focusedIndex = NSNotFound; + return YES; +} + +- (BOOL) resignFirstResponder { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + focusedIndex = NSNotFound; + return YES; +} + +- (void) drawRect:(NSRect) rect { + unsigned int paneIndex, paneCount; + + paneCount = [self _numberOfIcons]; + for( paneIndex = 0; paneIndex < paneCount; paneIndex++ ) + [self _drawIconAtIndex:paneIndex drawRect:rect]; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} + +- (int) tag { + return tag; +} + +- (void) setTag:(int) newTag { + tag = newTag; +} + +- (NSDragOperation) draggingSourceOperationMaskForLocal:(BOOL) flag { + return NSDragOperationMove; +} + +- (void) draggedImage:(NSImage *)image endedAt:(NSPoint) screenPoint operation:(NSDragOperation) operation { +} + +- (BOOL) ignoreModifierKeysWhileDragging { + return YES; +} +@end + +@implementation MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst { + focusedIndex = 0; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (void) _focusLast { + focusedIndex = [self _numberOfIcons] - 1; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (unsigned int) _iconsWide { + return NSWidth( [self bounds] ) / buttonSize.width; +} + +- (unsigned int) _numberOfIcons { + return [[self preferencePanes] count]; +} + +- (unsigned int) _numberOfRows { + unsigned int row = 0, column = 0; + if( ! [self _column:&column andRow:&row forIndex:[self _numberOfIcons] - 1] ) return 0; + return row; +} + +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index { + return [[self preferencePanes] objectAtIndex:index] == selectedPane; +} + +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index { + if( index >= [self _numberOfIcons] ) return NO; + + *row = index / [self _iconsWide]; + *column = index % [self _iconsWide]; + + return YES; +} + +- (NSRect) _boundsForIndex:(unsigned int) index { + unsigned int row = 0, column = 0, leftEdge = 0; + + if( ! [self _column:&column andRow:&row forIndex:index] ) return NSZeroRect; + + leftEdge = ( NSWidth( _bounds ) - ( [self _iconsWide] * buttonSize.width ) ) / 2. ; + + return NSMakeRect( ( column * buttonSize.width ) + leftEdge, row * buttonSize.height - (row * 6), buttonSize.width, buttonSize.height ); +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index { + NSString *unused; + return [self _iconImage:image andName:name andIdentifier:&unused forIndex:index]; +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index { + NSDictionary *info = nil; + NSBundle *pane = nil; + + if( index >= [self _numberOfIcons] ) return NO; + + pane = [[self preferencePanes] objectAtIndex:index]; + info = [pane infoDictionary]; + *image = [preferencesController _imageForPaneBundle:pane]; + *name = [preferencesController _paletteLabelForPaneBundle:pane]; + *identifier = [pane bundleIdentifier]; + + return YES; +} + +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect { + NSImage *image; + NSString *name; + unsigned int row, column; + NSPoint drawPoint; + float nameHeight; + NSRect buttonRect, destinationRect; + NSDictionary *attributesDictionary; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; + + buttonRect = [self _boundsForIndex:index]; + if( ! NSIntersectsRect( buttonRect, drawRect ) ) return; + if( ! [self _iconImage:&image andName:&name forIndex:index] ) return; + if( ! [self _column:&column andRow:&row forIndex:index] ) return; + + // Draw dark gray rectangle around currently selected icon (for MultipleIconView) + if( [self _isIconSelectedAtIndex:index] ) { + [[NSColor colorWithCalibratedWhite:0.8 alpha:0.75] set]; + NSRectFillUsingOperation(buttonRect, NSCompositeSourceOver); + } + + if( focusedIndex == index ) { + CGContextSaveGState( context ); + NSSetFocusRingStyle( NSFocusRingAbove ); + } + + // Draw icon, dark if it is currently being pressed + destinationRect = NSIntegralRect( NSMakeRect( NSMidX( buttonRect) - iconSize.width / 2., NSMaxY( buttonRect ) - iconBaseline - iconSize.height, iconSize.width, iconSize.height ) ); + destinationRect.size = iconSize; + if( index != pressedIconIndex && image ) [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + else if( image ) { + NSImage *darkImage; + NSSize darkImageSize; + + darkImage = [image copy]; + darkImageSize = [darkImage size]; + [darkImage lockFocus]; { + [[NSColor blackColor] set]; + NSRectFillUsingOperation( NSMakeRect( 0., 0., darkImageSize.width, darkImageSize.height ), NSCompositeSourceIn ); + [darkImage unlockFocus]; + } + + [darkImage drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:.6666667]; + [darkImage release]; + } + if( focusedIndex == index ) CGContextRestoreGState( context ); + + // Draw text + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + drawPoint = NSMakePoint( rint( buttonSize.width + 2 * NSMinX( buttonRect ) - NSWidth( _bounds ) - 1 ), rint( NSMaxY( buttonRect ) - titleBaseline - nameHeight ) ); + [name drawAtPoint:drawPoint withAttributes:attributesDictionary]; +} + +- (void) _sizeToFit { + if( ! [self preferencePanes] ) return; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _boundsForIndex:[self _numberOfIcons] - 1] ) + bottomBorder ) ]; +} + +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event { + NSImage *iconImage; + NSString *name; + NSString *identifier; + + if( ! [self _iconImage:&iconImage andName:&name andIdentifier:&identifier forIndex:index] ) + return YES; + + return [self _dragIconImage:iconImage andName:name andIdentifier:identifier event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event { + return [self _dragIconImage:iconImage andName:name andIdentifier:name event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event { + NSImage *dragImage; + NSPasteboard *pasteboard; + NSPoint dragPoint, startPoint; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + + dragImage = [[NSImage alloc] initWithSize:buttonSize]; + [dragImage lockFocus]; { + float nameHeight; + NSSize nameSize; + NSDictionary *attributesDictionary; + + [iconImage drawInRect:NSMakeRect( buttonSize.width / 2. - iconSize.width / 2., iconBaseline, iconSize.width, iconSize.height ) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:.5]; + + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, [[NSColor blackColor] colorWithAlphaComponent:.5], NSForegroundColorAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameSize = [name sizeWithAttributes:attributesDictionary]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + [name drawAtPoint:NSMakePoint( 0., nameHeight + titleBaseline - nameSize.height ) withAttributes:attributesDictionary]; + [dragImage unlockFocus]; + } + + pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:@"NSToolbarIndividualItemDragType"] owner:nil]; + [pasteboard setString:identifier forType:@"NSToolbarItemIdentiferPboardType"]; + + dragPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + startPoint = [self _boundsForIndex:[preferencePanes indexOfObject:[NSBundle bundleWithIdentifier:identifier]]].origin; + startPoint.y += buttonSize.height; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + pressedIconIndex = NSNotFound; + [self dragImage:dragImage at:startPoint offset:NSZeroSize event:event pasteboard:pasteboard source:self slideBack:YES]; + + return YES; +} +@end \ No newline at end of file diff --git a/mozilla/chimera/English.lproj/MVPreferencePaneGroups.strings b/mozilla/chimera/English.lproj/MVPreferencePaneGroups.strings new file mode 100644 index 00000000000..b410cd0bc55 Binary files /dev/null and b/mozilla/chimera/English.lproj/MVPreferencePaneGroups.strings differ diff --git a/mozilla/chimera/English.lproj/MVPreferences.nib/classes.nib b/mozilla/chimera/English.lproj/MVPreferences.nib/classes.nib new file mode 100644 index 00000000000..aeac16577ff --- /dev/null +++ b/mozilla/chimera/English.lproj/MVPreferences.nib/classes.nib @@ -0,0 +1,32 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {showAll = id; showPreferences = id; }; + CLASS = MVPreferencesController; + LANGUAGE = ObjC; + OUTLETS = { + groupView = id; + loadingImageView = id; + loadingTextFeld = id; + loadingView = id; + multiView = id; + window = id; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = MVPreferencesGroupedIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + }, + { + CLASS = MVPreferencesMultipleIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/chimera/English.lproj/MVPreferences.nib/info.nib b/mozilla/chimera/English.lproj/MVPreferences.nib/info.nib new file mode 100644 index 00000000000..d6140876225 --- /dev/null +++ b/mozilla/chimera/English.lproj/MVPreferences.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 19 36 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBSystem Version + 5Q45 + + diff --git a/mozilla/chimera/English.lproj/MVPreferences.nib/objects.nib b/mozilla/chimera/English.lproj/MVPreferences.nib/objects.nib new file mode 100644 index 00000000000..92598fe1cf1 Binary files /dev/null and b/mozilla/chimera/English.lproj/MVPreferences.nib/objects.nib differ diff --git a/mozilla/chimera/PreferencePanes/MVPreferencePaneDefaults.plist b/mozilla/chimera/PreferencePanes/MVPreferencePaneDefaults.plist new file mode 100644 index 00000000000..e1574407fcb --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferencePaneDefaults.plist @@ -0,0 +1,7 @@ +( Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane +) diff --git a/mozilla/chimera/PreferencePanes/MVPreferencePaneGroups.plist b/mozilla/chimera/PreferencePanes/MVPreferencePaneGroups.plist new file mode 100644 index 00000000000..ad5199ee34b --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferencePaneGroups.plist @@ -0,0 +1,14 @@ +( + { + identifier = chimera; + panes = ( + Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane, + Chimera.AdvancedPrefPane + ); + } +) \ No newline at end of file diff --git a/mozilla/chimera/PreferencePanes/MVPreferencePaneGroups.strings b/mozilla/chimera/PreferencePanes/MVPreferencePaneGroups.strings new file mode 100644 index 00000000000..b410cd0bc55 Binary files /dev/null and b/mozilla/chimera/PreferencePanes/MVPreferencePaneGroups.strings differ diff --git a/mozilla/chimera/PreferencePanes/MVPreferences.nib/classes.nib b/mozilla/chimera/PreferencePanes/MVPreferences.nib/classes.nib new file mode 100644 index 00000000000..aeac16577ff --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferences.nib/classes.nib @@ -0,0 +1,32 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {showAll = id; showPreferences = id; }; + CLASS = MVPreferencesController; + LANGUAGE = ObjC; + OUTLETS = { + groupView = id; + loadingImageView = id; + loadingTextFeld = id; + loadingView = id; + multiView = id; + window = id; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = MVPreferencesGroupedIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + }, + { + CLASS = MVPreferencesMultipleIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/chimera/PreferencePanes/MVPreferences.nib/info.nib b/mozilla/chimera/PreferencePanes/MVPreferences.nib/info.nib new file mode 100644 index 00000000000..d6140876225 --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferences.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 19 36 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBSystem Version + 5Q45 + + diff --git a/mozilla/chimera/PreferencePanes/MVPreferences.nib/objects.nib b/mozilla/chimera/PreferencePanes/MVPreferences.nib/objects.nib new file mode 100644 index 00000000000..92598fe1cf1 Binary files /dev/null and b/mozilla/chimera/PreferencePanes/MVPreferences.nib/objects.nib differ diff --git a/mozilla/chimera/PreferencePanes/MVPreferencesController.m b/mozilla/chimera/PreferencePanes/MVPreferencesController.m new file mode 100644 index 00000000000..77f6c82113e --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferencesController.m @@ -0,0 +1,298 @@ +#import +#import "MVPreferencesController.h" +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesGroupedIconView.h" +#import "CHToolbarAdditions.h" + +// #import "Defines.h" + +static MVPreferencesController *sharedInstance = nil; + +static NSString *MVToolbarShowAllItemIdentifier = @"MVToolbarShowAllItem"; +static NSString *MVPreferencesWindowNotification = @"MVPreferencesWindowNotification"; + +@interface NSToolbar (NSToolbarPrivate) +- (NSView *) _toolbarView; +@end + +@interface MVPreferencesController (MVPreferencesControllerPrivate) +- (void) _doUnselect:(NSNotification *) notification; +- (IBAction) _selectPreferencePane:(id) sender; +- (void) _resizeWindowForContentView:(NSView *) view; +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; +@end + +@implementation MVPreferencesController + ++ (MVPreferencesController *) sharedInstance { + return ( sharedInstance ? sharedInstance : [[[self alloc] init] autorelease] ); +} + +- (id) init { + if( ( self = [super init] ) ) { + unsigned i = 0; + NSBundle *bundle = nil; + NSString *bundlePath = [NSString stringWithFormat:@"%@/Contents/PreferencePanes", [[NSBundle mainBundle] bundlePath]]; + panes = [[[NSFileManager defaultManager] directoryContentsAtPath:bundlePath] mutableCopy]; + for( i = 0; i < [panes count]; i++ ) { + bundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/%@", bundlePath, [panes objectAtIndex:i]]]; + [bundle load]; + if( bundle ) [panes replaceObjectAtIndex:i withObject:bundle]; + else { + [panes removeObjectAtIndex:i]; + i--; + } + } + loadedPanes = [[NSMutableDictionary dictionary] retain]; + paneInfo = [[NSMutableDictionary dictionary] retain]; + [NSBundle loadNibNamed:@"MVPreferences" owner:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector( _doUnselect: ) name:NSPreferencePaneDoUnselectNotification object:nil]; + } + return self; +} + +- (void) dealloc { + [loadedPanes autorelease]; + [panes autorelease]; + [paneInfo autorelease]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + loadedPanes = nil; + panes = nil; + paneInfo = nil; + [super dealloc]; +} + +- (void) awakeFromNib { + NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"preferences.toolbar"] autorelease]; + NSArray *groups = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneGroups" ofType:@"plist"]]; + + if( groups ) { + [groupView setPreferencePanes:panes]; + [groupView setPreferencePaneGroups:groups]; + mainView = groupView; + } else { + [multiView setPreferencePanes:panes]; + mainView = multiView; + } + [self showAll:nil]; + + [window setDelegate:self]; + + [toolbar setAllowsUserCustomization:YES]; + [toolbar setAutosavesConfiguration:YES]; + [toolbar setDelegate:self]; + [toolbar setAlwaysCustomizableByDrag:YES]; + [toolbar setShowsContextMenu:NO]; + [window setToolbar:toolbar]; + [toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; + [toolbar setIndexOfFirstMovableItem:2]; +} + +- (NSWindow *) window { + return [[window retain] autorelease]; +} + +- (IBAction) showPreferences:(id) sender { + [self showAll:nil]; + [window makeKeyAndOrderFront:nil]; +} + +- (IBAction) showAll:(id) sender { + if( [[window contentView] isEqual:mainView] ) return; + if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { + /* more to handle later */ + NSLog( @"can't unselect current" ); + return; + } + [window setContentView:[[[NSView alloc] initWithFrame:[mainView frame]] autorelease]]; + + [window setTitle:[NSString stringWithFormat:NSLocalizedString( @"%@ Preferences", nil ), [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]]]; + [self _resizeWindowForContentView:mainView]; + + [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; + [window setContentView:mainView]; + [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; + + [currentPaneIdentifier autorelease]; + currentPaneIdentifier = nil; + + [window setInitialFirstResponder:mainView]; + [window makeFirstResponder:mainView]; +} + +- (void) selectPreferencePaneByIdentifier:(NSString *) identifier { + NSBundle *bundle = [NSBundle bundleWithIdentifier:identifier]; + if( bundle && ! [currentPaneIdentifier isEqualToString:identifier] ) { + NSPreferencePane *pane = nil; + NSView *prefView = nil; + if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { + /* more to handle later */ + NSLog( @"can't unselect current" ); + closeWhenPaneIsReady = NO; + [pendingPane autorelease]; + pendingPane = [identifier retain]; + return; + } + [pendingPane autorelease]; + pendingPane = nil; + [loadingImageView setImage:[self _imageForPaneBundle:bundle]]; + [loadingTextFeld setStringValue:[NSString stringWithFormat:NSLocalizedString( @"Loading %@...", nil ), [self _labelForPaneBundle:bundle]]]; + [window setTitle:[self _labelForPaneBundle:bundle]]; + [window setContentView:loadingView]; + [window display]; + if( ! ( pane = [loadedPanes objectForKey:identifier] ) ) { + pane = [[[[bundle principalClass] alloc] initWithBundle:bundle] autorelease]; + if( pane ) [loadedPanes setObject:pane forKey:identifier]; + } + if( [pane loadMainView] ) { + [pane willSelect]; + prefView = [pane mainView]; + + [self _resizeWindowForContentView:prefView]; + + [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; + [window setContentView:prefView]; + [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; + [pane didSelect]; + [[NSNotificationCenter defaultCenter] postNotificationName:MVPreferencesWindowNotification object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:window, @"window", nil]]; + [currentPaneIdentifier autorelease]; + currentPaneIdentifier = [identifier copy]; + + [window setInitialFirstResponder:[pane initialKeyView]]; + [window makeFirstResponder:[pane initialKeyView]]; + } else NSRunCriticalAlertPanel( NSLocalizedString( @"Preferences Error", nil ), [NSString stringWithFormat:NSLocalizedString( @"Could not load %@", nil ), [self _labelForPaneBundle:bundle]], nil, nil, nil ); + } +} + +- (BOOL) windowShouldClose:(id) sender { + if( currentPaneIdentifier && [[loadedPanes objectForKey:currentPaneIdentifier] shouldUnselect] != NSUnselectNow ) { + NSLog( @"can't unselect current" ); + closeWhenPaneIsReady = YES; + return NO; + } + return YES; +} + +- (void) windowWillClose:(NSNotification *) notification { + [[loadedPanes objectForKey:currentPaneIdentifier] willUnselect]; + [[loadedPanes objectForKey:currentPaneIdentifier] didUnselect]; + [currentPaneIdentifier autorelease]; + currentPaneIdentifier = nil; + //[loadedPanes removeAllObjects]; +} + +- (NSToolbarItem *) toolbar:(NSToolbar *) toolbar itemForItemIdentifier:(NSString *) itemIdentifier willBeInsertedIntoToolbar:(BOOL) flag { + NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease]; + if( [itemIdentifier isEqualToString:MVToolbarShowAllItemIdentifier] ) { + [toolbarItem setLabel:NSLocalizedString( @"Show All", nil )]; + [toolbarItem setImage:[NSImage imageNamed:@"NSApplicationIcon"]]; + [toolbarItem setTarget:self]; + [toolbarItem setAction:@selector( showAll: )]; + } else { + NSBundle *bundle = [NSBundle bundleWithIdentifier:itemIdentifier]; + if( bundle ) { + [toolbarItem setLabel:[self _labelForPaneBundle:bundle]]; + [toolbarItem setPaletteLabel:[self _paletteLabelForPaneBundle:bundle]]; + [toolbarItem setImage:[self _imageForPaneBundle:bundle]]; + [toolbarItem setTarget:self]; + [toolbarItem setAction:@selector( _selectPreferencePane: )]; + } else toolbarItem = nil; + } + return toolbarItem; +} + +- (NSArray *) toolbarDefaultItemIdentifiers:(NSToolbar *) toolbar { + NSMutableArray *fixed = [NSMutableArray arrayWithObjects:MVToolbarShowAllItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; + NSArray *defaults = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MVPreferencePaneDefaults" ofType:@"plist"]]; + [fixed addObjectsFromArray:defaults]; + return fixed; +} + +- (NSArray *) toolbarAllowedItemIdentifiers:(NSToolbar *) toolbar { + NSMutableArray *items = [NSMutableArray array]; + NSEnumerator *enumerator = [panes objectEnumerator]; + id item = nil; + while( ( item = [enumerator nextObject] ) ) + [items addObject:[item bundleIdentifier]]; + //[items addObject:MVToolbarShowAllItemIdentifier]; + [items addObject:NSToolbarSeparatorItemIdentifier]; + return items; +} +@end + +@implementation MVPreferencesController (MVPreferencesControllerPrivate) +- (IBAction) _selectPreferencePane:(id) sender { + [self selectPreferencePaneByIdentifier:[sender itemIdentifier]]; +} + +- (void) _doUnselect:(NSNotification *) notification { + if( closeWhenPaneIsReady ) [window close]; + [self selectPreferencePaneByIdentifier:pendingPane]; +} + +- (void) _resizeWindowForContentView:(NSView *) view { + NSRect windowFrame, newWindowFrame; + unsigned int newWindowHeight; + + windowFrame = [NSWindow contentRectForFrameRect:[window frame] styleMask:[window styleMask]]; + newWindowHeight = NSHeight( [view frame] ); + if( [[window toolbar] isVisible] ) + newWindowHeight += NSHeight( [[[window toolbar] _toolbarView] frame] ); + newWindowFrame = [NSWindow frameRectForContentRect:NSMakeRect( NSMinX( windowFrame ), NSMaxY( windowFrame ) - newWindowHeight, NSWidth( windowFrame ), newWindowHeight ) styleMask:[window styleMask]]; + + [window setFrame:newWindowFrame display:YES animate:[window isVisible]]; +} + +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle { + NSImage *image = nil; + NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + image = [[[cache objectForKey:@"MVPreferencePaneImage"] retain] autorelease]; + if( ! image ) { + NSDictionary *info = [bundle infoDictionary]; + image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"NSPrefPaneIconFile"]]] autorelease]; + if( ! image ) image = [[[NSImage alloc] initWithContentsOfFile:[bundle pathForImageResource:[info objectForKey:@"CFBundleIconFile"]]] autorelease]; + if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; + cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + if( image ) [cache setObject:image forKey:@"MVPreferencePaneImage"]; + } + return image; +} + +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle { + NSString *label = nil; + NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + label = [[[cache objectForKey:@"MVPreferencePanePaletteLabel"] retain] autorelease]; + if( ! label ) { + NSDictionary *info = [bundle infoDictionary]; + label = NSLocalizedStringFromTableInBundle( @"NSPrefPaneIconLabel", @"InfoPlist", bundle, nil ); + if( [label isEqualToString:@"NSPrefPaneIconLabel"] ) label = [info objectForKey:@"NSPrefPaneIconLabel"]; + if( ! label ) label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); + if( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; + if( ! label ) label = [bundle bundleIdentifier]; + if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; + cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + if( label ) [cache setObject:label forKey:@"MVPreferencePanePaletteLabel"]; + } + return label; +} + +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle { + NSString *label = nil; + NSMutableDictionary *cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + label = [[[cache objectForKey:@"MVPreferencePaneLabel"] retain] autorelease]; + if( ! label ) { + NSDictionary *info = [bundle infoDictionary]; + label = NSLocalizedStringFromTableInBundle( @"CFBundleName", @"InfoPlist", bundle, nil ); + if( [label isEqualToString:@"CFBundleName"] ) label = [info objectForKey:@"CFBundleName"]; + if( ! label ) label = [bundle bundleIdentifier]; + if( ! cache ) [paneInfo setObject:[NSMutableDictionary dictionary] forKey:[bundle bundleIdentifier]]; + cache = [paneInfo objectForKey:[bundle bundleIdentifier]]; + if( label ) [cache setObject:label forKey:@"MVPreferencePaneLabel"]; + } + return label; +} +@end + diff --git a/mozilla/chimera/PreferencePanes/MVPreferencesGroupedIconView.m b/mozilla/chimera/PreferencePanes/MVPreferencesGroupedIconView.m new file mode 100644 index 00000000000..f7ec7819515 --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferencesGroupedIconView.m @@ -0,0 +1,157 @@ +#import "MVPreferencesGroupedIconView.h" +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (unsigned int) _numberOfRows; +@end + +@interface MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups; +- (void) _sizeToFit; +- (NSRect) _rectForGroupAtIndex:(unsigned int) index; +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index; +- (void) _generateGroupViews; +- (void) _generateGroupViewAtIndex:(unsigned int) index; +@end + +@implementation MVPreferencesGroupedIconView +const unsigned int groupViewHeight = 95; +const unsigned int multiIconViewYOffset = 18; +const unsigned int sideGutterWidths = 15; +const unsigned int extraRowHeight = 69; + +- (id) initWithFrame:(NSRect) frame { + if( ( self = [super initWithFrame:frame] ) ) { + groupMultiIconViews = [[NSMutableArray array] retain]; + } + return self; +} + +- (void) drawRect:(NSRect) rect { + [self _generateGroupViews]; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setPreferencePaneGroups:(NSArray *) newPreferencePaneGroups { + [preferencePaneGroups autorelease]; + preferencePaneGroups = [newPreferencePaneGroups retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePaneGroups { + return preferencePaneGroups; +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + [[self window] makeFirstResponder:[self viewWithTag:0]]; + return YES; +} + +- (BOOL) resignFirstResponder { + return YES; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} +@end + +@implementation MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups { + return [[self preferencePaneGroups] count]; +} + +- (void) _sizeToFit { + if( ! [self _numberOfGroups] ) return; + [self _generateGroupViews]; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _rectForGroupAtIndex:[self _numberOfGroups] - 1] ) ) ]; +} + +- (NSRect) _rectForGroupAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( 0., (index * groupViewHeight ) + multiIconViewYOffset + index + extra, NSWidth( [self frame] ), groupViewHeight ); +} + +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + if( ! index ) return NSZeroRect; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( sideGutterWidths, ((index + 1) * groupViewHeight) - groupViewHeight + index + extra, NSWidth( [self frame] ) - (sideGutterWidths * 2), 1 ); +} + +- (void) _generateGroupViews { + unsigned int groupIndex, groupCount; + + groupCount = [self _numberOfGroups]; + for( groupIndex = 0; groupIndex < groupCount; groupIndex++ ) + [self _generateGroupViewAtIndex:groupIndex]; +} + +- (void) _generateGroupViewAtIndex:(unsigned int) index { + MVPreferencesMultipleIconView *multiIconView = nil; + NSString *identifier = [[preferencePaneGroups objectAtIndex:index] objectForKey:@"identifier"]; + NSString *name = NSLocalizedStringFromTable( identifier, @"MVPreferencePaneGroups", nil ); + NSDictionary *attributesDictionary; + unsigned nameHeight = 0; + + if( ! ( multiIconView = [self viewWithTag:index] ) ) { + NSMutableArray *panes = [NSMutableArray array]; + NSBox *sep = [[[NSBox alloc] initWithFrame:[self _rectForGroupSeparatorAtIndex:index]] autorelease]; + NSEnumerator *enumerator = [[[preferencePaneGroups objectAtIndex:index] objectForKey:@"panes"] objectEnumerator]; + id pane = nil, bundle = 0; + + multiIconView = [[[MVPreferencesMultipleIconView alloc] initWithFrame:[self _rectForGroupAtIndex:index]] autorelease]; + while( ( pane = [enumerator nextObject] ) ) { + bundle = [NSBundle bundleWithIdentifier:pane]; + if( bundle ) [panes addObject:bundle]; + } + + [multiIconView setPreferencesController:preferencesController]; + [multiIconView setPreferencePanes:panes]; + [multiIconView setTag:index]; + + [sep setBoxType:NSBoxSeparator]; + [sep setBorderType:NSBezelBorder]; + + [self addSubview:multiIconView]; + [self addSubview:sep]; +// if( ! index ) [[self window] makeFirstResponder:multiIconView]; + if( index - 1 >= 0 ) [[self viewWithTag:index - 1] setNextKeyView:multiIconView]; + if( index == [self _numberOfGroups] - 1 ) [multiIconView setNextKeyView:[self viewWithTag:0]]; + } + + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:13.], NSFontAttributeName, nil]; + nameHeight = [[NSFont boldSystemFontOfSize:13.] ascender]; + [name drawAtPoint:NSMakePoint( sideGutterWidths - 1, NSMinY( [multiIconView frame] ) - nameHeight - 1 ) withAttributes:attributesDictionary]; +} +@end diff --git a/mozilla/chimera/PreferencePanes/MVPreferencesMultipleIconView.m b/mozilla/chimera/PreferencePanes/MVPreferencesMultipleIconView.m new file mode 100644 index 00000000000..571f1f80192 --- /dev/null +++ b/mozilla/chimera/PreferencePanes/MVPreferencesMultipleIconView.m @@ -0,0 +1,393 @@ +#import +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" +#import "CHImageAdditions.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst; +- (void) _focusLast; +- (unsigned int) _iconsWide; +- (unsigned int) _numberOfIcons; +- (unsigned int) _numberOfRows; +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index; +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index; +- (NSRect) _boundsForIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index; +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect; +- (void) _sizeToFit; +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event; +@end + +@interface MVPreferencesController (MVPreferencesControllerPrivate) +- (IBAction) _selectPreferencePane:(id) sender; +- (void) _resizeWindowForContentView:(NSView *) view; +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; +@end + +@implementation MVPreferencesMultipleIconView +const NSSize buttonSize = { 81., 75. }; +const NSSize iconSize = { 32., 32. }; +const unsigned int titleBaseline = 15; +const unsigned int iconBaseline = 30; +const unsigned int bottomBorder = 15; + +- (id) initWithFrame:(NSRect) rect { + if( ( self = [super initWithFrame:rect] ) ) { + pressedIconIndex = NSNotFound; + focusedIndex = NSNotFound; + selectedPane = nil; + } + return self; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setSelectedPane:(NSBundle *) newSelectedPane { + selectedPane = newSelectedPane; + [self setNeedsDisplay:YES]; +} + +- (void) mouseDown:(NSEvent *) event { + NSPoint eventLocation; + NSRect slopRect; + const float dragSlop = 4.; + unsigned int index; + NSRect buttonRect; + BOOL mouseInBounds = NO; + + eventLocation = [self convertPoint:[event locationInWindow] fromView:nil]; + slopRect = NSInsetRect( NSMakeRect( eventLocation.x, eventLocation.y, 1., 1. ), -dragSlop, -dragSlop ); + + index = floor( eventLocation.x / buttonSize.width ) + ( floor( eventLocation.y / buttonSize.height ) * [self _iconsWide] ); + buttonRect = [self _boundsForIndex:index]; + if( index >= ( [self _iconsWide] * ( floor( eventLocation.y / buttonSize.height ) + 1 ) ) ) return; + if( ! NSWidth( buttonRect ) ) return; + + pressedIconIndex = index; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + while( 1 ) { + NSEvent *nextEvent; + NSPoint nextEventLocation; + unsigned int newPressedIconIndex; + + nextEvent = [NSApp nextEventMatchingMask:NSLeftMouseDraggedMask|NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]; + + nextEventLocation = [self convertPoint:[nextEvent locationInWindow] fromView:nil]; + mouseInBounds = NSMouseInRect(nextEventLocation, buttonRect, [self isFlipped]); + newPressedIconIndex = ( mouseInBounds ? index : NSNotFound ); + if( newPressedIconIndex != pressedIconIndex ) { + pressedIconIndex = newPressedIconIndex; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + } + + if( [nextEvent type] == NSLeftMouseUp ) break; + else if( ! NSMouseInRect( nextEventLocation, slopRect, NO ) ) { + if( [self _dragIconIndex:index event:event] ) { + mouseInBounds = NO; + break; + } + } + } + + pressedIconIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + if( mouseInBounds ) + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:index] bundleIdentifier]]; +} + +#define kTabCharCode 9 +#define kShiftTabCharCode 25 +#define kSpaceCharCode 32 + +- (void) keyDown:(NSEvent *) theEvent { + NSView *nextView = nil; + if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = 0; + else if( ! ( [theEvent modifierFlags] & NSShiftKeyMask ) ) focusedIndex++; + if( focusedIndex >= [self _numberOfIcons] ) { + if( ( nextView = [self nextValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusFirst]; + } else focusedIndex = 0; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kShiftTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = [self _numberOfIcons] - 1; + else if( [theEvent modifierFlags] & NSShiftKeyMask ) focusedIndex--; + if( (signed) focusedIndex < 0 && [self _numberOfIcons] ) { + if( ( nextView = [self previousValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusLast]; + } else focusedIndex = [self _numberOfIcons] - 1; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kSpaceCharCode ) { + if( focusedIndex != NSNotFound && focusedIndex < [self _numberOfIcons] && focusedIndex >= 0 ) { + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:focusedIndex] bundleIdentifier]]; + focusedIndex = NSNotFound; + } + } +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + focusedIndex = NSNotFound; + return YES; +} + +- (BOOL) resignFirstResponder { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + focusedIndex = NSNotFound; + return YES; +} + +- (void) drawRect:(NSRect) rect { + unsigned int paneIndex, paneCount; + + paneCount = [self _numberOfIcons]; + for( paneIndex = 0; paneIndex < paneCount; paneIndex++ ) + [self _drawIconAtIndex:paneIndex drawRect:rect]; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} + +- (int) tag { + return tag; +} + +- (void) setTag:(int) newTag { + tag = newTag; +} + +- (NSDragOperation) draggingSourceOperationMaskForLocal:(BOOL) flag { + return NSDragOperationMove; +} + +- (void) draggedImage:(NSImage *)image endedAt:(NSPoint) screenPoint operation:(NSDragOperation) operation { +} + +- (BOOL) ignoreModifierKeysWhileDragging { + return YES; +} +@end + +@implementation MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst { + focusedIndex = 0; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (void) _focusLast { + focusedIndex = [self _numberOfIcons] - 1; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (unsigned int) _iconsWide { + return NSWidth( [self bounds] ) / buttonSize.width; +} + +- (unsigned int) _numberOfIcons { + return [[self preferencePanes] count]; +} + +- (unsigned int) _numberOfRows { + unsigned int row = 0, column = 0; + if( ! [self _column:&column andRow:&row forIndex:[self _numberOfIcons] - 1] ) return 0; + return row; +} + +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index { + return [[self preferencePanes] objectAtIndex:index] == selectedPane; +} + +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index { + if( index >= [self _numberOfIcons] ) return NO; + + *row = index / [self _iconsWide]; + *column = index % [self _iconsWide]; + + return YES; +} + +- (NSRect) _boundsForIndex:(unsigned int) index { + unsigned int row = 0, column = 0, leftEdge = 0; + + if( ! [self _column:&column andRow:&row forIndex:index] ) return NSZeroRect; + + leftEdge = ( NSWidth( _bounds ) - ( [self _iconsWide] * buttonSize.width ) ) / 2. ; + + return NSMakeRect( ( column * buttonSize.width ) + leftEdge, row * buttonSize.height - (row * 6), buttonSize.width, buttonSize.height ); +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index { + NSString *unused; + return [self _iconImage:image andName:name andIdentifier:&unused forIndex:index]; +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index { + NSDictionary *info = nil; + NSBundle *pane = nil; + + if( index >= [self _numberOfIcons] ) return NO; + + pane = [[self preferencePanes] objectAtIndex:index]; + info = [pane infoDictionary]; + *image = [preferencesController _imageForPaneBundle:pane]; + *name = [preferencesController _paletteLabelForPaneBundle:pane]; + *identifier = [pane bundleIdentifier]; + + return YES; +} + +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect { + NSImage *image; + NSString *name; + unsigned int row, column; + NSPoint drawPoint; + float nameHeight; + NSRect buttonRect, destinationRect; + NSDictionary *attributesDictionary; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; + + buttonRect = [self _boundsForIndex:index]; + if( ! NSIntersectsRect( buttonRect, drawRect ) ) return; + if( ! [self _iconImage:&image andName:&name forIndex:index] ) return; + if( ! [self _column:&column andRow:&row forIndex:index] ) return; + + // Draw dark gray rectangle around currently selected icon (for MultipleIconView) + if( [self _isIconSelectedAtIndex:index] ) { + [[NSColor colorWithCalibratedWhite:0.8 alpha:0.75] set]; + NSRectFillUsingOperation(buttonRect, NSCompositeSourceOver); + } + + if( focusedIndex == index ) { + CGContextSaveGState( context ); + NSSetFocusRingStyle( NSFocusRingAbove ); + } + + // Draw icon, dark if it is currently being pressed + destinationRect = NSIntegralRect( NSMakeRect( NSMidX( buttonRect) - iconSize.width / 2., NSMaxY( buttonRect ) - iconBaseline - iconSize.height, iconSize.width, iconSize.height ) ); + destinationRect.size = iconSize; + if( index != pressedIconIndex && image ) [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + else if( image ) { + NSImage *darkImage; + NSSize darkImageSize; + + darkImage = [image copy]; + darkImageSize = [darkImage size]; + [darkImage lockFocus]; { + [[NSColor blackColor] set]; + NSRectFillUsingOperation( NSMakeRect( 0., 0., darkImageSize.width, darkImageSize.height ), NSCompositeSourceIn ); + [darkImage unlockFocus]; + } + + [darkImage drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:.6666667]; + [darkImage release]; + } + if( focusedIndex == index ) CGContextRestoreGState( context ); + + // Draw text + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + drawPoint = NSMakePoint( rint( buttonSize.width + 2 * NSMinX( buttonRect ) - NSWidth( _bounds ) - 1 ), rint( NSMaxY( buttonRect ) - titleBaseline - nameHeight ) ); + [name drawAtPoint:drawPoint withAttributes:attributesDictionary]; +} + +- (void) _sizeToFit { + if( ! [self preferencePanes] ) return; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _boundsForIndex:[self _numberOfIcons] - 1] ) + bottomBorder ) ]; +} + +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event { + NSImage *iconImage; + NSString *name; + NSString *identifier; + + if( ! [self _iconImage:&iconImage andName:&name andIdentifier:&identifier forIndex:index] ) + return YES; + + return [self _dragIconImage:iconImage andName:name andIdentifier:identifier event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event { + return [self _dragIconImage:iconImage andName:name andIdentifier:name event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event { + NSImage *dragImage; + NSPasteboard *pasteboard; + NSPoint dragPoint, startPoint; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + + dragImage = [[NSImage alloc] initWithSize:buttonSize]; + [dragImage lockFocus]; { + float nameHeight; + NSSize nameSize; + NSDictionary *attributesDictionary; + + [iconImage drawInRect:NSMakeRect( buttonSize.width / 2. - iconSize.width / 2., iconBaseline, iconSize.width, iconSize.height ) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:.5]; + + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, [[NSColor blackColor] colorWithAlphaComponent:.5], NSForegroundColorAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameSize = [name sizeWithAttributes:attributesDictionary]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + [name drawAtPoint:NSMakePoint( 0., nameHeight + titleBaseline - nameSize.height ) withAttributes:attributesDictionary]; + [dragImage unlockFocus]; + } + + pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:@"NSToolbarIndividualItemDragType"] owner:nil]; + [pasteboard setString:identifier forType:@"NSToolbarItemIdentiferPboardType"]; + + dragPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + startPoint = [self _boundsForIndex:[preferencePanes indexOfObject:[NSBundle bundleWithIdentifier:identifier]]].origin; + startPoint.y += buttonSize.height; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + pressedIconIndex = NSNotFound; + [self dragImage:dragImage at:startPoint offset:NSZeroSize event:event pasteboard:pasteboard source:self slideBack:YES]; + + return YES; +} +@end \ No newline at end of file diff --git a/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib b/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib new file mode 100644 index 00000000000..dc75f9a235a --- /dev/null +++ b/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib @@ -0,0 +1,55 @@ +{ + IBClasses = ( + { + ACTIONS = { + displayFontPanel = id; + restoreDefaultColors = id; + revertColors = id; + setAlsoUseForIncoming = id; + setColors = id; + setDontShowDisconnected = id; + setDontShowZero = id; + setOverrideColors = id; + setShowOnlineBuddiesInDock = id; + setShowServiceStatusInDock = id; + setShowUserStatusInDock = id; + setSmileyType = id; + setUseAquaServiceIcons = id; + setUseGraphicalSmilies = id; + }; + CLASS = AppearancePane; + LANGUAGE = ObjC; + OUTLETS = { + actionWell = id; + alsoUseForIncomingCheck = id; + backgroundWell = id; + dontShowDisconnectedCheck = id; + dontShowZeroCheck = id; + fontSampleText = id; + foregroundWell = id; + myFont = id; + overrideColorsCheck = id; + showOnlineBuddiesInDockCheck = id; + showServiceStatusInDockCheck = id; + showUserStatusInDockCheck = id; + smileyTypeChoice = id; + systemNameWell = id; + theirNameWell = id; + translationNameWell = id; + useAquaServiceIconsCheck = id; + useGraphicalSmiliesCheck = id; + yourNameWell = id; + }; + SUPERCLASS = NSPreferencePane; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = NSPreferencePane; + LANGUAGE = ObjC; + OUTLETS = {_firstKeyView = id; _initialKeyView = id; _lastKeyView = id; _window = id; }; + SUPERCLASS = NSObject; + }, + {CLASS = PersonalPane; LANGUAGE = ObjC; SUPERCLASS = NSPreferencePane; } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib b/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib new file mode 100644 index 00000000000..a0052e409ef --- /dev/null +++ b/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib @@ -0,0 +1,26 @@ + + + + + IBDocumentLocation + 372 4 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBGroupedObjects + + 3 + + 153 + 155 + + + IBLastGroupID + 4 + IBOpenObjects + + 5 + + IBSystem Version + 5Q125 + + diff --git a/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib b/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib new file mode 100644 index 00000000000..26d0953e8a2 Binary files /dev/null and b/mozilla/chimera/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib differ diff --git a/mozilla/chimera/PreferencePanes/Personal/Personal.nib/classes.nib b/mozilla/chimera/PreferencePanes/Personal/Personal.nib/classes.nib new file mode 100644 index 00000000000..dc75f9a235a --- /dev/null +++ b/mozilla/chimera/PreferencePanes/Personal/Personal.nib/classes.nib @@ -0,0 +1,55 @@ +{ + IBClasses = ( + { + ACTIONS = { + displayFontPanel = id; + restoreDefaultColors = id; + revertColors = id; + setAlsoUseForIncoming = id; + setColors = id; + setDontShowDisconnected = id; + setDontShowZero = id; + setOverrideColors = id; + setShowOnlineBuddiesInDock = id; + setShowServiceStatusInDock = id; + setShowUserStatusInDock = id; + setSmileyType = id; + setUseAquaServiceIcons = id; + setUseGraphicalSmilies = id; + }; + CLASS = AppearancePane; + LANGUAGE = ObjC; + OUTLETS = { + actionWell = id; + alsoUseForIncomingCheck = id; + backgroundWell = id; + dontShowDisconnectedCheck = id; + dontShowZeroCheck = id; + fontSampleText = id; + foregroundWell = id; + myFont = id; + overrideColorsCheck = id; + showOnlineBuddiesInDockCheck = id; + showServiceStatusInDockCheck = id; + showUserStatusInDockCheck = id; + smileyTypeChoice = id; + systemNameWell = id; + theirNameWell = id; + translationNameWell = id; + useAquaServiceIconsCheck = id; + useGraphicalSmiliesCheck = id; + yourNameWell = id; + }; + SUPERCLASS = NSPreferencePane; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + CLASS = NSPreferencePane; + LANGUAGE = ObjC; + OUTLETS = {_firstKeyView = id; _initialKeyView = id; _lastKeyView = id; _window = id; }; + SUPERCLASS = NSObject; + }, + {CLASS = PersonalPane; LANGUAGE = ObjC; SUPERCLASS = NSPreferencePane; } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/chimera/PreferencePanes/Personal/Personal.nib/info.nib b/mozilla/chimera/PreferencePanes/Personal/Personal.nib/info.nib new file mode 100644 index 00000000000..a0052e409ef --- /dev/null +++ b/mozilla/chimera/PreferencePanes/Personal/Personal.nib/info.nib @@ -0,0 +1,26 @@ + + + + + IBDocumentLocation + 372 4 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBGroupedObjects + + 3 + + 153 + 155 + + + IBLastGroupID + 4 + IBOpenObjects + + 5 + + IBSystem Version + 5Q125 + + diff --git a/mozilla/chimera/PreferencePanes/Personal/Personal.nib/objects.nib b/mozilla/chimera/PreferencePanes/Personal/Personal.nib/objects.nib new file mode 100644 index 00000000000..26d0953e8a2 Binary files /dev/null and b/mozilla/chimera/PreferencePanes/Personal/Personal.nib/objects.nib differ diff --git a/mozilla/chimera/resources/localized/English.lproj/MVPreferencePaneGroups.strings b/mozilla/chimera/resources/localized/English.lproj/MVPreferencePaneGroups.strings new file mode 100644 index 00000000000..b410cd0bc55 Binary files /dev/null and b/mozilla/chimera/resources/localized/English.lproj/MVPreferencePaneGroups.strings differ diff --git a/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/classes.nib b/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/classes.nib new file mode 100644 index 00000000000..aeac16577ff --- /dev/null +++ b/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/classes.nib @@ -0,0 +1,32 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = {showAll = id; showPreferences = id; }; + CLASS = MVPreferencesController; + LANGUAGE = ObjC; + OUTLETS = { + groupView = id; + loadingImageView = id; + loadingTextFeld = id; + loadingView = id; + multiView = id; + window = id; + }; + SUPERCLASS = NSObject; + }, + { + CLASS = MVPreferencesGroupedIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + }, + { + CLASS = MVPreferencesMultipleIconView; + LANGUAGE = ObjC; + OUTLETS = {preferencesController = id; }; + SUPERCLASS = NSView; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/info.nib b/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/info.nib new file mode 100644 index 00000000000..d6140876225 --- /dev/null +++ b/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/info.nib @@ -0,0 +1,12 @@ + + + + + IBDocumentLocation + 19 36 356 240 0 0 1152 746 + IBFramework Version + 248.0 + IBSystem Version + 5Q45 + + diff --git a/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/objects.nib b/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/objects.nib new file mode 100644 index 00000000000..92598fe1cf1 Binary files /dev/null and b/mozilla/chimera/resources/localized/English.lproj/MVPreferences.nib/objects.nib differ diff --git a/mozilla/chimera/src/preferences/MVPreferencePaneDefaults.plist b/mozilla/chimera/src/preferences/MVPreferencePaneDefaults.plist new file mode 100644 index 00000000000..e1574407fcb --- /dev/null +++ b/mozilla/chimera/src/preferences/MVPreferencePaneDefaults.plist @@ -0,0 +1,7 @@ +( Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane +) diff --git a/mozilla/chimera/src/preferences/MVPreferencePaneGroups.plist b/mozilla/chimera/src/preferences/MVPreferencePaneGroups.plist new file mode 100644 index 00000000000..ad5199ee34b --- /dev/null +++ b/mozilla/chimera/src/preferences/MVPreferencePaneGroups.plist @@ -0,0 +1,14 @@ +( + { + identifier = chimera; + panes = ( + Chimera.SitesPrefPane, + Chimera.BrowsingPrefPane, + Chimera.PersonalPrefPane, + Chimera.HelpersPrefPane, + Chimera.PrivacyPrefPane, + Chimera.SecurityPrefPane, + Chimera.AdvancedPrefPane + ); + } +) \ No newline at end of file diff --git a/mozilla/chimera/src/preferences/MVPreferencesGroupedIconView.m b/mozilla/chimera/src/preferences/MVPreferencesGroupedIconView.m new file mode 100644 index 00000000000..f7ec7819515 --- /dev/null +++ b/mozilla/chimera/src/preferences/MVPreferencesGroupedIconView.m @@ -0,0 +1,157 @@ +#import "MVPreferencesGroupedIconView.h" +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (unsigned int) _numberOfRows; +@end + +@interface MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups; +- (void) _sizeToFit; +- (NSRect) _rectForGroupAtIndex:(unsigned int) index; +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index; +- (void) _generateGroupViews; +- (void) _generateGroupViewAtIndex:(unsigned int) index; +@end + +@implementation MVPreferencesGroupedIconView +const unsigned int groupViewHeight = 95; +const unsigned int multiIconViewYOffset = 18; +const unsigned int sideGutterWidths = 15; +const unsigned int extraRowHeight = 69; + +- (id) initWithFrame:(NSRect) frame { + if( ( self = [super initWithFrame:frame] ) ) { + groupMultiIconViews = [[NSMutableArray array] retain]; + } + return self; +} + +- (void) drawRect:(NSRect) rect { + [self _generateGroupViews]; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setPreferencePaneGroups:(NSArray *) newPreferencePaneGroups { + [preferencePaneGroups autorelease]; + preferencePaneGroups = [newPreferencePaneGroups retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePaneGroups { + return preferencePaneGroups; +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + [[self window] makeFirstResponder:[self viewWithTag:0]]; + return YES; +} + +- (BOOL) resignFirstResponder { + return YES; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} +@end + +@implementation MVPreferencesGroupedIconView (MVPreferencesGroupedIconViewPrivate) +- (unsigned int) _numberOfGroups { + return [[self preferencePaneGroups] count]; +} + +- (void) _sizeToFit { + if( ! [self _numberOfGroups] ) return; + [self _generateGroupViews]; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _rectForGroupAtIndex:[self _numberOfGroups] - 1] ) ) ]; +} + +- (NSRect) _rectForGroupAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( 0., (index * groupViewHeight ) + multiIconViewYOffset + index + extra, NSWidth( [self frame] ), groupViewHeight ); +} + +- (NSRect) _rectForGroupSeparatorAtIndex:(unsigned int) index { + unsigned int extra = 0, groupIndex; + if( ! index ) return NSZeroRect; + for( groupIndex = 0; groupIndex < index; groupIndex++ ) + extra += [[self viewWithTag:groupIndex] _numberOfRows] * extraRowHeight; + return NSMakeRect( sideGutterWidths, ((index + 1) * groupViewHeight) - groupViewHeight + index + extra, NSWidth( [self frame] ) - (sideGutterWidths * 2), 1 ); +} + +- (void) _generateGroupViews { + unsigned int groupIndex, groupCount; + + groupCount = [self _numberOfGroups]; + for( groupIndex = 0; groupIndex < groupCount; groupIndex++ ) + [self _generateGroupViewAtIndex:groupIndex]; +} + +- (void) _generateGroupViewAtIndex:(unsigned int) index { + MVPreferencesMultipleIconView *multiIconView = nil; + NSString *identifier = [[preferencePaneGroups objectAtIndex:index] objectForKey:@"identifier"]; + NSString *name = NSLocalizedStringFromTable( identifier, @"MVPreferencePaneGroups", nil ); + NSDictionary *attributesDictionary; + unsigned nameHeight = 0; + + if( ! ( multiIconView = [self viewWithTag:index] ) ) { + NSMutableArray *panes = [NSMutableArray array]; + NSBox *sep = [[[NSBox alloc] initWithFrame:[self _rectForGroupSeparatorAtIndex:index]] autorelease]; + NSEnumerator *enumerator = [[[preferencePaneGroups objectAtIndex:index] objectForKey:@"panes"] objectEnumerator]; + id pane = nil, bundle = 0; + + multiIconView = [[[MVPreferencesMultipleIconView alloc] initWithFrame:[self _rectForGroupAtIndex:index]] autorelease]; + while( ( pane = [enumerator nextObject] ) ) { + bundle = [NSBundle bundleWithIdentifier:pane]; + if( bundle ) [panes addObject:bundle]; + } + + [multiIconView setPreferencesController:preferencesController]; + [multiIconView setPreferencePanes:panes]; + [multiIconView setTag:index]; + + [sep setBoxType:NSBoxSeparator]; + [sep setBorderType:NSBezelBorder]; + + [self addSubview:multiIconView]; + [self addSubview:sep]; +// if( ! index ) [[self window] makeFirstResponder:multiIconView]; + if( index - 1 >= 0 ) [[self viewWithTag:index - 1] setNextKeyView:multiIconView]; + if( index == [self _numberOfGroups] - 1 ) [multiIconView setNextKeyView:[self viewWithTag:0]]; + } + + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont boldSystemFontOfSize:13.], NSFontAttributeName, nil]; + nameHeight = [[NSFont boldSystemFontOfSize:13.] ascender]; + [name drawAtPoint:NSMakePoint( sideGutterWidths - 1, NSMinY( [multiIconView frame] ) - nameHeight - 1 ) withAttributes:attributesDictionary]; +} +@end diff --git a/mozilla/chimera/src/preferences/MVPreferencesMultipleIconView.m b/mozilla/chimera/src/preferences/MVPreferencesMultipleIconView.m new file mode 100644 index 00000000000..571f1f80192 --- /dev/null +++ b/mozilla/chimera/src/preferences/MVPreferencesMultipleIconView.m @@ -0,0 +1,393 @@ +#import +#import "MVPreferencesMultipleIconView.h" +#import "MVPreferencesController.h" +#import "CHImageAdditions.h" + +@interface MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst; +- (void) _focusLast; +- (unsigned int) _iconsWide; +- (unsigned int) _numberOfIcons; +- (unsigned int) _numberOfRows; +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index; +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index; +- (NSRect) _boundsForIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index; +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index; +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect; +- (void) _sizeToFit; +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event; +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event; +@end + +@interface MVPreferencesController (MVPreferencesControllerPrivate) +- (IBAction) _selectPreferencePane:(id) sender; +- (void) _resizeWindowForContentView:(NSView *) view; +- (NSImage *) _imageForPaneBundle:(NSBundle *) bundle; +- (NSString *) _paletteLabelForPaneBundle:(NSBundle *) bundle; +- (NSString *) _labelForPaneBundle:(NSBundle *) bundle; +@end + +@implementation MVPreferencesMultipleIconView +const NSSize buttonSize = { 81., 75. }; +const NSSize iconSize = { 32., 32. }; +const unsigned int titleBaseline = 15; +const unsigned int iconBaseline = 30; +const unsigned int bottomBorder = 15; + +- (id) initWithFrame:(NSRect) rect { + if( ( self = [super initWithFrame:rect] ) ) { + pressedIconIndex = NSNotFound; + focusedIndex = NSNotFound; + selectedPane = nil; + } + return self; +} + +- (void) setPreferencesController:(MVPreferencesController *) newPreferencesController { + [preferencesController autorelease]; + preferencesController = [newPreferencesController retain]; + [self setNeedsDisplay:YES]; +} + +- (void) setPreferencePanes:(NSArray *) newPreferencePanes { + [preferencePanes autorelease]; + preferencePanes = [newPreferencePanes retain]; + [self _sizeToFit]; + [self setNeedsDisplay:YES]; +} + +- (NSArray *) preferencePanes { + return preferencePanes; +} + +- (void) setSelectedPane:(NSBundle *) newSelectedPane { + selectedPane = newSelectedPane; + [self setNeedsDisplay:YES]; +} + +- (void) mouseDown:(NSEvent *) event { + NSPoint eventLocation; + NSRect slopRect; + const float dragSlop = 4.; + unsigned int index; + NSRect buttonRect; + BOOL mouseInBounds = NO; + + eventLocation = [self convertPoint:[event locationInWindow] fromView:nil]; + slopRect = NSInsetRect( NSMakeRect( eventLocation.x, eventLocation.y, 1., 1. ), -dragSlop, -dragSlop ); + + index = floor( eventLocation.x / buttonSize.width ) + ( floor( eventLocation.y / buttonSize.height ) * [self _iconsWide] ); + buttonRect = [self _boundsForIndex:index]; + if( index >= ( [self _iconsWide] * ( floor( eventLocation.y / buttonSize.height ) + 1 ) ) ) return; + if( ! NSWidth( buttonRect ) ) return; + + pressedIconIndex = index; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + while( 1 ) { + NSEvent *nextEvent; + NSPoint nextEventLocation; + unsigned int newPressedIconIndex; + + nextEvent = [NSApp nextEventMatchingMask:NSLeftMouseDraggedMask|NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]; + + nextEventLocation = [self convertPoint:[nextEvent locationInWindow] fromView:nil]; + mouseInBounds = NSMouseInRect(nextEventLocation, buttonRect, [self isFlipped]); + newPressedIconIndex = ( mouseInBounds ? index : NSNotFound ); + if( newPressedIconIndex != pressedIconIndex ) { + pressedIconIndex = newPressedIconIndex; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + } + + if( [nextEvent type] == NSLeftMouseUp ) break; + else if( ! NSMouseInRect( nextEventLocation, slopRect, NO ) ) { + if( [self _dragIconIndex:index event:event] ) { + mouseInBounds = NO; + break; + } + } + } + + pressedIconIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:index]]; + + if( mouseInBounds ) + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:index] bundleIdentifier]]; +} + +#define kTabCharCode 9 +#define kShiftTabCharCode 25 +#define kSpaceCharCode 32 + +- (void) keyDown:(NSEvent *) theEvent { + NSView *nextView = nil; + if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = 0; + else if( ! ( [theEvent modifierFlags] & NSShiftKeyMask ) ) focusedIndex++; + if( focusedIndex >= [self _numberOfIcons] ) { + if( ( nextView = [self nextValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusFirst]; + } else focusedIndex = 0; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kShiftTabCharCode ) { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + if( focusedIndex == NSNotFound && [self _numberOfIcons] ) focusedIndex = [self _numberOfIcons] - 1; + else if( [theEvent modifierFlags] & NSShiftKeyMask ) focusedIndex--; + if( (signed) focusedIndex < 0 && [self _numberOfIcons] ) { + if( ( nextView = [self previousValidKeyView] ) ) { + [[self window] makeFirstResponder:nextView]; + focusedIndex = NSNotFound; + if( [nextView isKindOfClass:[MVPreferencesMultipleIconView class]] ) + [(MVPreferencesMultipleIconView *)nextView _focusLast]; + } else focusedIndex = [self _numberOfIcons] - 1; + } + if( ! [self _numberOfIcons] ) focusedIndex = NSNotFound; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + } else if( [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == kSpaceCharCode ) { + if( focusedIndex != NSNotFound && focusedIndex < [self _numberOfIcons] && focusedIndex >= 0 ) { + [preferencesController selectPreferencePaneByIdentifier:[[preferencePanes objectAtIndex:focusedIndex] bundleIdentifier]]; + focusedIndex = NSNotFound; + } + } +} + +- (BOOL) acceptsFirstResponder { + return YES; +} + +- (BOOL) becomeFirstResponder { + focusedIndex = NSNotFound; + return YES; +} + +- (BOOL) resignFirstResponder { + [self setKeyboardFocusRingNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; + focusedIndex = NSNotFound; + return YES; +} + +- (void) drawRect:(NSRect) rect { + unsigned int paneIndex, paneCount; + + paneCount = [self _numberOfIcons]; + for( paneIndex = 0; paneIndex < paneCount; paneIndex++ ) + [self _drawIconAtIndex:paneIndex drawRect:rect]; +} + +- (BOOL) isFlipped { + return YES; +} + +- (BOOL) isOpaque { + return NO; +} + +- (int) tag { + return tag; +} + +- (void) setTag:(int) newTag { + tag = newTag; +} + +- (NSDragOperation) draggingSourceOperationMaskForLocal:(BOOL) flag { + return NSDragOperationMove; +} + +- (void) draggedImage:(NSImage *)image endedAt:(NSPoint) screenPoint operation:(NSDragOperation) operation { +} + +- (BOOL) ignoreModifierKeysWhileDragging { + return YES; +} +@end + +@implementation MVPreferencesMultipleIconView (MVPreferencesMultipleIconViewPrivate) +- (void) _focusFirst { + focusedIndex = 0; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (void) _focusLast { + focusedIndex = [self _numberOfIcons] - 1; + [self setNeedsDisplayInRect:[self _boundsForIndex:focusedIndex]]; +} + +- (unsigned int) _iconsWide { + return NSWidth( [self bounds] ) / buttonSize.width; +} + +- (unsigned int) _numberOfIcons { + return [[self preferencePanes] count]; +} + +- (unsigned int) _numberOfRows { + unsigned int row = 0, column = 0; + if( ! [self _column:&column andRow:&row forIndex:[self _numberOfIcons] - 1] ) return 0; + return row; +} + +- (BOOL) _isIconSelectedAtIndex:(unsigned int) index { + return [[self preferencePanes] objectAtIndex:index] == selectedPane; +} + +- (BOOL) _column:(unsigned int *) column andRow:(unsigned int *) row forIndex:(unsigned int) index { + if( index >= [self _numberOfIcons] ) return NO; + + *row = index / [self _iconsWide]; + *column = index % [self _iconsWide]; + + return YES; +} + +- (NSRect) _boundsForIndex:(unsigned int) index { + unsigned int row = 0, column = 0, leftEdge = 0; + + if( ! [self _column:&column andRow:&row forIndex:index] ) return NSZeroRect; + + leftEdge = ( NSWidth( _bounds ) - ( [self _iconsWide] * buttonSize.width ) ) / 2. ; + + return NSMakeRect( ( column * buttonSize.width ) + leftEdge, row * buttonSize.height - (row * 6), buttonSize.width, buttonSize.height ); +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name forIndex:(unsigned int) index { + NSString *unused; + return [self _iconImage:image andName:name andIdentifier:&unused forIndex:index]; +} + +- (BOOL) _iconImage:(NSImage **) image andName:(NSString **) name andIdentifier:(NSString **) identifier forIndex:(unsigned int) index { + NSDictionary *info = nil; + NSBundle *pane = nil; + + if( index >= [self _numberOfIcons] ) return NO; + + pane = [[self preferencePanes] objectAtIndex:index]; + info = [pane infoDictionary]; + *image = [preferencesController _imageForPaneBundle:pane]; + *name = [preferencesController _paletteLabelForPaneBundle:pane]; + *identifier = [pane bundleIdentifier]; + + return YES; +} + +- (void) _drawIconAtIndex:(unsigned int) index drawRect:(NSRect) drawRect { + NSImage *image; + NSString *name; + unsigned int row, column; + NSPoint drawPoint; + float nameHeight; + NSRect buttonRect, destinationRect; + NSDictionary *attributesDictionary; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; + + buttonRect = [self _boundsForIndex:index]; + if( ! NSIntersectsRect( buttonRect, drawRect ) ) return; + if( ! [self _iconImage:&image andName:&name forIndex:index] ) return; + if( ! [self _column:&column andRow:&row forIndex:index] ) return; + + // Draw dark gray rectangle around currently selected icon (for MultipleIconView) + if( [self _isIconSelectedAtIndex:index] ) { + [[NSColor colorWithCalibratedWhite:0.8 alpha:0.75] set]; + NSRectFillUsingOperation(buttonRect, NSCompositeSourceOver); + } + + if( focusedIndex == index ) { + CGContextSaveGState( context ); + NSSetFocusRingStyle( NSFocusRingAbove ); + } + + // Draw icon, dark if it is currently being pressed + destinationRect = NSIntegralRect( NSMakeRect( NSMidX( buttonRect) - iconSize.width / 2., NSMaxY( buttonRect ) - iconBaseline - iconSize.height, iconSize.width, iconSize.height ) ); + destinationRect.size = iconSize; + if( index != pressedIconIndex && image ) [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + else if( image ) { + NSImage *darkImage; + NSSize darkImageSize; + + darkImage = [image copy]; + darkImageSize = [darkImage size]; + [darkImage lockFocus]; { + [[NSColor blackColor] set]; + NSRectFillUsingOperation( NSMakeRect( 0., 0., darkImageSize.width, darkImageSize.height ), NSCompositeSourceIn ); + [darkImage unlockFocus]; + } + + [darkImage drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:1.]; + [image drawFlippedInRect:destinationRect operation:NSCompositeSourceOver fraction:.6666667]; + [darkImage release]; + } + if( focusedIndex == index ) CGContextRestoreGState( context ); + + // Draw text + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + drawPoint = NSMakePoint( rint( buttonSize.width + 2 * NSMinX( buttonRect ) - NSWidth( _bounds ) - 1 ), rint( NSMaxY( buttonRect ) - titleBaseline - nameHeight ) ); + [name drawAtPoint:drawPoint withAttributes:attributesDictionary]; +} + +- (void) _sizeToFit { + if( ! [self preferencePanes] ) return; + [self setFrameSize:NSMakeSize( NSWidth( _bounds ), NSMaxY( [self _boundsForIndex:[self _numberOfIcons] - 1] ) + bottomBorder ) ]; +} + +- (BOOL) _dragIconIndex:(unsigned int) index event:(NSEvent *) event { + NSImage *iconImage; + NSString *name; + NSString *identifier; + + if( ! [self _iconImage:&iconImage andName:&name andIdentifier:&identifier forIndex:index] ) + return YES; + + return [self _dragIconImage:iconImage andName:name andIdentifier:identifier event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name event:(NSEvent *) event { + return [self _dragIconImage:iconImage andName:name andIdentifier:name event:event]; +} + +- (BOOL) _dragIconImage:(NSImage *) iconImage andName:(NSString *) name andIdentifier:(NSString *) identifier event:(NSEvent *) event { + NSImage *dragImage; + NSPasteboard *pasteboard; + NSPoint dragPoint, startPoint; + NSMutableParagraphStyle *paraStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; + + dragImage = [[NSImage alloc] initWithSize:buttonSize]; + [dragImage lockFocus]; { + float nameHeight; + NSSize nameSize; + NSDictionary *attributesDictionary; + + [iconImage drawInRect:NSMakeRect( buttonSize.width / 2. - iconSize.width / 2., iconBaseline, iconSize.width, iconSize.height ) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:.5]; + + [paraStyle setAlignment:NSCenterTextAlignment]; + attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont toolTipsFontOfSize:11.], NSFontAttributeName, [[NSColor blackColor] colorWithAlphaComponent:.5], NSForegroundColorAttributeName, paraStyle, NSParagraphStyleAttributeName, nil]; + nameSize = [name sizeWithAttributes:attributesDictionary]; + nameHeight = [[NSFont toolTipsFontOfSize:11.] defaultLineHeightForFont]; + [name drawAtPoint:NSMakePoint( 0., nameHeight + titleBaseline - nameSize.height ) withAttributes:attributesDictionary]; + [dragImage unlockFocus]; + } + + pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pasteboard declareTypes:[NSArray arrayWithObject:@"NSToolbarIndividualItemDragType"] owner:nil]; + [pasteboard setString:identifier forType:@"NSToolbarItemIdentiferPboardType"]; + + dragPoint = [self convertPoint:[event locationInWindow] fromView:nil]; + startPoint = [self _boundsForIndex:[preferencePanes indexOfObject:[NSBundle bundleWithIdentifier:identifier]]].origin; + startPoint.y += buttonSize.height; + [self setNeedsDisplayInRect:[self _boundsForIndex:pressedIconIndex]]; + pressedIconIndex = NSNotFound; + [self dragImage:dragImage at:startPoint offset:NSZeroSize event:event pasteboard:pasteboard source:self slideBack:YES]; + + return YES; +} +@end \ No newline at end of file