aboutsummaryrefslogtreecommitdiffstats
path: root/Framework/MASShortcutBinder.m
diff options
context:
space:
mode:
Diffstat (limited to 'Framework/MASShortcutBinder.m')
-rw-r--r--Framework/MASShortcutBinder.m114
1 files changed, 114 insertions, 0 deletions
diff --git a/Framework/MASShortcutBinder.m b/Framework/MASShortcutBinder.m
new file mode 100644
index 0000000..bf85c41
--- /dev/null
+++ b/Framework/MASShortcutBinder.m
@@ -0,0 +1,114 @@
+#import "MASShortcutBinder.h"
+#import "MASShortcut.h"
+
+@interface MASShortcutBinder ()
+@property(strong) NSMutableDictionary *actions;
+@property(strong) NSMutableDictionary *shortcuts;
+@end
+
+@implementation MASShortcutBinder
+
+#pragma mark Initialization
+
+- (id) init
+{
+ self = [super init];
+ [self setActions:[NSMutableDictionary dictionary]];
+ [self setShortcuts:[NSMutableDictionary dictionary]];
+ [self setShortcutMonitor:[MASShortcutMonitor sharedMonitor]];
+ [self setBindingOptions:@{NSValueTransformerNameBindingOption: NSKeyedUnarchiveFromDataTransformerName}];
+ return self;
+}
+
+- (void) dealloc
+{
+ for (NSString *bindingName in [_actions allKeys]) {
+ [self unbind:bindingName];
+ }
+}
+
++ (instancetype) sharedBinder
+{
+ static dispatch_once_t once;
+ static MASShortcutBinder *sharedInstance;
+ dispatch_once(&once, ^{
+ sharedInstance = [[self alloc] init];
+ });
+ return sharedInstance;
+}
+
+#pragma mark Registration
+
+- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action
+{
+ [_actions setObject:[action copy] forKey:defaultsKeyName];
+ [self bind:defaultsKeyName toObject:[NSUserDefaultsController sharedUserDefaultsController]
+ withKeyPath:[@"values." stringByAppendingString:defaultsKeyName] options:_bindingOptions];
+}
+
+- (void) breakBindingWithDefaultsKey: (NSString*) defaultsKeyName
+{
+ [_shortcutMonitor unregisterShortcut:[_shortcuts objectForKey:defaultsKeyName]];
+ [_shortcuts removeObjectForKey:defaultsKeyName];
+ [_actions removeObjectForKey:defaultsKeyName];
+ [self unbind:defaultsKeyName];
+}
+
+- (void) registerDefaultShortcuts: (NSDictionary*) defaultShortcuts
+{
+ NSValueTransformer *transformer = [_bindingOptions valueForKey:NSValueTransformerBindingOption];
+ if (transformer == nil) {
+ NSString *transformerName = [_bindingOptions valueForKey:NSValueTransformerNameBindingOption];
+ if (transformerName) {
+ transformer = [NSValueTransformer valueTransformerForName:transformerName];
+ }
+ }
+
+ NSAssert(transformer != nil, @"Can’t register default shortcuts without a transformer.");
+
+ [defaultShortcuts enumerateKeysAndObjectsUsingBlock:^(NSString *defaultsKey, MASShortcut *shortcut, BOOL *stop) {
+ id value = [transformer reverseTransformedValue:shortcut];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:@{defaultsKey:value}];
+ }];
+}
+
+#pragma mark Bindings
+
+- (BOOL) isRegisteredAction: (NSString*) name
+{
+ return !![_actions objectForKey:name];
+}
+
+- (id) valueForUndefinedKey: (NSString*) key
+{
+ return [self isRegisteredAction:key] ?
+ [_shortcuts objectForKey:key] :
+ [super valueForUndefinedKey:key];
+}
+
+- (void) setValue: (id) value forUndefinedKey: (NSString*) key
+{
+ if (![self isRegisteredAction:key]) {
+ [super setValue:value forUndefinedKey:key];
+ return;
+ }
+
+ MASShortcut *newShortcut = value;
+ MASShortcut *currentShortcut = [_shortcuts objectForKey:key];
+
+ // Unbind previous shortcut if any
+ if (currentShortcut != nil) {
+ [_shortcutMonitor unregisterShortcut:currentShortcut];
+ }
+
+ // Just deleting the old shortcut
+ if (newShortcut == nil) {
+ return;
+ }
+
+ // Bind new shortcut
+ [_shortcuts setObject:newShortcut forKey:key];
+ [_shortcutMonitor registerShortcut:newShortcut withAction:[_actions objectForKey:key]];
+}
+
+@end