If you have an issue with any of our projects. feel free to register.

Unverified Commit 5a1c3982 authored by Christopher Snowhill's avatar Christopher Snowhill Committed by GitHub

Merge pull request #72 from nevack/nevack/preferences-revamp

Use SF Symbols in Preferences on Big Sur.
parents 515216cd 581b9e42
......@@ -10,16 +10,17 @@
#import "PreferencePanePlugin.h"
@interface GeneralPreferencePane : NSObject <PreferencePane> {
IBOutlet NSView *view;
NSString *title;
NSImage *icon;
IBOutlet NSView *view;
}
+ (GeneralPreferencePane *)preferencePaneWithView:(NSView *)v title:(NSString *)t iconNamed:(NSString *)i;
+ (instancetype)preferencePaneWithView:(NSView *)view
title:(NSString *)title
systemIconName:(NSString *)systemIconName
orOldIconNamed:(NSString *)oldIconName;
- (void)setView:(NSView *)v;
- (void)setTitle:(NSString *)t;
- (void)setIcon:(NSImage *)i;
- (instancetype) init NS_UNAVAILABLE;
- (instancetype) initWithView:(NSView *)contentView
title:(NSString *)title
icon:(NSImage *)image NS_DESIGNATED_INITIALIZER;
@end
......@@ -11,49 +11,39 @@
@implementation GeneralPreferencePane
+ (GeneralPreferencePane *)preferencePaneWithView:(NSView *)v title:(NSString *)t iconNamed:(NSString *)n
@synthesize title = _title;
@synthesize icon = _icon;
@synthesize view;
+ (instancetype)preferencePaneWithView:(NSView *)view
title:(NSString *)title
systemIconName:(NSString *)systemIconName
orOldIconNamed:(NSString *)oldIconName
{
GeneralPreferencePane *pane = [[GeneralPreferencePane alloc] init];
if (pane)
{
[pane setView:v];
[pane setTitle:t];
NSImage *i = [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:n]];
[pane setIcon:i];
}
return pane;
NSImage *icon;
if (@available(macOS 11.0, *))
{
if (systemIconName)
icon = [NSImage imageWithSystemSymbolName:systemIconName accessibilityDescription:nil];
}
if (icon == nil)
{
NSString *file = [[NSBundle bundleForClass:[self class]] pathForImageResource:oldIconName];
icon = [[NSImage alloc] initWithContentsOfFile:file];
}
return [[GeneralPreferencePane alloc] initWithView:view title:title icon:icon];
}
- (NSView *)view
{
return view;
}
- (NSString *)title
{
return title;
}
- (NSImage *)icon
{
return icon;
}
- (void)setView:(NSView *)v
{
view = v;
}
- (void)setTitle:(NSString *)t
{
title = t;
}
- (void)setIcon:(NSImage *)i
{
icon = i;
- (instancetype)initWithView:(NSView *)contentView title:(NSString *)title icon:(NSImage *)image {
self = [[[self class] alloc] init];
if (self)
{
view = contentView;
_title = title;
_icon = image;
}
return self;
}
@end
......@@ -15,17 +15,16 @@
#import "MIDIPane.h"
@interface GeneralPreferencesPlugin : NSObject <PreferencePanePlugin> {
IBOutlet HotKeyPane *hotKeyPane;
IBOutlet OutputPane *outputPane;
IBOutlet HotKeyPane *hotKeyPane;
IBOutlet OutputPane *outputPane;
IBOutlet MIDIPane *midiPane;
IBOutlet NSView *playlistView;
IBOutlet NSView *scrobblerView;
IBOutlet NSView *updatesView;
IBOutlet NSView *growlView;
IBOutlet NSView *appearanceView;
IBOutlet NSView *midiView;
IBOutlet NSView *playlistView;
IBOutlet NSView *scrobblerView;
IBOutlet NSView *updatesView;
IBOutlet NSView *notificationsView;
IBOutlet NSView *appearanceView;
__weak IBOutlet NSButton *iTunesStyleCheck;
}
......@@ -36,7 +35,7 @@
- (GeneralPreferencePane *)updatesPane;
- (GeneralPreferencePane *)scrobblerPane;
- (GeneralPreferencePane *)playlistPane;
- (GeneralPreferencePane *)growlPane;
- (GeneralPreferencePane *)notificationsPane;
- (GeneralPreferencePane *)appearancePane;
......
......@@ -25,28 +25,28 @@
+ (NSArray *)preferencePanes
{
GeneralPreferencesPlugin *plugin = [[GeneralPreferencesPlugin alloc] init];
[NSBundle loadNibNamed:@"Preferences" owner:plugin];
return [NSArray arrayWithObjects:
[plugin playlistPane],
[plugin hotKeyPane],
[plugin updatesPane],
[plugin outputPane],
[plugin scrobblerPane],
[plugin growlPane],
[plugin appearancePane],
[plugin midiPane],
nil];
}
[[NSBundle bundleWithIdentifier:@"org.cogx.cog.preferences"] loadNibNamed:@"Preferences"
owner:plugin
topLevelObjects:nil];
return @[[plugin playlistPane],
[plugin hotKeyPane],
[plugin updatesPane],
[plugin outputPane],
[plugin scrobblerPane],
[plugin notificationsPane],
[plugin appearancePane],
[plugin midiPane]];
}
- (HotKeyPane *)hotKeyPane
{
return hotKeyPane;
return hotKeyPane;
}
- (OutputPane *)outputPane
{
return outputPane;
return outputPane;
}
- (MIDIPane *)midiPane
......@@ -56,36 +56,51 @@
- (GeneralPreferencePane *)updatesPane
{
return [GeneralPreferencePane preferencePaneWithView:updatesView title:NSLocalizedStringFromTableInBundle(@"Updates", nil, [NSBundle bundleForClass:[self class]], @"") iconNamed:@"updates"];
return [GeneralPreferencePane preferencePaneWithView:updatesView
title:NSLocalizedPrefString(@"Updates")
systemIconName:@"arrow.triangle.2.circlepath.circle.fill"
orOldIconNamed:@"updates"];
}
- (GeneralPreferencePane *)scrobblerPane
{
return [GeneralPreferencePane preferencePaneWithView:scrobblerView title:NSLocalizedStringFromTableInBundle(@"Last.fm", nil, [NSBundle bundleForClass:[self class]], @"") iconNamed:@"lastfm"];
return [GeneralPreferencePane preferencePaneWithView:scrobblerView
title:NSLocalizedPrefString(@"Scrobble")
systemIconName:@"dot.radiowaves.left.and.right"
orOldIconNamed:@"lastfm"];
}
- (GeneralPreferencePane *)playlistPane
{
return [GeneralPreferencePane preferencePaneWithView:playlistView title:NSLocalizedStringFromTableInBundle(@"Playlist", nil, [NSBundle bundleForClass:[self class]], @"") iconNamed:@"playlist"];
return [GeneralPreferencePane preferencePaneWithView:playlistView
title:NSLocalizedPrefString(@"Playlist")
systemIconName:@"music.note.list"
orOldIconNamed:@"playlist"];
}
- (GeneralPreferencePane *)growlPane
- (GeneralPreferencePane *)notificationsPane
{
if (@available(macOS 10.14, *)) {
if (iTunesStyleCheck) {
iTunesStyleCheck.hidden = YES;
NSSize size = growlView.frame.size;
NSSize size = notificationsView.frame.size;
size.height -= 18;
[growlView setFrameSize:size];
[notificationsView setFrameSize:size];
}
}
return [GeneralPreferencePane preferencePaneWithView:growlView title:NSLocalizedStringFromTableInBundle(@"Growl", nil, [NSBundle bundleForClass:[self class]], @"") iconNamed:@"growl"];
return [GeneralPreferencePane preferencePaneWithView:notificationsView
title:NSLocalizedPrefString(@"Notifications")
systemIconName:@"bell.fill"
orOldIconNamed:@"growl"];
}
- (GeneralPreferencePane *)appearancePane
{
return [GeneralPreferencePane preferencePaneWithView:appearanceView title:NSLocalizedStringFromTableInBundle(@"Appearance", nil, [NSBundle bundleForClass:[self class]], @"") iconNamed:@"appearance"];
return [GeneralPreferencePane preferencePaneWithView:appearanceView
title:NSLocalizedPrefString(@"Appearance")
systemIconName:@"paintpalette.fill"
orOldIconNamed:@"appearance"];
}
@end
......@@ -31,11 +31,13 @@ static void setControlText(HotKeyControl* control, NSString* kcprop, NSString* m
- (NSString *)title
{
return NSLocalizedStringFromTableInBundle(@"Hot Keys", nil, [NSBundle bundleForClass:[self class]], @"");
return NSLocalizedPrefString(@"Hot Keys");
}
- (NSImage *)icon
{
if (@available(macOS 11.0, *))
return [NSImage imageWithSystemSymbolName:@"keyboard" accessibilityDescription:nil];
return [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"hot_keys"]];
}
......
......@@ -12,17 +12,19 @@
- (NSString *)title
{
return NSLocalizedStringFromTableInBundle(@"Synthesis", nil, [NSBundle bundleForClass:[self class]], @"");
return NSLocalizedPrefString(@"Synthesis");
}
- (NSImage *)icon
{
if (@available(macOS 11.0, *))
return [NSImage imageWithSystemSymbolName:@"pianokeys" accessibilityDescription:nil];
return [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"midi"]];
}
- (IBAction)setSoundFont:(id)sender
{
NSArray *fileTypes = [NSArray arrayWithObjects:@"sf2",@"sf2pack",@"sflist",@"json",nil];
NSArray *fileTypes = @[@"sf2", @"sf2pack", @"sflist", @"json"];
NSOpenPanel * panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection:NO];
[panel setCanChooseDirectories:NO];
......@@ -42,10 +44,8 @@
- (IBAction)setMidiPlugin:(id)sender
{
NSString * plugin = [[NSUserDefaults standardUserDefaults] stringForKey:@"midi.plugin"];
if ([plugin isEqualToString:@"Sc55rolD"] || [plugin isEqualToString:@"Sc55RoCl"])
[midiFlavorControl setEnabled:YES];
else
[midiFlavorControl setEnabled:NO];
BOOL enabled = [plugin isEqualToString:@"Sc55rolD"] || [plugin isEqualToString:@"Sc55RoCl"];
[midiFlavorControl setEnabled:enabled];
}
@end
......@@ -13,11 +13,13 @@
- (NSString *)title
{
return NSLocalizedStringFromTableInBundle(@"Output", nil, [NSBundle bundleForClass:[self class]], @"");
return NSLocalizedPrefString(@"Output");
}
- (NSImage *)icon
{
if (@available(macOS 11.0, *))
return [NSImage imageWithSystemSymbolName:@"hifispeaker.2.fill" accessibilityDescription:nil];
return [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"output"]];
}
......
......@@ -8,20 +8,21 @@
#import <Cocoa/Cocoa.h>
#define NSLocalizedPrefString(key) \
[[NSBundle bundleWithIdentifier:@"org.cogx.cog.preferences"] localizedStringForKey:(key) value:@"" table:nil]
@protocol PreferencePanePlugin <NSObject>
@protocol PreferencePane <NSObject>
@required
// An array of PrefPaneController instances that the plugin has available
+ (NSArray *)preferencePanes;
@property(readonly) NSView *view;
@property(readonly, copy) NSString *title;
@property(readonly) NSImage *icon;
@end
@protocol PreferencePane <NSObject>
@protocol PreferencePanePlugin <NSObject>
@required
- (NSView *)view;
- (NSString *)title;
- (NSImage *)icon;
// An array of PrefPaneController instances that the plugin has available
+ (NSArray<id<PreferencePane>> *)preferencePanes;
@end
......@@ -17,17 +17,13 @@
if (nil == window) {
// Determine path to the sample preference panes
NSString *pluginPath = [[NSBundle mainBundle] pathForResource:@"General" ofType:@"preferencePane"];
NSBundle *bundle = [NSBundle bundleWithPath:pluginPath];
NSBundle *bundle = [NSBundle bundleWithPath:pluginPath];
PreferencePluginController *pluginController = [[PreferencePluginController alloc] initWithPlugins:[NSArray arrayWithObject:bundle]];
window = [[PreferencesWindow alloc] initWithPreferencePanes:[pluginController preferencePanes]];
// Set which panes are included, and their order.
//[prefs setPanesOrder:[NSArray arrayWithObjects:@"General", @"Updating", @"A Non-Existent Preference Pane", nil]];
PreferencePluginController *pluginController = [[PreferencePluginController alloc] initWithPlugins:@[bundle]];
window = [[PreferencesWindow alloc] initWithPreferencePanes:[pluginController preferencePanes]];
}
// Show the preferences window.
[window show];
}
......
......@@ -8,14 +8,18 @@
#import <Cocoa/Cocoa.h>
/**
* TODO: Use NSTabViewController.
* This will allow to manage Toolbar automatically, lazy load
* preference panes and and crossfade between them.
*/
@interface PreferencesWindow : NSWindow<NSToolbarDelegate>
@interface PreferencesWindow : NSWindow<NSToolbarDelegate> {
NSMutableArray *preferencePaneOrder;
NSMutableDictionary *preferencePanes;
NSMutableDictionary *toolbarItems;
}
- (id)initWithPreferencePanes:(NSArray *)preferencePanes;
- (instancetype)initWithPreferencePanes:(NSArray *)preferencePanes NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithContentRect:(NSRect)contentRect
styleMask:(NSWindowStyleMask)style
backing:(NSBackingStoreType)backingStoreType
defer:(BOOL)flag NS_UNAVAILABLE;
- (void)show;
......
......@@ -20,144 +20,148 @@
@end
@implementation PreferencesWindow
@implementation PreferencesWindow {
NSMutableArray<NSToolbarItemIdentifier> *preferencePaneOrder;
NSMutableDictionary<NSToolbarItemIdentifier, id<PreferencePane>> *preferencePanes;
NSMutableDictionary<NSToolbarItemIdentifier, NSToolbarItem *> *toolbarItems;
}
- (id)initWithPreferencePanes:(NSArray *)panes
- (instancetype)initWithPreferencePanes:(NSArray<id<PreferencePane>> *)panes
{
self = [super initWithContentRect:NSMakeRect(0, 0, 350, 200)
styleMask:(NSClosableWindowMask | NSResizableWindowMask | NSTitledWindowMask)
backing:NSBackingStoreBuffered
defer:NO];
if (self)
{
preferencePaneOrder = [[NSMutableArray alloc] init];
preferencePanes = [[NSMutableDictionary alloc] init];
for (id<PreferencePane> pane in panes) {
[preferencePaneOrder addObject:[pane title]];
[preferencePanes setObject:pane forKey:[pane title]];
}
[self setReleasedWhenClosed:NO];
[self setTitle:@"Preferences"]; // initial default title
[self setShowsToolbarButton: NO];
[self setShowsResizeIndicator:NO];
[self center];
[[self standardWindowButton:NSWindowZoomButton] setEnabled:FALSE];
NSWindowStyleMask windowStyleMask =
(NSWindowStyleMaskClosable | NSWindowStyleMaskTitled);
self = [super initWithContentRect:NSMakeRect(0, 0, 530, 300)
styleMask:windowStyleMask
backing:NSBackingStoreBuffered
defer:NO];
if (self)
{
preferencePaneOrder = [[NSMutableArray alloc] init];
preferencePanes = [[NSMutableDictionary alloc] init];
for (id<PreferencePane> pane in panes) {
[preferencePaneOrder addObject:[pane title]];
[preferencePanes setObject:pane forKey:[pane title]];
}
[self setReleasedWhenClosed:NO];
[self setTitle:@"Preferences"];
[self center];
if (@available(macOS 11, *)) {
[self setToolbarStyle:NSWindowToolbarStylePreference];
}
[self createToolbar];
}
[self createToolbar];
}
return self;
}
- (NSString *)lastPaneDefaultsKey
{
return @"LastPreferencePane";
}
-(NSRect)newFrameForNewContentView:(NSView *)view {
NSRect newFrame = [self frame];
newFrame.size.height = [view frame].size.height + ([self frame].size.height - [[self contentView] frame].size.height);
newFrame.size.width = [view frame].size.width;
newFrame.origin.y += ([[self contentView] frame].size.height - [view frame].size.height);
return newFrame;
return @"LastPreferencePane";
}
- (void)setContentView:(NSView *)view animate:(BOOL)animate
{
NSSize newSize = view.bounds.size;
NSSize oldSize = [self contentView].bounds.size;
CGFloat diff = newSize.height - oldSize.height;
NSRect newFrame = [self frame];
newFrame.size.height += diff;
newFrame.origin.y -= diff;
if (animate) {
NSView *tempView = [[NSView alloc] initWithFrame:[[self contentView] frame]];
[self setContentView:tempView];
[self setContentView:nil];
}
NSRect newFrame = [self newFrameForNewContentView:view];
[self setFrame:newFrame display:animate animate:animate];
[self setContentView:view];
[self setFrame:newFrame display:animate animate:animate];
[self setContentView:view];
[self setContentSize:newSize];
}
- (BOOL)loadPaneNamed:(NSString *)name display:(BOOL)display
{
id<PreferencePane> paneController = [preferencePanes objectForKey:name];
id<PreferencePane> paneController = preferencePanes[name];
if (!paneController) {
return NO;
}
NSView *paneView = [paneController view];
if (!paneView) {
if (!paneView || [self contentView] == paneView) {
return NO;
}
[self setContentView:paneView animate:display];
[self setTitle:name];
[self setContentView:paneView animate:display];
// Update defaults
[[NSUserDefaults standardUserDefaults] setObject:name forKey:[self lastPaneDefaultsKey]];
[[self toolbar] setSelectedItemIdentifier:name];
return YES;
}
- (void)createToolbar
{
toolbarItems = [[NSMutableDictionary alloc] init];
for (NSString *name in preferencePaneOrder) {
id<PreferencePane> pane = [preferencePanes objectForKey:name];
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:name];
[item setPaletteLabel:name]; // item's label in the "Customize Toolbar" sheet (not relevant here, but we set it anyway)
[item setLabel:name]; // item's label in the toolbar
[item setToolTip:name];
[item setImage:[pane icon]];
[item setTarget:self];
[item setAction:@selector(toolbarItemClicked:)]; // action called when item is clicked
[toolbarItems setObject:item forKey:name];
}
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:[bundleIdentifier stringByAppendingString:@" Preferences Toolbar"]];
[toolbar setDelegate:self];
[toolbar setAllowsUserCustomization:NO];
[toolbar setAutosavesConfiguration:NO];
[toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[toolbar setSizeMode:NSToolbarSizeModeDefault];
[self setToolbar:toolbar];
}
toolbarItems = [[NSMutableDictionary alloc] init];
for (NSString *name in preferencePaneOrder) {
id<PreferencePane> pane = preferencePanes[name];
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:name];
[item setPaletteLabel:name]; // item's label in the "Customize Toolbar" sheet (not relevant here, but we set it anyway)
[item setLabel:name]; // item's label in the toolbar
[item setToolTip:name];
[item setImage:[pane icon]];
[item setTarget:self];
[item setAction:@selector(toolbarItemClicked:)]; // action called when item is clicked
toolbarItems[name] = item;
}
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:[bundleIdentifier stringByAppendingString:@" Preferences Toolbar"]];
[toolbar setDelegate:self];
[toolbar setAllowsUserCustomization:NO];
[toolbar setAutosavesConfiguration:NO];
[toolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel];
[toolbar setSizeMode:NSToolbarSizeModeDefault];
[self setToolbar:toolbar];