Skip to content

Commit

Permalink
Fix issue with preferences defaulting
Browse files Browse the repository at this point in the history
Fix a flaw in preference defaulting which was leading to a mismatch
between what the app menu showed and what was actually persisted
(mainly an issue with trying "subtract" a modifier from the defaults,
which we previously modeled as an empty preference)

Also refactors EMRPreferences to be a proper class rather than a
collection of class methods to allow a cleaner interface, better init
control, and improved testability.
  • Loading branch information
dmarcotte committed Jul 21, 2017
1 parent 999d402 commit 16ed829
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 205 deletions.
237 changes: 107 additions & 130 deletions easy-move-resize.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

25 changes: 18 additions & 7 deletions easy-move-resize/EMRAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@
#import "EMRMoveResize.h"
#import "EMRPreferences.h"

@implementation EMRAppDelegate
@implementation EMRAppDelegate {
EMRPreferences *preferences;
}

- (id) init {
self = [super init];
if (self) {
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"userPrefs"];
preferences = [[EMRPreferences alloc] initWithUserDefaults:userDefaults];
}
return self;
}

CGEventRef myCGEventCallback(CGEventTapProxy __unused proxy, CGEventType type, CGEventRef event, void *refcon) {

Expand Down Expand Up @@ -237,7 +248,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
[self initModifierMenuItems];

// Retrieve the Key press modifier flags to activate move/resize actions.
keyModifierFlags = [EMRPreferences modifierFlags];
keyModifierFlags = [preferences modifierFlags];

CFRunLoopSourceRef runLoopSource;

Expand Down Expand Up @@ -299,7 +310,7 @@ - (void)initModifierMenuItems {
[_ctrlMenu setState:0];
[_shiftMenu setState:0];
[_disabledMenu setState:0];
NSSet* flags = [EMRPreferences getFlagStringSet];
NSSet* flags = [preferences getFlagStringSet];
if ([flags containsObject:ALT_KEY]) {
[_altMenu setState:1];
}
Expand All @@ -318,14 +329,14 @@ - (IBAction)modifierToggle:(id)sender {
NSMenuItem *menu = (NSMenuItem*)sender;
BOOL newState = ![menu state];
[menu setState:newState];
[EMRPreferences setModifierKey:[menu title] enabled:newState];
keyModifierFlags = [EMRPreferences modifierFlags];
[preferences setModifierKey:[menu title] enabled:newState];
keyModifierFlags = [preferences modifierFlags];
}

- (IBAction)resetModifiersToDefaults:(id)sender {
[EMRPreferences removeDefaults];
[preferences setToDefaults];
[self initModifierMenuItems];
keyModifierFlags = [EMRPreferences modifierFlags];
keyModifierFlags = [preferences modifierFlags];
}

- (IBAction)toggleDisabled:(id)sender {
Expand Down
34 changes: 18 additions & 16 deletions easy-move-resize/EMRPreferences.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
//
// EMRPreferences.h
// easy-move-resize
//
// Created by Rajpaul Bagga on 2016-01-21.
//
// Preferences can be stored manually by running from Terminal a command like:
// defaults write org.dmarcotte.Easy-Move-Resize ModifierFlags CMD,CTRL


// Preferences can alternativevly be managed from the Terminal:
// Read:
// `defaults write org.dmarcotte.Easy-Move-Resize ModifierFlags CMD,CTRL`
// Write:
// `defaults write org.dmarcotte.Easy-Move-Resize ModifierFlags CMD,CTRL`
// Note that deleting this preference or writing invalid keys may cause trouble and require that
// you choose "Reset to Defaults from the app menu.
#ifndef EMRPreferences_h
#define EMRPreferences_h

Expand All @@ -22,15 +19,20 @@

}

// Initialize an EMRPreferences, persisting settings to the given userDefaults
- (id)initWithUserDefaults:(NSUserDefaults *)defaults;

// Get the modifier flags from the standard preferences
+ (int) modifierFlags;
// Store a modifier flag string in the preferences. (e.g. "CTRL,CMD"
+ (void) setModifierFlagString:(NSString*)flagString;
- (int) modifierFlags;

// Set or unset the given modifier key in the preferences
- (void) setModifierKey:(NSString*)singleFlagString enabled:(BOOL)enabled;

+ (void) setModifierKey:(NSString*)singleFlagString enabled:(BOOL)enabled;
+ (NSSet*) getFlagStringSet;
// returns a set of the currently persisted key constants
- (NSSet*) getFlagStringSet;

+ (void) removeDefaults;
// reset preferences to the defaults
- (void)setToDefaults;

@end

Expand Down
66 changes: 40 additions & 26 deletions easy-move-resize/EMRPreferences.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,35 @@

#define DEFAULT_MODIFIER_FLAGS kCGEventFlagMaskCommand | kCGEventFlagMaskControl

@implementation EMRPreferences
@implementation EMRPreferences {
@private
NSUserDefaults *userDefaults;
}

- (id)init {
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"Must initialize with a NSUserDefaults pointer in -initWithUserDefaults"
userInfo:nil];
return nil;
}

- (id)initWithUserDefaults:(NSUserDefaults *)defaults {
self = [super init];
if (self) {
userDefaults = defaults;
NSString *modifierFlagString = [userDefaults stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
if (modifierFlagString == nil) {
// ensure our defaults are initialized
[self setToDefaults];
}
}
return self;
}

+ (int)modifierFlags {
- (int)modifierFlags {
int modifierFlags = 0;

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

NSString *modifierFlagString = [defaults stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
NSString *modifierFlagString = [userDefaults stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
if (modifierFlagString == nil) {
return DEFAULT_MODIFIER_FLAGS;
}
Expand All @@ -19,21 +40,18 @@ + (int)modifierFlags {
return modifierFlags;
}

+ (void)setModifierFlagString:(NSString *)flagString {
- (void)setModifierFlagString:(NSString *)flagString {
flagString = [[flagString stringByReplacingOccurrencesOfString:@" " withString:@""] uppercaseString];
[[NSUserDefaults standardUserDefaults] setObject:flagString forKey:MODIFIER_FLAGS_DEFAULTS_KEY];
[userDefaults setObject:flagString forKey:MODIFIER_FLAGS_DEFAULTS_KEY];
}


+ (void)setModifierKey:(NSString *)singleFlagString enabled:(BOOL)enabled {
- (void)setModifierKey:(NSString *)singleFlagString enabled:(BOOL)enabled {
singleFlagString = [singleFlagString uppercaseString];
NSString *modifierFlagString = [[NSUserDefaults standardUserDefaults] stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
NSString *modifierFlagString = [userDefaults stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
if (modifierFlagString == nil) {
// No prior value set. Set if enabled.
if (enabled) {
[self setModifierFlagString:singleFlagString];
return;
}
NSLog(@"Unexpected null... this should always have a value");
[self setToDefaults];
}
NSMutableSet *flagSet = [self createSetFromFlagString:modifierFlagString];
if (enabled) {
Expand All @@ -45,24 +63,21 @@ + (void)setModifierKey:(NSString *)singleFlagString enabled:(BOOL)enabled {
[self setModifierFlagString:[[flagSet allObjects] componentsJoinedByString:@","]];
}

+ (NSSet*)getFlagStringSet {
NSString *modifierFlagString = [[NSUserDefaults standardUserDefaults] stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
- (NSSet*)getFlagStringSet {
NSString *modifierFlagString = [userDefaults stringForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
if (modifierFlagString == nil) {
return [NSSet setWithObjects:CTRL_KEY, CMD_KEY, nil];
NSLog(@"Unexpected null... this should always have a value");
[self setToDefaults];
}
NSMutableSet *flagSet = [self createSetFromFlagString:modifierFlagString];
return flagSet;
}

+ (void) removeDefaults {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:MODIFIER_FLAGS_DEFAULTS_KEY];
- (void)setToDefaults {
[self setModifierFlagString:[@[CTRL_KEY, CMD_KEY] componentsJoinedByString:@","]];
}


// --------------------------------------------------------------------
// Private methods

+ (NSMutableSet*)createSetFromFlagString:(NSString*)modifierFlagString {
- (NSMutableSet*)createSetFromFlagString:(NSString*)modifierFlagString {
modifierFlagString = [[modifierFlagString stringByReplacingOccurrencesOfString:@" " withString:@""] uppercaseString];
if ([modifierFlagString length] == 0) {
return [[NSMutableSet alloc] initWithCapacity:0];
Expand All @@ -72,8 +87,7 @@ + (NSMutableSet*)createSetFromFlagString:(NSString*)modifierFlagString {
return flagSet;
}


+ (int)flagsFromFlagString:(NSString*)modifierFlagString {
- (int)flagsFromFlagString:(NSString*)modifierFlagString {
int modifierFlags = 0;
if (modifierFlagString == nil || [modifierFlagString length] == 0) {
return 0;
Expand Down
43 changes: 43 additions & 0 deletions easy-move-resizeTests/EMRPreferencesTest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#import <XCTest/XCTest.h>
#import "EMRPreferences.h"

@interface EMRPreferencesTest : XCTestCase

@end

@implementation EMRPreferencesTest {
NSString *testDefaultsName;
EMRPreferences *preferences;
}

- (void)setUp {
[super setUp];
NSString *uuid = [[NSUUID UUID] UUIDString];
testDefaultsName = [@"org.dmarcotte.Easy-Move-Resize." stringByAppendingString:uuid];
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:testDefaultsName];
preferences = [[EMRPreferences alloc] initWithUserDefaults:userDefaults];
}

- (void)tearDown {
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:testDefaultsName];
[super tearDown];
}

- (void)testResetPreferences {
[preferences setToDefaults];
NSSet *flagStringSet = [preferences getFlagStringSet];
NSSet *expectedSet = [NSSet setWithArray:@[@"CTRL", @"CMD"]];
XCTAssertEqualObjects(flagStringSet, expectedSet, "Should contain the expected defaults");

[preferences setModifierKey:@"CTRL" enabled:NO];
flagStringSet = [preferences getFlagStringSet];
expectedSet = [NSSet setWithArray:@[@"CMD"]];
XCTAssertEqualObjects(flagStringSet, expectedSet, "Should contain the modified defaults");

[preferences setToDefaults];
flagStringSet = [preferences getFlagStringSet];
expectedSet = [NSSet setWithArray:@[@"CMD", @"CTRL"]];
XCTAssertEqualObjects(flagStringSet, expectedSet, "Should contain the restored defaults");
}

@end
22 changes: 22 additions & 0 deletions easy-move-resizeTests/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
26 changes: 0 additions & 26 deletions easy-move-resizeTests/easy_move_resizeTests.m

This file was deleted.

0 comments on commit 16ed829

Please sign in to comment.