aboutsummaryrefslogtreecommitdiffstats
path: root/Demo
diff options
context:
space:
mode:
Diffstat (limited to 'Demo')
-rw-r--r--Demo/AppDelegate.m89
-rw-r--r--Demo/MainMenu.xib58
2 files changed, 125 insertions, 22 deletions
diff --git a/Demo/AppDelegate.m b/Demo/AppDelegate.m
index 5c1c3f7..fd8d307 100644
--- a/Demo/AppDelegate.m
+++ b/Demo/AppDelegate.m
@@ -1,7 +1,14 @@
#import "AppDelegate.h"
+static NSString *const MASCustomShortcutKey = @"customShortcut";
+static NSString *const MASCustomShortcutEnabledKey = @"customShortcutEnabled";
+static NSString *const MASHardcodedShortcutEnabledKey = @"hardcodedShortcutEnabled";
+
+static void *MASObservingContext = &MASObservingContext;
+
@interface AppDelegate ()
-@property (nonatomic, assign) IBOutlet MASShortcutView *shortcutView;
+@property(strong) IBOutlet MASShortcutView *customShortcutView;
+@property(strong) IBOutlet NSTextField *feedbackTextField;
@end
@implementation AppDelegate
@@ -10,20 +17,80 @@
{
[super awakeFromNib];
- static NSString *const ShortcutKey = @"customShortcut";
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+
+ // Register default values to be used for the first app start
+ [defaults registerDefaults:@{
+ MASHardcodedShortcutEnabledKey : @YES,
+ MASCustomShortcutEnabledKey : @YES,
+ }];
// Bind the shortcut recorder view’s value to user defaults.
// Run “defaults read com.shpakovski.mac.Demo” to see what’s stored
// in user defaults.
- [_shortcutView setAssociatedUserDefaultsKey:ShortcutKey];
-
- // Play a ping sound when the shortcut stored in user defaults is pressed.
- // Note that when the shortcut stored in user defaults changes, you don’t have
- // to update anything: the old shortcut will automatically stop working and
- // the sound will play after pressing the new one.
- [[MASShortcutBinder sharedBinder] bindShortcutWithDefaultsKey:ShortcutKey toAction:^{
- [[NSSound soundNamed:@"Ping"] play];
- }];
+ [_customShortcutView setAssociatedUserDefaultsKey:MASCustomShortcutKey];
+
+ // Enable or disable the recorder view according to the first checkbox state
+ [_customShortcutView bind:@"enabled" toObject:defaults
+ withKeyPath:MASCustomShortcutEnabledKey options:nil];
+
+ // Watch user defaults for changes in the checkbox states
+ [defaults addObserver:self forKeyPath:MASCustomShortcutEnabledKey
+ options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew
+ context:MASObservingContext];
+ [defaults addObserver:self forKeyPath:MASHardcodedShortcutEnabledKey
+ options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew
+ context:MASObservingContext];
+}
+
+- (void) playShortcutFeedback
+{
+ [[NSSound soundNamed:@"Ping"] play];
+ [_feedbackTextField setStringValue:@"Shortcut pressed!"];
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ [_feedbackTextField setStringValue:@""];
+ });
+}
+
+// Handle changes in user defaults. We have to check keyPath here to see which of the
+// two checkboxes was changed. This is not very elegant, in practice you could use something
+// like https://github.com/facebook/KVOController with a nicer API.
+- (void) observeValueForKeyPath: (NSString*) keyPath ofObject: (id) object change: (NSDictionary*) change context: (void*) context
+{
+ if (context != MASObservingContext) {
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+ return;
+ }
+
+ BOOL newValue = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
+ if ([keyPath isEqualToString:MASCustomShortcutEnabledKey]) {
+ [self setCustomShortcutEnabled:newValue];
+ } else if ([keyPath isEqualToString:MASHardcodedShortcutEnabledKey]) {
+ [self setHardcodedShortcutEnabled:newValue];
+ }
+}
+
+- (void) setCustomShortcutEnabled: (BOOL) enabled
+{
+ if (enabled) {
+ [[MASShortcutBinder sharedBinder] bindShortcutWithDefaultsKey:MASCustomShortcutKey toAction:^{
+ [self playShortcutFeedback];
+ }];
+ } else {
+ [[MASShortcutBinder sharedBinder] breakBindingWithDefaultsKey:MASCustomShortcutKey];
+ }
+}
+
+- (void) setHardcodedShortcutEnabled: (BOOL) enabled
+{
+ MASShortcut *shortcut = [MASShortcut shortcutWithKeyCode:kVK_ANSI_Keypad2 modifierFlags:NSCommandKeyMask];
+ if (enabled) {
+ [[MASShortcutMonitor sharedMonitor] registerShortcut:shortcut withAction:^{
+ [self playShortcutFeedback];
+ }];
+ } else {
+ [[MASShortcutMonitor sharedMonitor] unregisterShortcut:shortcut];
+ }
}
#pragma mark NSApplicationDelegate
diff --git a/Demo/MainMenu.xib b/Demo/MainMenu.xib
index 488dea2..3d99587 100644
--- a/Demo/MainMenu.xib
+++ b/Demo/MainMenu.xib
@@ -649,39 +649,75 @@
</menu>
<window title="Demo" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="DemoWindow" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
- <rect key="contentRect" x="335" y="390" width="290" height="171"/>
+ <rect key="contentRect" x="335" y="390" width="385" height="129"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/>
<view key="contentView" id="372">
- <rect key="frame" x="0.0" y="0.0" width="290" height="171"/>
+ <rect key="frame" x="0.0" y="0.0" width="385" height="129"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="536" customClass="MASShortcutView">
- <rect key="frame" x="20" y="102" width="250" height="19"/>
+ <rect key="frame" x="142" y="90" width="158" height="19"/>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PG0-jh-Onh">
- <rect key="frame" x="18" y="134" width="119" height="17"/>
- <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Record a shortcut:" id="85u-1A-n7H">
+ <rect key="frame" x="18" y="92" width="111" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Custom shortcut:" id="85u-1A-n7H">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
- <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ieo-bz-mir">
- <rect key="frame" x="18" y="23" width="254" height="68"/>
- <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" id="WDe-Rt-e8p">
+ <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zCi-ki-Uuh">
+ <rect key="frame" x="140" y="63" width="169" height="18"/>
+ <buttonCell key="cell" type="check" title="Enable custom shortcut" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Y47-p3-sDa">
+ <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <binding destination="rCO-Ve-DT5" name="value" keyPath="values.customShortcutEnabled" id="VjS-3V-VdA"/>
+ </connections>
+ </button>
+ <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KnS-ut-phz">
+ <rect key="frame" x="18" y="65" width="111" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Options:" id="cUE-gA-heG">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F4r-KM-wn9">
+ <rect key="frame" x="140" y="43" width="227" height="18"/>
+ <buttonCell key="cell" type="check" title="Enable hard-coded shortcut (⌘2)" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="7gv-jN-44g">
+ <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <binding destination="rCO-Ve-DT5" name="value" keyPath="values.hardcodedShortcutEnabled" id="dlZ-si-HeN"/>
+ </connections>
+ </button>
+ <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9fB-XS-8pK">
+ <rect key="frame" x="18" y="20" width="111" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Feedback:" id="Zbz-mV-NDc">
<font key="font" metaFont="system"/>
- <string key="title">After recording a shortcut, press it to play a sound. Notice that the shortcut is played even when the demo app is not in the foreground.</string>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
+ <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Aso-dH-W8I">
+ <rect key="frame" x="140" y="20" width="211" height="17"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" placeholderString="Press a shortcut to see feedback" id="Ckx-v7-e6x">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" red="1" green="0.14901961389999999" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+ <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
</subviews>
</view>
- <point key="canvasLocation" x="297" y="335.5"/>
+ <point key="canvasLocation" x="348.5" y="367.5"/>
</window>
<customObject id="494" customClass="AppDelegate">
<connections>
- <outlet property="shortcutView" destination="536" id="548"/>
+ <outlet property="customShortcutView" destination="536" id="aO6-hh-1vm"/>
+ <outlet property="feedbackTextField" destination="Aso-dH-W8I" id="hk8-xL-ieC"/>
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>