Files
2019-09-10 14:23:26 +08:00

122 lines
3.7 KiB
Objective-C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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
{
NSAssert([defaultsKeyName rangeOfString:@"."].location == NSNotFound,
@"Illegal character in binding name (“.”), please see http://git.io/x5YS.");
NSAssert([defaultsKeyName rangeOfString:@" "].location == NSNotFound,
@"Illegal character in binding name (“ ”), please see http://git.io/x5YS.");
[_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, @"Cant 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) {
[_shortcuts removeObjectForKey:key];
return;
}
// Bind new shortcut
[_shortcuts setObject:newShortcut forKey:key];
[_shortcutMonitor registerShortcut:newShortcut withAction:[_actions objectForKey:key]];
}
@end