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