Refactoring UserPrefs

This commit is contained in:
relikd
2019-10-03 12:13:38 +02:00
parent b25565c74f
commit ae18e93b6a
21 changed files with 223 additions and 255 deletions

View File

@@ -22,25 +22,21 @@
#import "SettingsAboutView.h"
#import "NSView+Ext.h"
#import "UserPrefs.h"
@implementation SettingsAboutView
- (instancetype)init {
self = [super initWithFrame: NSZeroRect];
NSString *name = [UserPrefs appName];
NSString *version = [NSString stringWithFormat:NSLocalizedString(@"Version %@", nil),
#if DEBUG
[UserPrefs appVersionWithBuildNo]
#else
[UserPrefs appVersion]
NSDictionary *info = [[NSBundle mainBundle] infoDictionary];
NSString *version = [NSString stringWithFormat:NSLocalizedString(@"Version %@", nil), info[@"CFBundleShortVersionString"]];
#if DEBUG // append build number, e.g., '0.9.4 (9906)'
version = [version stringByAppendingFormat:@" (%@)", info[@"CFBundleVersion"]];
#endif
];
// Application icon image (top-centered)
NSImageView *logo = [[NSView imageView:NSImageNameApplicationIcon size:64] placeIn:self x:CENTER yTop:PAD_M];
// Add app name
NSTextField *lblN = [[[[NSView label:name] large] bold] placeIn:self x:CENTER yTop: YFromTop(logo) + PAD_M];
NSTextField *lblN = [[[[NSView label:APP_NAME] large] bold] placeIn:self x:CENTER yTop: YFromTop(logo) + PAD_M];
// Add version info
NSTextField *lblV = [[[[NSView label:version] small] selectable] placeIn:self x:CENTER yTop: YFromTop(lblN) + PAD_S];

View File

@@ -24,6 +24,7 @@
#import "SettingsAppearanceView.h"
#import "AppHook.h"
#import "BarStatusItem.h"
#import "UserPrefs.h"
@implementation SettingsAppearance
@@ -41,10 +42,9 @@
/// Sync new value with UserDefaults and update status bar icon
- (void)didSelectCheckbox:(NSButton*)sender {
BOOL state = (sender.state == NSControlStateValueOn);
[[NSUserDefaults standardUserDefaults] setBool:state forKey:sender.identifier];
if ([sender.identifier isEqualToString:@"globalUnreadCount"] ||
[sender.identifier isEqualToString:@"globalTintMenuBarIcon"]) {
NSString *pref = sender.identifier;
UserPrefsSetBool(pref, (sender.state == NSControlStateValueOn));
if (pref == Pref_globalUnreadCount || pref == Pref_globalTintMenuIcon) { // == because static string
[[(AppHook*)NSApp statusItem] updateBarIcon];
}
}

View File

@@ -22,67 +22,64 @@
#import "SettingsAppearanceView.h"
#import "NSView+Ext.h"
#import "Constants.h"
#import "UserPrefs.h"
#import "Constants.h" // column icons
#import "UserPrefs.h" // preference constants & UserPrefsBool()
@interface SettingsAppearanceView()
@property (assign) NSUInteger row;
@property (assign) CGFloat y;
@end
/***/ static CGFloat const IconSize = 18;
/***/ static CGFloat const colWidth = (IconSize + PAD_M); // checkbox column width
/***/ static CGFloat const X__ = PAD_WIN + 0 * colWidth;
/***/ static CGFloat const _X_ = PAD_WIN + 1 * colWidth;
/***/ static CGFloat const __X = PAD_WIN + 2 * colWidth;
@implementation SettingsAppearanceView
- (instancetype)init {
self = [super initWithFrame: NSZeroRect];
self.row = 0;
// Insert matrix header (the three icons)
[self head:0 img:RSSImageSettingsGlobal tooltip:NSLocalizedString(@"Show in menu bar", nil)];
[self head:1 img:RSSImageSettingsGroup tooltip:NSLocalizedString(@"Show in group menu", nil)];
[self head:2 img:RSSImageSettingsFeed tooltip:NSLocalizedString(@"Show in feed menu", nil)];
// Generate checkbox matrix (checkbox state, X: default ON, O: default OFF, blank: hidden)
[self entry:"X " label:NSLocalizedString(@"Tint menu bar icon on unread", nil)];
[self entry:"X " label:NSLocalizedString(@"Update all feeds", nil)];
[self entry:"XXX" label:NSLocalizedString(@"Open all unread", nil)];
[self entry:"XXX" label:NSLocalizedString(@"Mark all read", nil)];
[self entry:"XXX" label:NSLocalizedString(@"Mark all unread", nil)];
[self entry:"XXX" label:NSLocalizedString(@"Number of unread items", nil)];
[self entry:" X" label:NSLocalizedString(@"Tick mark unread items", nil)];
[[self entry:" O" label:NSLocalizedString(@"Short article names", nil)] tooltip:NSLocalizedString(@"Truncate article title after 60 characters", nil)];
[[self entry:" O" label:NSLocalizedString(@"Limit number of articles", nil)] tooltip:NSLocalizedString(@"Display at most 40 articles in feed menu", nil)];
// Insert matrix header (icons above checkbox matrix)
ColumnIcon(self, X__, RSSImageSettingsGlobal, NSLocalizedString(@"Show in menu bar", nil));
ColumnIcon(self, _X_, RSSImageSettingsGroup, NSLocalizedString(@"Show in group menu", nil));
ColumnIcon(self, __X, RSSImageSettingsFeed, NSLocalizedString(@"Show in feed menu", nil));
// Generate checkbox matrix
self.y = PAD_WIN + IconSize + PAD_S;
[self entry:NSLocalizedString(@"Tint menu bar icon on unread", nil) c1:Pref_globalTintMenuIcon c2:nil c3:nil];
[self entry:NSLocalizedString(@"Update all feeds", nil) c1:Pref_globalUpdateAll c2:nil c3:nil];
[self entry:NSLocalizedString(@"Open all unread", nil) c1:Pref_globalOpenUnread c2:Pref_groupOpenUnread c3:Pref_feedOpenUnread];
[self entry:NSLocalizedString(@"Mark all read", nil) c1:Pref_globalMarkRead c2:Pref_groupMarkRead c3:Pref_feedMarkRead];
[self entry:NSLocalizedString(@"Mark all unread", nil) c1:Pref_globalMarkUnread c2:Pref_groupMarkUnread c3:Pref_feedMarkUnread];
[self entry:NSLocalizedString(@"Number of unread articles", nil) c1:Pref_globalUnreadCount c2:Pref_groupUnreadCount c3:Pref_feedUnreadCount];
[self entry:NSLocalizedString(@"Indicator for unread articles", nil) c1:nil c2:nil c3:Pref_feedUnreadIndicator];
[[self entry:NSLocalizedString(@"Truncate article title", nil) c1:nil c2:nil c3:Pref_feedTruncateTitle]
tooltip:NSLocalizedString(@"Truncate article title after 60 characters", nil)];
[[self entry:NSLocalizedString(@"Limit number of articles", nil) c1:nil c2:nil c3:Pref_feedLimitArticles]
tooltip:NSLocalizedString(@"Display at most 40 articles in feed menu", nil)];
return self;
}
/// Helper method for matrix table header icons
- (void)head:(int)x img:(NSImageName)img tooltip:(NSString*)ttip {
[[[NSView imageView:img size:IconSize] tooltip:ttip] placeIn:self x:PAD_WIN + x * colWidth yTop:PAD_WIN];
static inline void ColumnIcon(id this, CGFloat x, const NSImageName img, NSString *ttip) {
[[[NSView imageView:img size:IconSize] placeIn:this x:x yTop:PAD_WIN] tooltip:ttip];
}
/// Helper method for generating a checkbox
static inline NSButton* Checkbox(id this, CGFloat x, CGFloat y, NSString *key) {
NSButton *check = [[NSView checkbox: UserPrefsBool(key)] placeIn:this x:x yTop:y];
check.identifier = key;
return check;
}
/// Create new entry with 1-3 checkboxes and a descriptive label
- (NSTextField*)entry:(char*)m label:(NSString*)text {
static char* const scope[] = { "global", "group", "feed" };
static char* const ident[] = { "TintMenuBarIcon", "UpdateAll", "OpenUnread", "MarkRead", "MarkUnread", "UnreadCount", "TickMark", "ShortNames", "LimitArticles" };
CGFloat y = PAD_WIN + IconSize + PAD_S + self.row * (PAD_S + HEIGHT_LABEL);
// Add checkboxes: row 0 - 8, col 0 - 2
for (NSUInteger col = 0; col < 3; col++) {
NSString *key = [NSString stringWithFormat:@"%s%s", scope[col], ident[self.row]];
BOOL state;
switch (m[col]) {
case 'X': state = [UserPrefs defaultYES:key]; break;
case 'O': state = [UserPrefs defaultNO: key]; break;
default: continue; // ignore blanks
}
NSButton *check = [[NSView checkbox:state] placeIn:self x:PAD_WIN + col * colWidth + 2 yTop:y + 2]; // 2px checkbox offset
check.identifier = key;
check.accessibilityLabel = [text stringByAppendingFormat:@" (%s)", scope[col]]; // TODO: localize: global, group, feed
}
self.row += 1;
// Add label
return [[[NSView label:text] placeIn:self x:PAD_WIN + 3 * colWidth yTop:y] sizeToRight:PAD_WIN];
- (NSTextField*)entry:(NSString*)label c1:(NSString*)pref1 c2:(NSString*)pref2 c3:(NSString*)pref3 {
CGFloat y = self.y;
self.y += (PAD_S + HEIGHT_LABEL);
// TODO: localize: global, group, feed
if (pref1) Checkbox(self, X__ + 2, y + 2, pref1).accessibilityLabel = [label stringByAppendingString:@" (global)"];
if (pref2) Checkbox(self, _X_ + 2, y + 2, pref2).accessibilityLabel = [label stringByAppendingString:@" (group)"];
if (pref3) Checkbox(self, __X + 2, y + 2, pref3).accessibilityLabel = [label stringByAppendingString:@" (feed)"];
return [[[NSView label:label] placeIn:self x:PAD_WIN + 3 * colWidth yTop:y] sizeToRight:PAD_WIN];
}
@end

View File

@@ -44,7 +44,7 @@
[pop addItemWithTitle: [self applicationNameForBundleId:bundleID]];
pop.lastItem.representedObject = bundleID;
}
[pop selectItemAtIndex:[pop indexOfItemWithRepresentedObject:[UserPrefs getHttpApplication]]];
[pop selectItemAtIndex:[pop indexOfItemWithRepresentedObject:UserPrefsString(Pref_defaultHttpApplication)]];
// Default RSS Reader application
NSString *feedBundleId = CFBridgingRelease(LSCopyDefaultHandlerForURLScheme(CFSTR("feed")));
self.view.defaultReader.objectValue = [self applicationNameForBundleId:feedBundleId];
@@ -65,7 +65,7 @@
// Callback method fired when user selects a different item from popup list
- (void)changeHttpApplication:(NSPopUpButton *)sender {
[UserPrefs setHttpApplication:sender.selectedItem.representedObject];
UserPrefsSet(Pref_defaultHttpApplication, sender.selectedItem.representedObject);
}
// Callback method from round help button right of default feed reader text

View File

@@ -21,6 +21,7 @@
// SOFTWARE.
#import "ModalSheet.h"
#import "UserPrefs.h"
#import "NSView+Ext.h"
@interface ModalSheet()
@@ -35,7 +36,7 @@
static NSInteger const maxWidth = 1200;
static CGFloat const contentOffsetY = PAD_WIN + HEIGHT_BUTTON + PAD_L;
NSInteger w = [[NSUserDefaults standardUserDefaults] integerForKey:@"modalSheetWidth"];
NSInteger w = UserPrefsInt(Pref_modalSheetWidth);
if (w < minWidth) w = minWidth;
else if (w > maxWidth) w = maxWidth;
@@ -90,8 +91,9 @@
return;
}
// Save modal view width for next time
CGFloat w = NSWidth(self.contentView.frame) - 2 * PAD_WIN;
[[NSUserDefaults standardUserDefaults] setInteger:(NSInteger)w forKey:@"modalSheetWidth"];
NSInteger width = (NSInteger)(NSWidth(self.contentView.frame) - 2 * PAD_WIN);
if (UserPrefsInt(Pref_modalSheetWidth) != width)
UserPrefsSetInt(Pref_modalSheetWidth, width);
// Remove subviews to avoid _NSKeyboardFocusClipView issues
[self.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.sheetParent endSheet:self returnCode:(successful ? NSModalResponseOK : NSModalResponseCancel)];

View File

@@ -49,13 +49,13 @@
flexibleWidth,
TabItem(NSImageNameInfo, NSLocalizedString(@"About", nil), [SettingsAbout class]),
];
[self switchToTab:[UserPrefs defaultUInt:0 forKey:@"preferencesTab"]];
[self switchToTab: UserPrefsUInt(Pref_prefSelectedTab)];
}
return self;
}
/// Helper method to generate tab item with image, label, and controller.
static NSTabViewItem* TabItem(NSImageName imageName, NSString *text, Class class) {
static inline NSTabViewItem* TabItem(NSImageName imageName, NSString *text, Class class) {
NSTabViewItem *item = [NSTabViewItem tabViewItemWithViewController: [class new]];
item.image = [NSImage imageNamed:imageName];
item.label = text;
@@ -76,10 +76,9 @@ static NSTabViewItem* TabItem(NSImageName imageName, NSString *text, Class class
/// Delegate method, store last selected tab to user preferences
- (void)tabView:(NSTabView*)tabView didSelectTabViewItem:(nullable NSTabViewItem*)tabViewItem {
[super tabView:tabView didSelectTabViewItem:tabViewItem];
NSInteger prevIndex = [[NSUserDefaults standardUserDefaults] integerForKey:@"preferencesTab"];
NSInteger newIndex = self.selectedTabViewItemIndex;
if (prevIndex != newIndex)
[[NSUserDefaults standardUserDefaults] setInteger:newIndex forKey:@"preferencesTab"];
if (UserPrefsInt(Pref_prefSelectedTab) != newIndex)
UserPrefsSetInt(Pref_prefSelectedTab, newIndex);
}
@end
@@ -95,7 +94,7 @@ static NSTabViewItem* TabItem(NSImageName imageName, NSString *text, Class class
w.title = [NSString stringWithFormat:NSLocalizedString(@"%@ Preferences", nil), NSProcessInfo.processInfo.processName];
w.contentViewController = [PrefTabs new];
w.delegate = w;
NSWindowPersistableFrameDescriptor prevFrame = [[NSUserDefaults standardUserDefaults] stringForKey:@"prefWindow"];
NSWindowPersistableFrameDescriptor prevFrame = UserPrefsString(Pref_prefWindowFrame);
if (!prevFrame) {
[w setContentSize:NSMakeSize(320, 327)];
[w center];
@@ -111,7 +110,7 @@ static NSTabViewItem* TabItem(NSImageName imageName, NSString *text, Class class
}
- (void)windowWillClose:(NSNotification *)notification {
[[NSUserDefaults standardUserDefaults] setObject:self.stringWithSavedFrame forKey:@"prefWindow"];
UserPrefsSet(Pref_prefWindowFrame, self.stringWithSavedFrame);
}
/// Do not respond to Cmd-Z and Cmd-Shift-Z. Will be handled in subview controllers.