diff options
| author | Vadim Shpakovski | 2012-09-19 13:16:23 +0300 |
|---|---|---|
| committer | Vadim Shpakovski | 2012-09-19 13:16:23 +0300 |
| commit | cbc369c71a79f613ffbc3dbad91086f047d3c221 (patch) | |
| tree | b02e8d839ba1183aa6d06657e77f5a3e829e033b | |
| parent | 4099b62587959708bd02d1c49ec1c8fa39448cf4 (diff) | |
| download | MASShortcut-cbc369c71a79f613ffbc3dbad91086f047d3c221.tar.bz2 | |
Removes ARC to support 32-bit.
| -rw-r--r-- | MASShortcut+Monitoring.m | 7 | ||||
| -rw-r--r-- | MASShortcut+UserDefaults.h | 8 | ||||
| -rw-r--r-- | MASShortcut+UserDefaults.m | 87 | ||||
| -rw-r--r-- | MASShortcut.m | 10 | ||||
| -rw-r--r-- | MASShortcutView+UserDefaults.h | 7 | ||||
| -rw-r--r-- | MASShortcutView+UserDefaults.m | 128 | ||||
| -rw-r--r-- | MASShortcutView.h | 17 | ||||
| -rw-r--r-- | MASShortcutView.m | 428 |
8 files changed, 9 insertions, 683 deletions
diff --git a/MASShortcut+Monitoring.m b/MASShortcut+Monitoring.m index 1460f6b..51787c2 100644 --- a/MASShortcut+Monitoring.m +++ b/MASShortcut+Monitoring.m @@ -25,7 +25,7 @@ void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, + (id)addGlobalHotkeyMonitorWithShortcut:(MASShortcut *)shortcut handler:(void (^)())handler { NSString *monitor = [NSString stringWithFormat:@"%p: %@", shortcut, shortcut.description]; - MASShortcutHotKey *hotKey = [[MASShortcutHotKey alloc] initWithShortcut:shortcut handler:handler]; + MASShortcutHotKey *hotKey = [[[MASShortcutHotKey alloc] initWithShortcut:shortcut handler:handler] autorelease]; [MASRegisteredHotKeys() setObject:hotKey forKey:monitor]; return monitor; } @@ -57,7 +57,7 @@ void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, { self = [super init]; if (self) { - _shortcut = shortcut; + _shortcut = [shortcut retain]; _handler = [handler copy]; InstallHotkeyWithShortcut(shortcut, &_carbonHotKeyID, &_carbonHotKey); } @@ -67,6 +67,7 @@ void InstallHotkeyWithShortcut(MASShortcut *shortcut, UInt32 *outCarbonHotKeyID, - (void)dealloc { [self uninstallExisitingHotKey]; + [super dealloc]; } - (void)uninstallExisitingHotKey @@ -86,7 +87,7 @@ NSMutableDictionary *MASRegisteredHotKeys() static NSMutableDictionary *shared = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - shared = [NSMutableDictionary dictionary]; + shared = [[NSMutableDictionary alloc] init]; }); return shared; } diff --git a/MASShortcut+UserDefaults.h b/MASShortcut+UserDefaults.h deleted file mode 100644 index 0c7f14e..0000000 --- a/MASShortcut+UserDefaults.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "MASShortcut.h" - -@interface MASShortcut (UserDefaults) - -+ (void)registerGlobalShortcutWithUserDefaultsKey:(NSString *)userDefaultsKey handler:(void (^)())handler; -+ (void)unregisterGlobalShortcutWithUserDefaultsKey:(NSString *)userDefaultsKey; - -@end diff --git a/MASShortcut+UserDefaults.m b/MASShortcut+UserDefaults.m deleted file mode 100644 index 3bdbab9..0000000 --- a/MASShortcut+UserDefaults.m +++ /dev/null @@ -1,87 +0,0 @@ -#import "MASShortcut+UserDefaults.h" -#import "MASShortcut+Monitoring.h" - -@interface MASShortcutUserDefaultsHotKey : NSObject - -@property (nonatomic, readonly) NSString *userDefaultsKey; -@property (nonatomic, copy) void (^handler)(); -@property (nonatomic, weak) id monitor; - -- (id)initWithUserDefaultsKey:(NSString *)userDefaultsKey handler:(void (^)())handler; - -@end - -#pragma mark - - -@implementation MASShortcut (UserDefaults) - -+ (NSMutableDictionary *)registeredUserDefaultsHotKeys -{ - static NSMutableDictionary *shared = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - shared = [NSMutableDictionary dictionary]; - }); - return shared; -} - -+ (void)registerGlobalShortcutWithUserDefaultsKey:(NSString *)userDefaultsKey handler:(void (^)())handler; -{ - MASShortcutUserDefaultsHotKey *hotKey = [[MASShortcutUserDefaultsHotKey alloc] initWithUserDefaultsKey:userDefaultsKey handler:handler]; - [[self registeredUserDefaultsHotKeys] setObject:hotKey forKey:userDefaultsKey]; -} - -+ (void)unregisterGlobalShortcutWithUserDefaultsKey:(NSString *)userDefaultsKey -{ - NSMutableDictionary *registeredHotKeys = [self registeredUserDefaultsHotKeys]; - [registeredHotKeys removeObjectForKey:userDefaultsKey]; -} - -@end - -#pragma mark - - -@implementation MASShortcutUserDefaultsHotKey - -@synthesize monitor = _monitor; -@synthesize handler = _handler; -@synthesize userDefaultsKey = _userDefaultsKey; - -#pragma mark - - -- (id)initWithUserDefaultsKey:(NSString *)userDefaultsKey handler:(void (^)())handler -{ - self = [super init]; - if (self) { - _userDefaultsKey = userDefaultsKey.copy; - _handler = [handler copy]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) - name:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]]; - [self installHotKeyFromUserDefaults]; - } - return self; -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]]; - [MASShortcut removeGlobalHotkeyMonitor:self.monitor]; -} - -#pragma mark - - -- (void)userDefaultsDidChange:(NSNotification *)note -{ - [MASShortcut removeGlobalHotkeyMonitor:self.monitor]; - [self installHotKeyFromUserDefaults]; -} - -- (void)installHotKeyFromUserDefaults -{ - NSData *data = [[NSUserDefaults standardUserDefaults] dataForKey:_userDefaultsKey]; - MASShortcut *shortcut = [MASShortcut shortcutWithData:data]; - if (shortcut == nil) return; - self.monitor = [MASShortcut addGlobalHotkeyMonitorWithShortcut:shortcut handler:self.handler]; -} - -@end diff --git a/MASShortcut.m b/MASShortcut.m index ca5a1ae..5bb039d 100644 --- a/MASShortcut.m +++ b/MASShortcut.m @@ -42,12 +42,12 @@ NSString *const kMASShortcutModifierFlags = @"ModifierFlags"; + (MASShortcut *)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags { - return [[self alloc] initWithKeyCode:code modifierFlags:flags]; + return [[[self alloc] initWithKeyCode:code modifierFlags:flags] autorelease]; } + (MASShortcut *)shortcutWithEvent:(NSEvent *)event { - return [[self alloc] initWithKeyCode:event.keyCode modifierFlags:event.modifierFlags]; + return [[[self alloc] initWithKeyCode:event.keyCode modifierFlags:event.modifierFlags] autorelease]; } + (MASShortcut *)shortcutWithData:(NSData *)data @@ -195,7 +195,7 @@ NSString *const kMASShortcutModifierFlags = @"ModifierFlags"; if (keystroke.length) { static NSMutableCharacterSet *validChars = nil; if (validChars == nil) { - validChars = [[NSMutableCharacterSet alloc] init]; + validChars = [[[NSMutableCharacterSet alloc] init] autorelease]; [validChars formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]]; [validChars formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]]; [validChars formUnionWithCharacterSet:[NSCharacterSet symbolCharacterSet]]; @@ -286,8 +286,8 @@ NSString *const kMASShortcutModifierFlags = @"ModifierFlags"; CFNumberRef code = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyCode); CFNumberRef flags = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyModifiers); - if (([(__bridge NSNumber *)code unsignedIntegerValue] == self.keyCode) && - ([(__bridge NSNumber *)flags unsignedIntegerValue] == self.carbonFlags)) { + if (([(NSNumber *)code unsignedIntegerValue] == self.keyCode) && + ([(NSNumber *)flags unsignedIntegerValue] == self.carbonFlags)) { if (outError) { NSString *description = NSLocalizedString(@"This combination cannot be used used because it is already used by a system-wide " diff --git a/MASShortcutView+UserDefaults.h b/MASShortcutView+UserDefaults.h deleted file mode 100644 index 05d3c5b..0000000 --- a/MASShortcutView+UserDefaults.h +++ /dev/null @@ -1,7 +0,0 @@ -#import "MASShortcutView.h" - -@interface MASShortcutView (UserDefaults) - -@property (nonatomic, copy) NSString *associatedUserDefaultsKey; - -@end diff --git a/MASShortcutView+UserDefaults.m b/MASShortcutView+UserDefaults.m deleted file mode 100644 index 42a2379..0000000 --- a/MASShortcutView+UserDefaults.m +++ /dev/null @@ -1,128 +0,0 @@ -#import "MASShortcutView+UserDefaults.h" -#import "MASShortcut.h" -#import <objc/runtime.h> - -@interface MASShortcutDefaultsObserver : NSObject - -@property (nonatomic, readonly) NSString *userDefaultsKey; -@property (nonatomic, readonly, weak) MASShortcutView *shortcutView; - -- (id)initWithShortcutView:(MASShortcutView *)shortcutView userDefaultsKey:(NSString *)userDefaultsKey; - -@end - -#pragma mark - - -@implementation MASShortcutView (UserDefaults) - -void *kDefaultsObserver = &kDefaultsObserver; - -- (NSString *)associatedUserDefaultsKey -{ - MASShortcutDefaultsObserver *defaultsObserver = objc_getAssociatedObject(self, kDefaultsObserver); - return defaultsObserver.userDefaultsKey; -} - -- (void)setAssociatedUserDefaultsKey:(NSString *)associatedUserDefaultsKey -{ - // First, stop observing previous shortcut view - objc_setAssociatedObject(self, kDefaultsObserver, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); - - // Next, start observing current shortcut view - MASShortcutDefaultsObserver *defaultsObserver = [[MASShortcutDefaultsObserver alloc] initWithShortcutView:self userDefaultsKey:associatedUserDefaultsKey]; - objc_setAssociatedObject(self, kDefaultsObserver, defaultsObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC); -} - -@end - -#pragma mark - - -@implementation MASShortcutDefaultsObserver { - MASShortcut *_originalShortcut; - BOOL _internalPreferenceChange; - BOOL _internalShortcutChange; -} - -@synthesize userDefaultsKey = _userDefaultsKey; -@synthesize shortcutView = _shortcutView; - -#pragma mark - - -- (id)initWithShortcutView:(MASShortcutView *)shortcutView userDefaultsKey:(NSString *)userDefaultsKey -{ - self = [super init]; - if (self) { - _originalShortcut = shortcutView.shortcutValue; - _shortcutView = shortcutView; - _userDefaultsKey = userDefaultsKey.copy; - [self startObservingShortcutView]; - } - return self; -} - -- (void)dealloc -{ - // __weak _shortcutView is not yet deallocated because it refers MASShortcutDefaultsObserver - [self stopObservingShortcutView]; -} - -#pragma mark - - -void *kShortcutValueObserver = &kShortcutValueObserver; - -- (void)startObservingShortcutView -{ - // Read initial shortcut value from user preferences - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSData *data = [defaults dataForKey:_userDefaultsKey]; - _shortcutView.shortcutValue = [MASShortcut shortcutWithData:data]; - - // Observe user preferences to update shortcut value when it changed - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:NSUserDefaultsDidChangeNotification object:defaults]; - - // Observe the keyboard shortcut that user inputs by hand - [_shortcutView addObserver:self forKeyPath:@"shortcutValue" options:0 context:kShortcutValueObserver]; -} - -- (void)userDefaultsDidChange:(NSNotification *)note -{ - // Ignore notifications posted from -[self observeValueForKeyPath:] - if (_internalPreferenceChange) return; - - _internalShortcutChange = YES; - NSData *data = [note.object dataForKey:_userDefaultsKey]; - _shortcutView.shortcutValue = [MASShortcut shortcutWithData:data]; - _internalShortcutChange = NO; -} - -- (void)stopObservingShortcutView -{ - // Stop observing keyboard hotkeys entered by user in the shortcut view - [_shortcutView removeObserver:self forKeyPath:@"shortcutValue" context:kShortcutValueObserver]; - - // Stop observing user preferences - [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:[NSUserDefaults standardUserDefaults]]; - - // Restore original hotkey in the shortcut view - _shortcutView.shortcutValue = _originalShortcut; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - if (context == kShortcutValueObserver) { - if (_internalShortcutChange) return; - MASShortcut *shortcut = [object valueForKey:keyPath]; - _internalPreferenceChange = YES; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setObject:(shortcut.data ?: [NSKeyedArchiver archivedDataWithRootObject:nil]) forKey:_userDefaultsKey]; - [defaults synchronize]; - - _internalPreferenceChange = NO; - } - else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -@end diff --git a/MASShortcutView.h b/MASShortcutView.h deleted file mode 100644 index 5259123..0000000 --- a/MASShortcutView.h +++ /dev/null @@ -1,17 +0,0 @@ -@class MASShortcut; - -typedef enum { - MASShortcutViewAppearanceDefault = 0, // Height = 19 px - MASShortcutViewAppearanceTexturedRect, // Height = 25 px - MASShortcutViewAppearanceRounded // Height = 43 px -} MASShortcutViewAppearance; - -@interface MASShortcutView : NSView - -@property (nonatomic, strong) MASShortcut *shortcutValue; -@property (nonatomic, getter = isRecording) BOOL recording; -@property (nonatomic, getter = isEnabled) BOOL enabled; -@property (nonatomic, copy) void (^shortcutValueChange)(MASShortcutView *sender); -@property (nonatomic) MASShortcutViewAppearance appearance; - -@end diff --git a/MASShortcutView.m b/MASShortcutView.m deleted file mode 100644 index 27e6ae7..0000000 --- a/MASShortcutView.m +++ /dev/null @@ -1,428 +0,0 @@ -#import "MASShortcutView.h" -#import "MASShortcut.h" - -#define HINT_BUTTON_WIDTH 23.0 -#define BUTTON_FONT_SIZE 11.0 -#define SEGMENT_CHROME_WIDTH 6.0 - -#pragma mark - - -@interface MASShortcutView () // Private accessors - -@property (nonatomic, getter = isHinting) BOOL hinting; -@property (nonatomic, copy) NSString *shortcutPlaceholder; - -@end - -#pragma mark - - -@implementation MASShortcutView { - NSButtonCell *_shortcutCell; - NSInteger _shortcutToolTipTag; - NSInteger _hintToolTipTag; - NSTrackingArea *_hintArea; -} - -@synthesize enabled = _enabled; -@synthesize hinting = _hinting; -@synthesize shortcutValue = _shortcutValue; -@synthesize shortcutPlaceholder = _shortcutPlaceholder; -@synthesize shortcutValueChange = _shortcutValueChange; -@synthesize recording = _recording; - -#pragma mark - - -- (id)initWithFrame:(CGRect)frameRect -{ - self = [super initWithFrame:frameRect]; - if (self) { - _shortcutCell = [[NSButtonCell alloc] init]; - _shortcutCell.buttonType = NSPushOnPushOffButton; - _shortcutCell.font = [[NSFontManager sharedFontManager] convertFont:_shortcutCell.font toSize:BUTTON_FONT_SIZE]; - _enabled = YES; - [self resetShortcutCellStyle]; - } - return self; -} - -- (void)dealloc -{ - [self activateEventMonitoring:NO]; - [self activateResignObserver:NO]; -} - -#pragma mark - Public accessors - -- (void)setEnabled:(BOOL)flag -{ - if (_enabled != flag) { - _enabled = flag; - [self updateTrackingAreas]; - self.recording = NO; - [self setNeedsDisplay:YES]; - } -} - -- (void)setAppearance:(MASShortcutViewAppearance)appearance -{ - if (_appearance != appearance) { - _appearance = appearance; - [self resetShortcutCellStyle]; - [self setNeedsDisplay:YES]; - } -} - -- (void)resetShortcutCellStyle -{ - switch (_appearance) { - case MASShortcutViewAppearanceDefault: { - _shortcutCell.bezelStyle = NSRoundRectBezelStyle; - break; - } - case MASShortcutViewAppearanceTexturedRect: { - _shortcutCell.bezelStyle = NSTexturedRoundedBezelStyle; - break; - } - case MASShortcutViewAppearanceRounded: { - _shortcutCell.bezelStyle = NSRoundedBezelStyle; - break; - } - } -} - -- (void)setRecording:(BOOL)flag -{ - // Only one recorder can be active at the moment - static MASShortcutView *currentRecorder = nil; - if (flag && (currentRecorder != self)) { - currentRecorder.recording = NO; - currentRecorder = flag ? self : nil; - } - - // Only enabled view supports recording - if (flag && !self.enabled) return; - - if (_recording != flag) { - _recording = flag; - self.shortcutPlaceholder = nil; - [self resetToolTips]; - [self activateEventMonitoring:_recording]; - [self activateResignObserver:_recording]; - [self setNeedsDisplay:YES]; - } -} - -- (void)setShortcutValue:(MASShortcut *)shortcutValue -{ - _shortcutValue = shortcutValue; - [self resetToolTips]; - [self setNeedsDisplay:YES]; - - if (self.shortcutValueChange) { - self.shortcutValueChange(self); - } -} - -- (void)setShortcutPlaceholder:(NSString *)shortcutPlaceholder -{ - _shortcutPlaceholder = shortcutPlaceholder.copy; - [self setNeedsDisplay:YES]; -} - -#pragma mark - Drawing - -- (BOOL)isFlipped -{ - return YES; -} - -- (void)drawInRect:(CGRect)frame withTitle:(NSString *)title alignment:(NSTextAlignment)alignment state:(NSInteger)state -{ - _shortcutCell.title = title; - _shortcutCell.alignment = alignment; - _shortcutCell.state = state; - _shortcutCell.enabled = self.enabled; - - switch (_appearance) { - case MASShortcutViewAppearanceDefault: { - [_shortcutCell drawWithFrame:frame inView:self]; - break; - } - case MASShortcutViewAppearanceTexturedRect: { - [_shortcutCell drawWithFrame:CGRectOffset(frame, 0.0, 1.0) inView:self]; - break; - } - case MASShortcutViewAppearanceRounded: { - [_shortcutCell drawWithFrame:CGRectOffset(frame, 0.0, 1.0) inView:self]; - break; - } - } -} - -- (void)drawRect:(CGRect)dirtyRect -{ - if (self.shortcutValue) { - [self drawInRect:self.bounds withTitle:MASShortcutChar(self.recording ? kMASShortcutGlyphEscape : kMASShortcutGlyphDeleteLeft) - alignment:NSRightTextAlignment state:NSOffState]; - - CGRect shortcutRect; - [self getShortcutRect:&shortcutRect hintRect:NULL]; - NSString *title = (self.recording - ? (_hinting - ? NSLocalizedString(@"Use Old Shortuct", @"Cancel action button for non-empty shortcut in recording state") - : (self.shortcutPlaceholder.length > 0 - ? self.shortcutPlaceholder - : NSLocalizedString(@"Type New Shortcut", @"Non-empty shortcut button in recording state"))) - : _shortcutValue ? _shortcutValue.description : @""); - [self drawInRect:shortcutRect withTitle:title alignment:NSCenterTextAlignment state:self.isRecording ? NSOnState : NSOffState]; - } - else { - if (self.recording) - { - [self drawInRect:self.bounds withTitle:MASShortcutChar(kMASShortcutGlyphEscape) alignment:NSRightTextAlignment state:NSOffState]; - - CGRect shortcutRect; - [self getShortcutRect:&shortcutRect hintRect:NULL]; - NSString *title = (_hinting - ? NSLocalizedString(@"Cancel", @"Cancel action button in recording state") - : (self.shortcutPlaceholder.length > 0 - ? self.shortcutPlaceholder - : NSLocalizedString(@"Type Shortcut", @"Empty shortcut button in recording state"))); - [self drawInRect:shortcutRect withTitle:title alignment:NSCenterTextAlignment state:NSOnState]; - } - else - { - [self drawInRect:self.bounds withTitle:NSLocalizedString(@"Record Shortcut", @"Empty shortcut button in normal state") - alignment:NSCenterTextAlignment state:NSOffState]; - } - } -} - -#pragma mark - Mouse handling - -- (void)getShortcutRect:(CGRect *)shortcutRectRef hintRect:(CGRect *)hintRectRef -{ - CGRect shortcutRect, hintRect; - CGFloat hintButtonWidth = HINT_BUTTON_WIDTH; - switch (self.appearance) { - case MASShortcutViewAppearanceTexturedRect: hintButtonWidth += 2.0; break; - case MASShortcutViewAppearanceRounded: hintButtonWidth += 3.0; break; - default: break; - } - CGRectDivide(self.bounds, &hintRect, &shortcutRect, hintButtonWidth, CGRectMaxXEdge); - if (shortcutRectRef) *shortcutRectRef = shortcutRect; - if (hintRectRef) *hintRectRef = hintRect; -} - -- (BOOL)locationInShortcutRect:(CGPoint)location -{ - CGRect shortcutRect; - [self getShortcutRect:&shortcutRect hintRect:NULL]; - return CGRectContainsPoint(shortcutRect, [self convertPoint:location fromView:nil]); -} - -- (BOOL)locationInHintRect:(CGPoint)location -{ - CGRect hintRect; - [self getShortcutRect:NULL hintRect:&hintRect]; - return CGRectContainsPoint(hintRect, [self convertPoint:location fromView:nil]); -} - -- (void)mouseDown:(NSEvent *)event -{ - if (self.enabled) { - if (self.shortcutValue) { - if (self.recording) { - if ([self locationInHintRect:event.locationInWindow]) { - self.recording = NO; - } - } - else { - if ([self locationInShortcutRect:event.locationInWindow]) { - self.recording = YES; - } - else { - self.shortcutValue = nil; - } - } - } - else { - if (self.recording) { - if ([self locationInHintRect:event.locationInWindow]) { - self.recording = NO; - } - } - else { - self.recording = YES; - } - } - } - else { - [super mouseDown:event]; - } -} - -#pragma mark - Handling mouse over - -- (void)updateTrackingAreas -{ - [super updateTrackingAreas]; - - if (_hintArea) { - [self removeTrackingArea:_hintArea]; - _hintArea = nil; - } - - // Forbid hinting if view is disabled - if (!self.enabled) return; - - CGRect hintRect; - [self getShortcutRect:NULL hintRect:&hintRect]; - NSTrackingAreaOptions options = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingAssumeInside); - _hintArea = [[NSTrackingArea alloc] initWithRect:hintRect options:options owner:self userInfo:nil]; - [self addTrackingArea:_hintArea]; -} - -- (void)setHinting:(BOOL)flag -{ - if (_hinting != flag) { - _hinting = flag; - [self setNeedsDisplay:YES]; - } -} - -- (void)mouseEntered:(NSEvent *)event -{ - self.hinting = YES; -} - -- (void)mouseExited:(NSEvent *)event -{ - self.hinting = NO; -} - -void *kUserDataShortcut = &kUserDataShortcut; -void *kUserDataHint = &kUserDataHint; - -- (void)resetToolTips -{ - if (_shortcutToolTipTag) { - [self removeToolTip:_shortcutToolTipTag], _shortcutToolTipTag = 0; - } - if (_hintToolTipTag) { - [self removeToolTip:_hintToolTipTag], _hintToolTipTag = 0; - } - - if ((self.shortcutValue == nil) || self.recording || !self.enabled) return; - - CGRect shortcutRect, hintRect; - [self getShortcutRect:&shortcutRect hintRect:&hintRect]; - _shortcutToolTipTag = [self addToolTipRect:shortcutRect owner:self userData:kUserDataShortcut]; - _hintToolTipTag = [self addToolTipRect:hintRect owner:self userData:kUserDataHint]; -} - -- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(CGPoint)point userData:(void *)data -{ - if (data == kUserDataShortcut) { - return NSLocalizedString(@"Click to record new shortcut", @"Tooltip for non-empty shortcut button"); - } - else if (data == kUserDataHint) { - return NSLocalizedString(@"Delete shortcut", @"Tooltip for hint button near the non-empty shortcut"); - } - return nil; -} - -#pragma mark - Event monitoring - -- (void)activateEventMonitoring:(BOOL)shouldActivate -{ - static BOOL isActive = NO; - if (isActive == shouldActivate) return; - isActive = shouldActivate; - - static id eventMonitor = nil; - if (shouldActivate) { - __weak MASShortcutView *weakSelf = self; - NSEventMask eventMask = (NSKeyDownMask | NSFlagsChangedMask); - eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *event) { - - MASShortcut *shortcut = [MASShortcut shortcutWithEvent:event]; - if ((shortcut.keyCode == kVK_Delete) || (shortcut.keyCode == kVK_ForwardDelete)) { - // Delete shortcut - weakSelf.shortcutValue = nil; - weakSelf.recording = NO; - event = nil; - } - else if (shortcut.keyCode == kVK_Escape) { - // Cancel recording - weakSelf.recording = NO; - event = nil; - } - else if (shortcut.shouldBypass) { - // Command + W, Command + Q, ESC should deactivate recorder - weakSelf.recording = NO; - } - else { - // Verify possible shortcut - if (shortcut.keyCodeString.length > 0) { - if (shortcut.valid) { - // Verify that shortcut is not used - NSError *error = nil; - if ([shortcut isTakenError:&error]) { - // Prevent cancel of recording when Alert window is key - [weakSelf activateResignObserver:NO]; - [weakSelf activateEventMonitoring:NO]; - NSString *format = NSLocalizedString(@"The key combination %@ cannot be used", - @"Title for alert when shortcut is already used"); - NSRunCriticalAlertPanel([NSString stringWithFormat:format, shortcut], error.localizedDescription, - NSLocalizedString(@"OK", @"Alert button when shortcut is already used"), - nil, nil); - weakSelf.shortcutPlaceholder = nil; - [weakSelf activateResignObserver:YES]; - [weakSelf activateEventMonitoring:YES]; - } - else { - weakSelf.shortcutValue = shortcut; - weakSelf.recording = NO; - } - } - else { - // Key press with or without SHIFT is not valid input - NSBeep(); - } - } - else { - // User is playing with modifier keys - weakSelf.shortcutPlaceholder = shortcut.modifierFlagsString; - } - event = nil; - } - return event; - }]; - } - else { - [NSEvent removeMonitor:eventMonitor]; - } -} - -- (void)activateResignObserver:(BOOL)shouldActivate -{ - static BOOL isActive = NO; - if (isActive == shouldActivate) return; - isActive = shouldActivate; - - static id observer = nil; - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - if (shouldActivate) { - __weak MASShortcutView *weakSelf = self; - observer = [notificationCenter addObserverForName:NSWindowDidResignKeyNotification object:self.window - queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { - weakSelf.recording = NO; - }]; - } - else { - [notificationCenter removeObserver:observer]; - } -} - -@end |
