mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Prefs commit.
This commit is contained in:
parent
926b5e4e90
commit
3bc9784e37
BIN
camino/English.lproj/MVPreferencePaneGroups.strings
Normal file
BIN
camino/English.lproj/MVPreferencePaneGroups.strings
Normal file
Binary file not shown.
32
camino/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
32
camino/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
12
camino/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
12
camino/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>19 36 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q45</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
camino/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
BIN
camino/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
Binary file not shown.
7
camino/PreferencePanes/MVPreferencePaneDefaults.plist
Normal file
7
camino/PreferencePanes/MVPreferencePaneDefaults.plist
Normal file
@ -0,0 +1,7 @@
|
||||
( Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane
|
||||
)
|
14
camino/PreferencePanes/MVPreferencePaneGroups.plist
Normal file
14
camino/PreferencePanes/MVPreferencePaneGroups.plist
Normal file
@ -0,0 +1,14 @@
|
||||
(
|
||||
{
|
||||
identifier = chimera;
|
||||
panes = (
|
||||
Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane,
|
||||
Chimera.AdvancedPrefPane
|
||||
);
|
||||
}
|
||||
)
|
BIN
camino/PreferencePanes/MVPreferencePaneGroups.strings
Normal file
BIN
camino/PreferencePanes/MVPreferencePaneGroups.strings
Normal file
Binary file not shown.
32
camino/PreferencePanes/MVPreferences.nib/classes.nib
generated
Normal file
32
camino/PreferencePanes/MVPreferences.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
12
camino/PreferencePanes/MVPreferences.nib/info.nib
generated
Normal file
12
camino/PreferencePanes/MVPreferences.nib/info.nib
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>19 36 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q45</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
camino/PreferencePanes/MVPreferences.nib/objects.nib
generated
Normal file
BIN
camino/PreferencePanes/MVPreferences.nib/objects.nib
generated
Normal file
Binary file not shown.
298
camino/PreferencePanes/MVPreferencesController.m
Normal file
298
camino/PreferencePanes/MVPreferencesController.m
Normal file
@ -0,0 +1,298 @@
|
||||
#import <PreferencePanes/PreferencePanes.h>
|
||||
#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
|
||||
|
157
camino/PreferencePanes/MVPreferencesGroupedIconView.m
Normal file
157
camino/PreferencePanes/MVPreferencesGroupedIconView.m
Normal file
@ -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
|
393
camino/PreferencePanes/MVPreferencesMultipleIconView.m
Normal file
393
camino/PreferencePanes/MVPreferencesMultipleIconView.m
Normal file
@ -0,0 +1,393 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#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
|
55
camino/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib
generated
Normal file
55
camino/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
26
camino/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib
generated
Normal file
26
camino/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>372 4 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBGroupedObjects</key>
|
||||
<dict>
|
||||
<key>3</key>
|
||||
<array>
|
||||
<string>153</string>
|
||||
<string>155</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>4</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q125</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
camino/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib
generated
Normal file
BIN
camino/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib
generated
Normal file
Binary file not shown.
55
camino/PreferencePanes/Personal/Personal.nib/classes.nib
generated
Normal file
55
camino/PreferencePanes/Personal/Personal.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
26
camino/PreferencePanes/Personal/Personal.nib/info.nib
generated
Normal file
26
camino/PreferencePanes/Personal/Personal.nib/info.nib
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>372 4 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBGroupedObjects</key>
|
||||
<dict>
|
||||
<key>3</key>
|
||||
<array>
|
||||
<string>153</string>
|
||||
<string>155</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>4</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q125</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
camino/PreferencePanes/Personal/Personal.nib/objects.nib
generated
Normal file
BIN
camino/PreferencePanes/Personal/Personal.nib/objects.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
32
camino/resources/localized/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
32
camino/resources/localized/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
12
camino/resources/localized/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
12
camino/resources/localized/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>19 36 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q45</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
camino/resources/localized/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
BIN
camino/resources/localized/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
Binary file not shown.
7
camino/src/preferences/MVPreferencePaneDefaults.plist
Normal file
7
camino/src/preferences/MVPreferencePaneDefaults.plist
Normal file
@ -0,0 +1,7 @@
|
||||
( Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane
|
||||
)
|
14
camino/src/preferences/MVPreferencePaneGroups.plist
Normal file
14
camino/src/preferences/MVPreferencePaneGroups.plist
Normal file
@ -0,0 +1,14 @@
|
||||
(
|
||||
{
|
||||
identifier = chimera;
|
||||
panes = (
|
||||
Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane,
|
||||
Chimera.AdvancedPrefPane
|
||||
);
|
||||
}
|
||||
)
|
157
camino/src/preferences/MVPreferencesGroupedIconView.m
Normal file
157
camino/src/preferences/MVPreferencesGroupedIconView.m
Normal file
@ -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
|
393
camino/src/preferences/MVPreferencesMultipleIconView.m
Normal file
393
camino/src/preferences/MVPreferencesMultipleIconView.m
Normal file
@ -0,0 +1,393 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#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
|
BIN
chimera/English.lproj/MVPreferencePaneGroups.strings
Normal file
BIN
chimera/English.lproj/MVPreferencePaneGroups.strings
Normal file
Binary file not shown.
32
chimera/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
32
chimera/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
12
chimera/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
12
chimera/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>19 36 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q45</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
chimera/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
BIN
chimera/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
Binary file not shown.
7
chimera/PreferencePanes/MVPreferencePaneDefaults.plist
Normal file
7
chimera/PreferencePanes/MVPreferencePaneDefaults.plist
Normal file
@ -0,0 +1,7 @@
|
||||
( Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane
|
||||
)
|
14
chimera/PreferencePanes/MVPreferencePaneGroups.plist
Normal file
14
chimera/PreferencePanes/MVPreferencePaneGroups.plist
Normal file
@ -0,0 +1,14 @@
|
||||
(
|
||||
{
|
||||
identifier = chimera;
|
||||
panes = (
|
||||
Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane,
|
||||
Chimera.AdvancedPrefPane
|
||||
);
|
||||
}
|
||||
)
|
BIN
chimera/PreferencePanes/MVPreferencePaneGroups.strings
Normal file
BIN
chimera/PreferencePanes/MVPreferencePaneGroups.strings
Normal file
Binary file not shown.
32
chimera/PreferencePanes/MVPreferences.nib/classes.nib
generated
Normal file
32
chimera/PreferencePanes/MVPreferences.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
12
chimera/PreferencePanes/MVPreferences.nib/info.nib
generated
Normal file
12
chimera/PreferencePanes/MVPreferences.nib/info.nib
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>19 36 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q45</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
chimera/PreferencePanes/MVPreferences.nib/objects.nib
generated
Normal file
BIN
chimera/PreferencePanes/MVPreferences.nib/objects.nib
generated
Normal file
Binary file not shown.
298
chimera/PreferencePanes/MVPreferencesController.m
Normal file
298
chimera/PreferencePanes/MVPreferencesController.m
Normal file
@ -0,0 +1,298 @@
|
||||
#import <PreferencePanes/PreferencePanes.h>
|
||||
#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
|
||||
|
157
chimera/PreferencePanes/MVPreferencesGroupedIconView.m
Normal file
157
chimera/PreferencePanes/MVPreferencesGroupedIconView.m
Normal file
@ -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
|
393
chimera/PreferencePanes/MVPreferencesMultipleIconView.m
Normal file
393
chimera/PreferencePanes/MVPreferencesMultipleIconView.m
Normal file
@ -0,0 +1,393 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#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
|
55
chimera/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib
generated
Normal file
55
chimera/PreferencePanes/Personal/English.lproj/Personal.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
26
chimera/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib
generated
Normal file
26
chimera/PreferencePanes/Personal/English.lproj/Personal.nib/info.nib
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>372 4 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBGroupedObjects</key>
|
||||
<dict>
|
||||
<key>3</key>
|
||||
<array>
|
||||
<string>153</string>
|
||||
<string>155</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>4</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q125</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
chimera/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib
generated
Normal file
BIN
chimera/PreferencePanes/Personal/English.lproj/Personal.nib/objects.nib
generated
Normal file
Binary file not shown.
55
chimera/PreferencePanes/Personal/Personal.nib/classes.nib
generated
Normal file
55
chimera/PreferencePanes/Personal/Personal.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
26
chimera/PreferencePanes/Personal/Personal.nib/info.nib
generated
Normal file
26
chimera/PreferencePanes/Personal/Personal.nib/info.nib
generated
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>372 4 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBGroupedObjects</key>
|
||||
<dict>
|
||||
<key>3</key>
|
||||
<array>
|
||||
<string>153</string>
|
||||
<string>155</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>4</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q125</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
chimera/PreferencePanes/Personal/Personal.nib/objects.nib
generated
Normal file
BIN
chimera/PreferencePanes/Personal/Personal.nib/objects.nib
generated
Normal file
Binary file not shown.
Binary file not shown.
32
chimera/resources/localized/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
32
chimera/resources/localized/English.lproj/MVPreferences.nib/classes.nib
generated
Normal file
@ -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;
|
||||
}
|
12
chimera/resources/localized/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
12
chimera/resources/localized/English.lproj/MVPreferences.nib/info.nib
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>19 36 356 240 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5Q45</string>
|
||||
</dict>
|
||||
</plist>
|
BIN
chimera/resources/localized/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
BIN
chimera/resources/localized/English.lproj/MVPreferences.nib/objects.nib
generated
Normal file
Binary file not shown.
7
chimera/src/preferences/MVPreferencePaneDefaults.plist
Normal file
7
chimera/src/preferences/MVPreferencePaneDefaults.plist
Normal file
@ -0,0 +1,7 @@
|
||||
( Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane
|
||||
)
|
14
chimera/src/preferences/MVPreferencePaneGroups.plist
Normal file
14
chimera/src/preferences/MVPreferencePaneGroups.plist
Normal file
@ -0,0 +1,14 @@
|
||||
(
|
||||
{
|
||||
identifier = chimera;
|
||||
panes = (
|
||||
Chimera.SitesPrefPane,
|
||||
Chimera.BrowsingPrefPane,
|
||||
Chimera.PersonalPrefPane,
|
||||
Chimera.HelpersPrefPane,
|
||||
Chimera.PrivacyPrefPane,
|
||||
Chimera.SecurityPrefPane,
|
||||
Chimera.AdvancedPrefPane
|
||||
);
|
||||
}
|
||||
)
|
157
chimera/src/preferences/MVPreferencesGroupedIconView.m
Normal file
157
chimera/src/preferences/MVPreferencesGroupedIconView.m
Normal file
@ -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
|
393
chimera/src/preferences/MVPreferencesMultipleIconView.m
Normal file
393
chimera/src/preferences/MVPreferencesMultipleIconView.m
Normal file
@ -0,0 +1,393 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#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
|
Loading…
Reference in New Issue
Block a user