From d0f4d54bb9eb66cbd19fa4dabb56fc09f42bd22d Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Sun, 3 Mar 2013 23:49:27 +0100 Subject: [PATCH 01/16] Rename the application delegate, and hopefully catch the last vestiges of the old names. --- English.lproj/MainMenu.xib | 231 +----------------- Enjoyable.xcodeproj/project.pbxproj | 78 +++--- ...roller.h => EnjoyableApplicationDelegate.h | 8 +- ...roller.m => EnjoyableApplicationDelegate.m | 60 +++-- NJInputController.h => NJDeviceController.h | 4 +- NJInputController.m => NJDeviceController.m | 12 +- NJMappingsController.m | 12 +- NJOutput.h | 4 +- NJOutput.m | 2 +- NJOutputController.h | 4 +- NJOutputController.m | 2 +- NJOutputMapping.m | 4 +- NJOutputMouseMove.m | 4 +- NJOutputMouseScroll.m | 2 +- NJOutputSwitchMouseMode.m | 8 +- 15 files changed, 107 insertions(+), 328 deletions(-) rename ApplicationController.h => EnjoyableApplicationDelegate.h (73%) rename ApplicationController.m => EnjoyableApplicationDelegate.m (72%) rename NJInputController.h => NJDeviceController.h (84%) rename NJInputController.m => NJDeviceController.m (96%) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 8dd62bf..1a87bd7 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -1125,13 +1125,13 @@ - ApplicationController + EnjoyableApplicationDelegate NJMappingsController - NJInputController + NJDeviceController NJOutputController @@ -2237,147 +2237,6 @@ - - ApplicationController - NSObject - - toggleActivity: - id - - - toggleActivity: - - toggleActivity: - id - - - - NSToolbarItem - NSMenuItem - ConfigsController - NSMenu - NSDrawer - JoystickController - NSWindow - TargetController - - - - activeButton - NSToolbarItem - - - activeMenuItem - NSMenuItem - - - configsController - ConfigsController - - - dockMenuBase - NSMenu - - - drawer - NSDrawer - - - jsController - JoystickController - - - mainWindow - NSWindow - - - targetController - TargetController - - - - IBProjectSource - ./Classes/ApplicationController.h - - - - ConfigsController - NSObject - - id - id - id - id - - - - addPressed: - id - - - exportPressed: - id - - - importPressed: - id - - - removePressed: - id - - - - NSButton - NSTableView - TargetController - - - - removeButton - NSButton - - - tableView - NSTableView - - - targetController - TargetController - - - - IBProjectSource - ./Classes/ConfigsController.h - - - - JoystickController - NSObject - - ConfigsController - NSOutlineView - TargetController - - - - configsController - ConfigsController - - - outlineView - NSOutlineView - - - targetController - TargetController - - - - IBProjectSource - ./Classes/JoystickController.h - - NJKeyInputField NSTextField @@ -2397,92 +2256,6 @@ ./Classes/NJKeyInputField.h - - TargetController - NSObject - - id - id - id - id - id - - - - configChosen: - id - - - mbtnChanged: - id - - - mdirChanged: - id - - - radioChanged: - id - - - sdirChanged: - id - - - - NSPopUpButton - ConfigsController - JoystickController - NJKeyInputField - NSSegmentedControl - NSSegmentedControl - NSMatrix - NSSegmentedControl - NSTextField - - - - configPopup - NSPopUpButton - - - configsController - ConfigsController - - - joystickController - JoystickController - - - keyInput - NJKeyInputField - - - mouseBtnSelect - NSSegmentedControl - - - mouseDirSelect - NSSegmentedControl - - - radioButtons - NSMatrix - - - scrollDirSelect - NSSegmentedControl - - - title - NSTextField - - - - IBProjectSource - ./Classes/TargetController.h - - 0 diff --git a/Enjoyable.xcodeproj/project.pbxproj b/Enjoyable.xcodeproj/project.pbxproj index c633833..ccdd256 100644 --- a/Enjoyable.xcodeproj/project.pbxproj +++ b/Enjoyable.xcodeproj/project.pbxproj @@ -27,9 +27,9 @@ D5617FE70FAFDB5800928B3A /* NJKeyInputField.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617FE60FAFDB5800928B3A /* NJKeyInputField.m */; }; D594BE860FAE6219007A85F2 /* NJDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BE850FAE6219007A85F2 /* NJDevice.m */; }; D594BE8A0FAE64AD007A85F2 /* NJInput.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BE890FAE64AD007A85F2 /* NJInput.m */; }; - D594BEF90FAE6FF2007A85F2 /* NJInputController.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BEF80FAE6FF2007A85F2 /* NJInputController.m */; }; + D594BEF90FAE6FF2007A85F2 /* NJDeviceController.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BEF80FAE6FF2007A85F2 /* NJDeviceController.m */; }; D594BF000FAE7397007A85F2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D594BEFF0FAE7397007A85F2 /* IOKit.framework */; }; - D594BF830FAE9661007A85F2 /* ApplicationController.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BF820FAE9661007A85F2 /* ApplicationController.m */; }; + D594BF830FAE9661007A85F2 /* EnjoyableApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BF820FAE9661007A85F2 /* EnjoyableApplicationDelegate.m */; }; D5F809710FB093400006A4DE /* NJOutputMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = D5F809700FB093400006A4DE /* NJOutputMapping.m */; }; D5F80A9D0FB0A2FF0006A4DE /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = D5617A080FAEAF8300928B3A /* icon.icns */; }; EE1D7C9216E01E7000B000EB /* NSView+FirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */; }; @@ -78,11 +78,11 @@ D594BE850FAE6219007A85F2 /* NJDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJDevice.m; sourceTree = ""; }; D594BE880FAE64AD007A85F2 /* NJInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJInput.h; sourceTree = ""; }; D594BE890FAE64AD007A85F2 /* NJInput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJInput.m; sourceTree = ""; }; - D594BEF70FAE6FF2007A85F2 /* NJInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJInputController.h; sourceTree = ""; }; - D594BEF80FAE6FF2007A85F2 /* NJInputController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJInputController.m; sourceTree = ""; }; + D594BEF70FAE6FF2007A85F2 /* NJDeviceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJDeviceController.h; sourceTree = ""; }; + D594BEF80FAE6FF2007A85F2 /* NJDeviceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJDeviceController.m; sourceTree = ""; }; D594BEFF0FAE7397007A85F2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; - D594BF810FAE9661007A85F2 /* ApplicationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationController.h; sourceTree = ""; }; - D594BF820FAE9661007A85F2 /* ApplicationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ApplicationController.m; sourceTree = ""; }; + D594BF810FAE9661007A85F2 /* EnjoyableApplicationDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnjoyableApplicationDelegate.h; sourceTree = ""; }; + D594BF820FAE9661007A85F2 /* EnjoyableApplicationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EnjoyableApplicationDelegate.m; sourceTree = ""; }; D5F8096F0FB093400006A4DE /* NJOutputMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJOutputMapping.h; sourceTree = ""; }; D5F809700FB093400006A4DE /* NJOutputMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJOutputMapping.m; sourceTree = ""; }; EE1D7C9016E01E7000B000EB /* NSView+FirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+FirstResponder.h"; sourceTree = ""; }; @@ -109,44 +109,43 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( - D5617D290FAF579A00928B3A /* NJInputAnalog.h */, - D5617D2A0FAF579A00928B3A /* NJInputAnalog.m */, + D594BF810FAE9661007A85F2 /* EnjoyableApplicationDelegate.h */, + D594BF820FAE9661007A85F2 /* EnjoyableApplicationDelegate.m */, + D594BEF70FAE6FF2007A85F2 /* NJDeviceController.h */, + D594BEF80FAE6FF2007A85F2 /* NJDeviceController.m */, + D5617A340FAEB74000928B3A /* NJMappingsController.h */, + D5617A350FAEB74000928B3A /* NJMappingsController.m */, + D5617FE20FAFD7B000928B3A /* NJOutputController.h */, + D5617FE30FAFD7B000928B3A /* NJOutputController.m */, + D5617FE50FAFDB5800928B3A /* NJKeyInputField.h */, + D5617FE60FAFDB5800928B3A /* NJKeyInputField.m */, + D5617A370FAEBA1800928B3A /* NJMapping.h */, + D5617A380FAEBA1800928B3A /* NJMapping.m */, D594BE840FAE6219007A85F2 /* NJDevice.h */, D594BE850FAE6219007A85F2 /* NJDevice.m */, + EEF86B7316E2241000674B87 /* NJInputPathElement.h */, D594BE880FAE64AD007A85F2 /* NJInput.h */, D594BE890FAE64AD007A85F2 /* NJInput.m */, - D5617D240FAF579300928B3A /* NJInputHat.h */, - D5617D250FAF579300928B3A /* NJInputHat.m */, + D5617D290FAF579A00928B3A /* NJInputAnalog.h */, + D5617D2A0FAF579A00928B3A /* NJInputAnalog.m */, D5617D180FAF568100928B3A /* NJInputButton.h */, D5617D190FAF568100928B3A /* NJInputButton.m */, - D594BEF70FAE6FF2007A85F2 /* NJInputController.h */, - D594BEF80FAE6FF2007A85F2 /* NJInputController.m */, - D594BF810FAE9661007A85F2 /* ApplicationController.h */, - D594BF820FAE9661007A85F2 /* ApplicationController.m */, - D5617A340FAEB74000928B3A /* NJMappingsController.h */, - D5617A350FAEB74000928B3A /* NJMappingsController.m */, - D5617A370FAEBA1800928B3A /* NJMapping.h */, - D5617A380FAEBA1800928B3A /* NJMapping.m */, - D5F8096F0FB093400006A4DE /* NJOutputMapping.h */, - D5F809700FB093400006A4DE /* NJOutputMapping.m */, + D5617D240FAF579300928B3A /* NJInputHat.h */, + D5617D250FAF579300928B3A /* NJInputHat.m */, D5617FD40FAFD06000928B3A /* NJOutput.h */, D5617FD50FAFD06000928B3A /* NJOutput.m */, D5617FD70FAFD1E600928B3A /* NJOutputKeyPress.h */, D5617FD80FAFD1E600928B3A /* NJOutputKeyPress.m */, - D5617FE20FAFD7B000928B3A /* NJOutputController.h */, - D5617FE30FAFD7B000928B3A /* NJOutputController.m */, - D5617FE50FAFDB5800928B3A /* NJKeyInputField.h */, - D5617FE60FAFDB5800928B3A /* NJKeyInputField.m */, - 8BD9B54115C230FE00929C5D /* NJOutputMouseMove.h */, - 8BD9B54215C230FE00929C5D /* NJOutputMouseMove.m */, + D5F8096F0FB093400006A4DE /* NJOutputMapping.h */, + D5F809700FB093400006A4DE /* NJOutputMapping.m */, 8B7E476A15C314A200C588FA /* NJOutputMouseButton.h */, 8B7E476B15C314A200C588FA /* NJOutputMouseButton.m */, + 8BD9B54115C230FE00929C5D /* NJOutputMouseMove.h */, + 8BD9B54215C230FE00929C5D /* NJOutputMouseMove.m */, 8BEFAD9A15C46BFF00823AEC /* NJOutputMouseScroll.h */, 8BEFAD9B15C46BFF00823AEC /* NJOutputMouseScroll.m */, 8BEFAD9E15C476DC00823AEC /* NJOutputSwitchMouseMode.h */, 8BEFAD9F15C476DC00823AEC /* NJOutputSwitchMouseMode.m */, - EEF86B7316E2241000674B87 /* NJInputPathElement.h */, - EEF86B7416E298CD00674B87 /* NJEvents.h */, ); name = Classes; sourceTree = ""; @@ -181,6 +180,7 @@ isa = PBXGroup; children = ( 080E96DDFE201D6D7F000001 /* Classes */, + EE1D5F8B16E403D600749C36 /* Categories */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, @@ -192,12 +192,9 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( - 32CA4F630368D1EE00C91783 /* Enjoyable_Prefix.pch */, 29B97316FDCFA39411CA2CEA /* main.m */, - EE1D7C9416E0ECCF00B000EB /* NSError+Description.h */, - EE1D7C9516E0ECCF00B000EB /* NSError+Description.m */, - EE1D7C9016E01E7000B000EB /* NSView+FirstResponder.h */, - EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */, + EEF86B7416E298CD00674B87 /* NJEvents.h */, + 32CA4F630368D1EE00C91783 /* Enjoyable_Prefix.pch */, ); name = "Other Sources"; sourceTree = ""; @@ -223,6 +220,17 @@ name = Frameworks; sourceTree = ""; }; + EE1D5F8B16E403D600749C36 /* Categories */ = { + isa = PBXGroup; + children = ( + EE1D7C9416E0ECCF00B000EB /* NSError+Description.h */, + EE1D7C9516E0ECCF00B000EB /* NSError+Description.m */, + EE1D7C9016E01E7000B000EB /* NSView+FirstResponder.h */, + EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */, + ); + name = Categories; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -293,8 +301,8 @@ 8D11072D0486CEB800E47090 /* main.m in Sources */, D594BE860FAE6219007A85F2 /* NJDevice.m in Sources */, D594BE8A0FAE64AD007A85F2 /* NJInput.m in Sources */, - D594BEF90FAE6FF2007A85F2 /* NJInputController.m in Sources */, - D594BF830FAE9661007A85F2 /* ApplicationController.m in Sources */, + D594BEF90FAE6FF2007A85F2 /* NJDeviceController.m in Sources */, + D594BF830FAE9661007A85F2 /* EnjoyableApplicationDelegate.m in Sources */, D5617A360FAEB74000928B3A /* NJMappingsController.m in Sources */, D5617A390FAEBA1800928B3A /* NJMapping.m in Sources */, D5617D1A0FAF568100928B3A /* NJInputButton.m in Sources */, diff --git a/ApplicationController.h b/EnjoyableApplicationDelegate.h similarity index 73% rename from ApplicationController.h rename to EnjoyableApplicationDelegate.h index a1b8742..6a198e6 100644 --- a/ApplicationController.h +++ b/EnjoyableApplicationDelegate.h @@ -1,16 +1,16 @@ // -// ApplicationController.h +// EnjoyableApplicationDelegate.h // Enjoy // // Created by Sam McCall on 4/05/09. // Copyright 2009 University of Otago. All rights reserved. // -@class NJInputController; +@class NJDeviceController; @class NJOutputController; @class NJMappingsController; -@interface ApplicationController : NSObject { +@interface EnjoyableApplicationDelegate : NSObject { IBOutlet NSDrawer *drawer; IBOutlet NSWindow *mainWindow; IBOutlet NSToolbarItem *activeButton; @@ -18,7 +18,7 @@ IBOutlet NSMenu *dockMenuBase; } -@property (nonatomic, strong) IBOutlet NJInputController *inputController; +@property (nonatomic, strong) IBOutlet NJDeviceController *inputController; @property (nonatomic, strong) IBOutlet NJOutputController *outputController; @property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController; diff --git a/ApplicationController.m b/EnjoyableApplicationDelegate.m similarity index 72% rename from ApplicationController.m rename to EnjoyableApplicationDelegate.m index faad07a..23324d3 100644 --- a/ApplicationController.m +++ b/EnjoyableApplicationDelegate.m @@ -1,20 +1,20 @@ // -// ApplicationController.m +// EnjoyableApplicationDelegate.m // Enjoy // // Created by Sam McCall on 4/05/09. // -#import "ApplicationController.h" +#import "EnjoyableApplicationDelegate.h" #import "NJMapping.h" #import "NJMappingsController.h" -#import "NJInputController.h" +#import "NJDeviceController.h" #import "NJOutputController.h" #import "NJEvents.h" -@implementation ApplicationController { - BOOL active; +@implementation EnjoyableApplicationDelegate { + NSInteger mappingsMenuIndex; } - (void)didSwitchApplication:(NSNotification *)notification { @@ -23,25 +23,30 @@ } - (void)applicationDidFinishLaunching:(NSNotification *)notification { + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(mappingDidChange:) + name:NJEventMappingChanged + object:nil]; + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(eventTranslationActivated:) + name:NJEventTranslationActivated + object:nil]; + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(eventTranslationDeactivated:) + name:NJEventTranslationDeactivated + object:nil]; + + mappingsMenuIndex = dockMenuBase.numberOfItems; + while (![dockMenuBase itemAtIndex:mappingsMenuIndex - 1].isSeparatorItem) + --mappingsMenuIndex; + [drawer open]; self.outputController.enabled = NO; [self.inputController setup]; [self.mappingsController load]; - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(mappingDidChange:) - name:NJEventMappingChanged - object:nil]; - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(eventTranslationActivated:) - name:NJEventTranslationActivated - object:nil]; - [NSNotificationCenter.defaultCenter - addObserver:self - selector:@selector(eventTranslationDeactivated:) - name:NJEventTranslationDeactivated - object:nil]; } - (void)applicationWillTerminate:(NSNotification *)aNotification { @@ -73,15 +78,8 @@ self.inputController.translatingEvents = !self.inputController.translatingEvents; } -- (NSInteger)firstMappingMenuIndex { - for (NSInteger i = dockMenuBase.numberOfItems - 1; i >= 0; --i) - if ([dockMenuBase itemAtIndex:i].isSeparatorItem) - return i + 1; - return dockMenuBase.numberOfItems; -} - - (void)mappingsChanged { - NSInteger removeFrom = self.firstMappingMenuIndex; + NSInteger removeFrom = mappingsMenuIndex; while (dockMenuBase.numberOfItems > removeFrom) [dockMenuBase removeItemAtIndex:dockMenuBase.numberOfItems - 1]; int added = 0; @@ -96,16 +94,16 @@ } - (void)mappingDidChange:(NSNotification *)note { - NSInteger firstMapping = self.firstMappingMenuIndex; NJMapping *current = note.object; NSArray *mappings = self.mappingsController.mappings; for (NSUInteger i = 0; i < mappings.count; ++i) - [dockMenuBase itemAtIndex:i + firstMapping].state = mappings[i] == current; + [dockMenuBase itemAtIndex:i + mappingsMenuIndex].state = mappings[i] == current; } - (void)chooseMapping:(id)sender { - NSInteger idx = [dockMenuBase indexOfItem:sender] - self.firstMappingMenuIndex; + NSInteger idx = [dockMenuBase indexOfItem:sender] - mappingsMenuIndex; NJMapping *chosen = self.mappingsController.mappings[idx]; [_mappingsController activateMapping:chosen]; } + @end diff --git a/NJInputController.h b/NJDeviceController.h similarity index 84% rename from NJInputController.h rename to NJDeviceController.h index fdd0532..2769222 100644 --- a/NJInputController.h +++ b/NJDeviceController.h @@ -1,5 +1,5 @@ // -// NJInputController.h +// NJDeviceController.h // Enjoy // // Created by Sam McCall on 4/05/09. @@ -11,7 +11,7 @@ @class NJMappingsController; @class NJOutputController; -@interface NJInputController : NSObject { +@interface NJDeviceController : NSObject { IBOutlet NSOutlineView *outlineView; IBOutlet NJOutputController *outputController; IBOutlet NJMappingsController *mappingsController; diff --git a/NJInputController.m b/NJDeviceController.m similarity index 96% rename from NJInputController.m rename to NJDeviceController.m index 618e99b..e68cfdb 100644 --- a/NJInputController.m +++ b/NJDeviceController.m @@ -1,11 +1,11 @@ // -// NJInputController.h +// NJDeviceController.m // Enjoy // // Created by Sam McCall on 4/05/09. // -#import "NJInputController.h" +#import "NJDeviceController.h" #import "NJMapping.h" #import "NJMappingsController.h" @@ -15,7 +15,7 @@ #import "NJOutputController.h" #import "NJEvents.h" -@implementation NJInputController { +@implementation NJDeviceController { IOHIDManagerRef hidManager; NSTimer *continuousTimer; NSMutableArray *runningOutputs; @@ -83,7 +83,7 @@ } static void input_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDValueRef value) { - NJInputController *controller = (__bridge NJInputController *)ctx; + NJDeviceController *controller = (__bridge NJDeviceController *)ctx; IOHIDDeviceRef device = IOHIDQueueGetDevice(inSender); if (controller.translatingEvents) { @@ -116,7 +116,7 @@ static int findAvailableIndex(NSArray *list, NJDevice *dev) { } static void add_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) { - NJInputController *controller = (__bridge NJInputController *)ctx; + NJDeviceController *controller = (__bridge NJDeviceController *)ctx; [controller addDeviceForDevice:device]; } @@ -128,7 +128,7 @@ static void add_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDevi } static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) { - NJInputController *controller = (__bridge NJInputController *)ctx; + NJDeviceController *controller = (__bridge NJDeviceController *)ctx; [controller removeDeviceForDevice:device]; } diff --git a/NJMappingsController.m b/NJMappingsController.m index e01cb91..fe96462 100644 --- a/NJMappingsController.m +++ b/NJMappingsController.m @@ -7,7 +7,7 @@ #import "NJMappingsController.h" -#import "ApplicationController.h" +#import "EnjoyableApplicationDelegate.h" #import "NJMapping.h" #import "NJMappingsController.h" #import "NJOutput.h" @@ -62,7 +62,7 @@ - (IBAction)addPressed:(id)sender { NJMapping *newMapping = [[NJMapping alloc] initWithName:@"Untitled"]; [_mappings addObject:newMapping]; - [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged]; + [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; [tableView reloadData]; [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_mappings.count - 1] byExtendingSelection:NO]; [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES]; @@ -75,7 +75,7 @@ [_mappings removeObjectAtIndex:tableView.selectedRow]; [tableView reloadData]; - [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged]; + [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; [self activateMapping:_mappings[0]]; [self save]; } @@ -92,7 +92,7 @@ - (void)tableView:(NSTableView *)view setObjectValue:(NSString *)obj forTableColumn:(NSTableColumn *)col row:(NSInteger)index { [(NJMapping *)_mappings[index] setName:obj]; [tableView reloadData]; - [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged]; + [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { @@ -147,7 +147,7 @@ current = 0; _mappings = newMappings; [tableView reloadData]; - [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged]; + [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; [self activateMapping:_mappings[current]]; } } @@ -234,7 +234,7 @@ } [self save]; - [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged]; + [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; [self activateMapping:mapping]; [outputController loadCurrent]; diff --git a/NJOutput.h b/NJOutput.h index 2bfc167..b82c4e7 100644 --- a/NJOutput.h +++ b/NJOutput.h @@ -6,7 +6,7 @@ // Copyright 2009 University of Otago. All rights reserved. // -@class NJInputController; +@class NJDeviceController; @interface NJOutput : NSObject @@ -16,7 +16,7 @@ - (void)trigger; - (void)untrigger; -- (BOOL)update:(NJInputController *)jc; +- (BOOL)update:(NJDeviceController *)jc; - (NSDictionary *)serialize; + (NJOutput *)outputDeserialize:(NSDictionary *)serialization diff --git a/NJOutput.m b/NJOutput.m index dd751e1..ab29ed8 100644 --- a/NJOutput.m +++ b/NJOutput.m @@ -63,7 +63,7 @@ - (void)untrigger { } -- (BOOL)update:(NJInputController *)jc { +- (BOOL)update:(NJDeviceController *)jc { return NO; } diff --git a/NJOutputController.h b/NJOutputController.h index bf590a6..5b9a749 100644 --- a/NJOutputController.h +++ b/NJOutputController.h @@ -9,7 +9,7 @@ #import "NJKeyInputField.h" @class NJMappingsController; -@class NJInputController; +@class NJDeviceController; @class NJOutput; @class NJOutputMouseMove; @@ -22,7 +22,7 @@ IBOutlet NSTextField *title; IBOutlet NSPopUpButton *mappingPopup; IBOutlet NJMappingsController *mappingsController; - IBOutlet NJInputController *inputController; + IBOutlet NJDeviceController *inputController; } @property (assign) BOOL enabled; diff --git a/NJOutputController.m b/NJOutputController.m index f05c615..6725125 100644 --- a/NJOutputController.m +++ b/NJOutputController.m @@ -10,7 +10,7 @@ #import "NJMappingsController.h" #import "NJMapping.h" #import "NJInput.h" -#import "NJInputController.h" +#import "NJDeviceController.h" #import "NJKeyInputField.h" #import "NJOutputMapping.h" #import "NJOutputController.h" diff --git a/NJOutputMapping.m b/NJOutputMapping.m index e411172..5cd5d9f 100644 --- a/NJOutputMapping.m +++ b/NJOutputMapping.m @@ -7,7 +7,7 @@ #import "NJOutputMapping.h" -#import "ApplicationController.h" +#import "EnjoyableApplicationDelegate.h" #import "NJMapping.h" #import "NJMappingsController.h" @@ -37,7 +37,7 @@ } - (void)trigger { - ApplicationController *ctrl = NSApplication.sharedApplication.delegate; + EnjoyableApplicationDelegate *ctrl = NSApplication.sharedApplication.delegate; [ctrl.mappingsController activateMapping:_mapping]; } diff --git a/NJOutputMouseMove.m b/NJOutputMouseMove.m index 5e59d4e..3346fb2 100644 --- a/NJOutputMouseMove.m +++ b/NJOutputMouseMove.m @@ -7,7 +7,7 @@ #import "NJOutputMouseMove.h" -#import "NJInputController.h" +#import "NJDeviceController.h" @implementation NJOutputMouseMove { int sign; @@ -32,7 +32,7 @@ return output; } -- (BOOL)update:(NJInputController *)jc { +- (BOOL)update:(NJDeviceController *)jc { if (fabsf(self.magnitude) < 0.01) { sign = 0; return NO; // dead zone diff --git a/NJOutputMouseScroll.m b/NJOutputMouseScroll.m index 9057125..2f6d2d6 100644 --- a/NJOutputMouseScroll.m +++ b/NJOutputMouseScroll.m @@ -37,7 +37,7 @@ } } -- (BOOL)update:(NJInputController *)jc { +- (BOOL)update:(NJDeviceController *)jc { if (fabsf(self.magnitude) < 0.01f) { sign = 0; return NO; // dead zone diff --git a/NJOutputSwitchMouseMode.m b/NJOutputSwitchMouseMode.m index 3332a91..1750869 100644 --- a/NJOutputSwitchMouseMode.m +++ b/NJOutputSwitchMouseMode.m @@ -7,8 +7,8 @@ #import "NJOutputSwitchMouseMode.h" -#import "ApplicationController.h" -#import "NJInputController.h" +#import "EnjoyableApplicationDelegate.h" +#import "NJDeviceController.h" @implementation NJOutputSwitchMouseMode @@ -27,8 +27,8 @@ - (void)trigger { // FIXME: It's hacky to get at the controller this way, but it's // also hacky to pass it. Shouldn't need to do either. - ApplicationController *ac = NSApplication.sharedApplication.delegate; - NJInputController *jc = ac.inputController; + EnjoyableApplicationDelegate *ac = NSApplication.sharedApplication.delegate; + NJDeviceController *jc = ac.inputController; jc.frontWindowOnly = !jc.frontWindowOnly; } -- 2.20.1 From ca998dd950f0b1900b21dc05cf57987d09b4e70e Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 13:52:00 +0100 Subject: [PATCH 02/16] Rework toolbar UI. No more drawer, use a popover. No more weird toggle button, use a segmented control. Swap sides. --- English.lproj/MainMenu.xib | 684 +++++++++++++++++++++++++-------- EnjoyableApplicationDelegate.h | 4 - EnjoyableApplicationDelegate.m | 23 +- NJDeviceController.h | 9 +- NJDeviceController.m | 6 + NJMappingsController.h | 18 +- NJMappingsController.m | 28 +- NJOutputController.m | 4 +- 8 files changed, 587 insertions(+), 189 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 1a87bd7..2e2b440 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -16,13 +16,13 @@ NSButtonCell NSCustomObject NSCustomView - NSDrawer NSMatrix NSMenu NSMenuItem NSOutlineView NSPopUpButton NSPopUpButtonCell + NSPopover NSScrollView NSScroller NSSegmentedCell @@ -36,6 +36,7 @@ NSToolbarFlexibleSpaceItem NSToolbarItem NSView + NSViewController NSWindowTemplate @@ -319,50 +320,116 @@ YES NO YES - 1 - 2 + 2 + 1 - + - 42CA6E7F-AC4A-4681-98B6-B9901269E463 + 4AC66688-76E8-47ED-AC0A-7462220A4019 - - Start/Stop - - - - NSImage - NSGoRightTemplate + Custom View + Custom View + + + + 268 + {{0, 14}, {140, 25}} + + + _NS:9 + YES + + -2080374784 + 134217728 + (default) + + LucidaGrande + 13 + 1044 + + _NS:9 + + -2034483200 + 163 + + NSImage + NSListViewTemplate + + + + 400 + 75 + + NO + - {0, 0} - {0, 0} + {13, 25} + {141, 25} YES - YES - -1 + NO + 0 YES 0 - + - A03535DA-B573-44B2-86A0-5E261E68FC16 + 94389EFE-310F-4DB5-95F6-D4AEE8839979 - - Configurations - - - - NSImage - NSListViewTemplate + Custom View + Custom View + + + + 268 + {{5, 14}, {67, 25}} + + + _NS:9 + YES + + 67108864 + 0 + + _NS:9 + + + + 32 + + NSImage + NSPathTemplate + + + Show and remap inputs + YES + 0 + + + 32 + + NSImage + NSActionTemplate + + + Run mapped actions + 1 + 0 + + + 4 + + NO + - {0, 0} - {0, 0} + {67, 25} + {67, 25} YES YES - -1 + 0 YES 0 @@ -394,22 +461,22 @@ - - - + + + - + - + {640, 300} - + 256 @@ -433,7 +500,8 @@ 256 {200, 298} - + + YES NO YES @@ -474,11 +542,7 @@ 67108928 2624 Text Cell - - LucidaGrande - 13 - 1044 - + 6 @@ -532,6 +596,7 @@ {{1, 1}, {200, 298}} + @@ -542,6 +607,7 @@ -2147483392 {{1, 1}, {8, 298}} + NO @@ -553,6 +619,7 @@ -2147483392 {{-100, -100}, {473, 15}} + NO 1 @@ -563,7 +630,8 @@ {202, 300} - + + 150034 @@ -576,6 +644,7 @@ {202, 300} + NSView @@ -588,6 +657,7 @@ 265 {{227, 123}, {180, 24}} + _NS:9 YES @@ -624,6 +694,7 @@ 265 {{227, 55}, {180, 24}} + _NS:9 YES @@ -655,6 +726,7 @@ 265 {{227, 89}, {180, 24}} + _NS:9 YES @@ -687,6 +759,7 @@ 265 {{229, 190}, {176, 24}} + _NS:9 NJKeyInputField @@ -696,6 +769,7 @@ 265 {{226, 156}, {182, 26}} + YES @@ -728,6 +802,7 @@ 268 {{20, 16}, {201, 236}} + NO 7 @@ -872,6 +947,7 @@ 266 {{0, 269}, {429, 17}} + YES @@ -895,6 +971,7 @@ 10 {{12, 258}, {405, 5}} + {0, 0} @@ -921,27 +998,31 @@ {{211, 0}, {429, 300}} + NSView {640, 300} + YES {640, 300} + + {{0, 0}, {1440, 878}} - {640, 369} + {640, 355} {10000000000000, 10000000000000} Enjoyable YES - + 256 @@ -955,8 +1036,9 @@ 256 - {320, 418} + {196, 256} + YES NO @@ -968,9 +1050,9 @@ - 317 - 40 - 1000 + 190 + 190 + 190 75497536 2048 @@ -991,8 +1073,6 @@ - 3 - YES YES @@ -1002,7 +1082,7 @@ 20 - 46170112 + 48267264 1 @@ -1011,11 +1091,12 @@ NO 0 1 - 1 + -1 - {{1, 1}, {320, 418}} + {{2, 2}, {196, 256}} + @@ -1026,7 +1107,8 @@ -2147483392 {{306, 1}, {15, 403}} - + + NO _doScroller: @@ -1035,20 +1117,22 @@ -2147483392 - {{1, 404}, {305, 15}} + {{-100, -100}, {366, 16}} - + + NO 1 _doScroller: - 0.99688480000000002 + 0.98123324396782841 - {{0, 34}, {322, 420}} + {{0, 54}, {200, 260}} - - 133682 + + + 150035 @@ -1059,9 +1143,10 @@ - 260 - {{10, 4}, {39, 28}} + 292 + {{20, 19}, {39, 28}} + YES @@ -1085,9 +1170,10 @@ - 260 - {{57, 4}, {39, 28}} + 292 + {{67, 19}, {39, 28}} + YES 603979776 @@ -1109,21 +1195,12 @@ NO - {322, 454} + {200, 314} + + NSView - - - {200, 100} - {100, 0} - {400, 10000} - 2 - 0.0 - 15 - - - EnjoyableApplicationDelegate @@ -1136,6 +1213,15 @@ NJOutputController + + + + 0 + 1 + 0.0 + 0.0 + YES + @@ -1219,38 +1305,6 @@ 370 - - - parentWindow - - - - 454 - - - - contentView - - - - 455 - - - - toggle: - - - - 498 - - - - toggle: - - - - 811 - delegate @@ -1291,13 +1345,21 @@ 826 + + + translatingEventsChanged: + + + + 858 + - drawer - - + translatingEventsSetting + + - 486 + 859 @@ -1315,14 +1377,6 @@ 607 - - - activeButton - - - - 609 - toggleActivity: @@ -1331,14 +1385,6 @@ 610 - - - toggleActivity: - - - - 611 - dockMenuBase @@ -1427,6 +1473,30 @@ 827 + + + mappingPressed: + + + + 855 + + + + popover + + + + 856 + + + + popoverActivate + + + + 857 + dataSource @@ -1563,6 +1633,30 @@ 818 + + + view + + + + 854 + + + + contentViewController + + + + 852 + + + + delegate + + + + 853 + @@ -1757,18 +1851,13 @@ 451 + - Drawer Content View - - 452 - - - 453 @@ -1828,17 +1917,12 @@ 487 - - + + - - 495 - - - 507 @@ -1882,11 +1966,6 @@ - - 608 - - - 652 @@ -2109,11 +2188,6 @@ - - 790 - - - 810 @@ -2134,6 +2208,64 @@ + + 837 + + + + + + + + 835 + + + + + + + + 836 + + + + + 842 + + + + + + + + 840 + + + + + + + + 841 + + + + + 849 + + + + + 850 + + + Popover View Controller + + + 851 + + + @@ -2161,7 +2293,6 @@ {{114, 276}, {770, 487}} com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2172,7 +2303,6 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2183,7 +2313,6 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2220,23 +2349,118 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - 828 + 859 + + EnjoyableApplicationDelegate + NSObject + + NSMenuItem + NSMenu + NSDrawer + NJDeviceController + NJMappingsController + NJOutputController + + + + activeMenuItem + NSMenuItem + + + dockMenuBase + NSMenu + + + drawer + NSDrawer + + + inputController + NJDeviceController + + + mappingsController + NJMappingsController + + + outputController + NJOutputController + + + + IBProjectSource + ./Classes/EnjoyableApplicationDelegate.h + + + + NJDeviceController + NSObject + + translatingEventsChanged: + id + + + translatingEventsChanged: + + translatingEventsChanged: + id + + + + NJMappingsController + NSOutlineView + NJOutputController + NSSegmentedControl + + + + mappingsController + NJMappingsController + + + outlineView + NSOutlineView + + + outputController + NJOutputController + + + translatingEventsSetting + NSSegmentedControl + + + + IBProjectSource + ./Classes/NJDeviceController.h + + NJKeyInputField NSTextField @@ -2256,6 +2480,153 @@ ./Classes/NJKeyInputField.h + + NJMappingsController + NSObject + + id + id + id + id + id + + + + addPressed: + id + + + exportPressed: + id + + + importPressed: + id + + + mappingPressed: + id + + + removePressed: + id + + + + NJOutputController + NSPopover + NSButton + NSButton + NSTableView + + + + outputController + NJOutputController + + + popover + NSPopover + + + popoverActivate + NSButton + + + removeButton + NSButton + + + tableView + NSTableView + + + + IBProjectSource + ./Classes/NJMappingsController.h + + + + NJOutputController + NSObject + + id + id + id + id + + + + mbtnChanged: + id + + + mdirChanged: + id + + + radioChanged: + id + + + sdirChanged: + id + + + + NJDeviceController + NJKeyInputField + NSPopUpButton + NJMappingsController + NSSegmentedControl + NSSegmentedControl + NSMatrix + NSSegmentedControl + NSTextField + + + + inputController + NJDeviceController + + + keyInput + NJKeyInputField + + + mappingPopup + NSPopUpButton + + + mappingsController + NJMappingsController + + + mouseBtnSelect + NSSegmentedControl + + + mouseDirSelect + NSSegmentedControl + + + radioButtons + NSMatrix + + + scrollDirSelect + NSSegmentedControl + + + title + NSTextField + + + + IBProjectSource + ./Classes/NJOutputController.h + + 0 @@ -2263,11 +2634,12 @@ YES 3 + {15, 15} {8, 8} - {9, 9} {11, 10} {11, 11} {10, 3} + {13, 10} {16, 15} {8, 8} diff --git a/EnjoyableApplicationDelegate.h b/EnjoyableApplicationDelegate.h index 6a198e6..17737e8 100644 --- a/EnjoyableApplicationDelegate.h +++ b/EnjoyableApplicationDelegate.h @@ -11,9 +11,6 @@ @class NJMappingsController; @interface EnjoyableApplicationDelegate : NSObject { - IBOutlet NSDrawer *drawer; - IBOutlet NSWindow *mainWindow; - IBOutlet NSToolbarItem *activeButton; IBOutlet NSMenuItem *activeMenuItem; IBOutlet NSMenu *dockMenuBase; } @@ -22,7 +19,6 @@ @property (nonatomic, strong) IBOutlet NJOutputController *outputController; @property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController; -- (IBAction)toggleActivity:(id)sender; - (void)mappingsChanged; @end diff --git a/EnjoyableApplicationDelegate.m b/EnjoyableApplicationDelegate.m index 23324d3..74e8265 100644 --- a/EnjoyableApplicationDelegate.m +++ b/EnjoyableApplicationDelegate.m @@ -43,7 +43,6 @@ while (![dockMenuBase itemAtIndex:mappingsMenuIndex - 1].isSeparatorItem) --mappingsMenuIndex; - [drawer open]; self.outputController.enabled = NO; [self.inputController setup]; [self.mappingsController load]; @@ -54,23 +53,19 @@ } - (void)eventTranslationActivated:(NSNotification *)note { - activeButton.image = [NSImage imageNamed:@"NSStopProgressFreestandingTemplate"]; - activeMenuItem.state = [note.object translatingEvents]; [NSWorkspace.sharedWorkspace.notificationCenter - addObserver:self - selector:@selector(didSwitchApplication:) - name:NSWorkspaceDidActivateApplicationNotification - object:nil]; + addObserver:self + selector:@selector(didSwitchApplication:) + name:NSWorkspaceDidActivateApplicationNotification + object:nil]; NSLog(@"Listening for application changes."); } - (void)eventTranslationDeactivated:(NSNotification *)note { - activeButton.image = [NSImage imageNamed:@"NSGoRightTemplate"]; - activeMenuItem.state = [note.object translatingEvents]; [NSWorkspace.sharedWorkspace.notificationCenter - removeObserver:self - name:NSWorkspaceDidActivateApplicationNotification - object:nil]; + removeObserver:self + name:NSWorkspaceDidActivateApplicationNotification + object:nil]; NSLog(@"Ignoring application changes."); } @@ -83,7 +78,7 @@ while (dockMenuBase.numberOfItems > removeFrom) [dockMenuBase removeItemAtIndex:dockMenuBase.numberOfItems - 1]; int added = 0; - for (NJMapping *mapping in self.mappingsController.mappings) { + for (NJMapping *mapping in self.mappingsController) { NSString *keyEquiv = ++added < 10 ? @(added).stringValue : @""; [dockMenuBase addItemWithTitle:mapping.name action:@selector(chooseMapping:) @@ -102,7 +97,7 @@ - (void)chooseMapping:(id)sender { NSInteger idx = [dockMenuBase indexOfItem:sender] - mappingsMenuIndex; - NJMapping *chosen = self.mappingsController.mappings[idx]; + NJMapping *chosen = self.mappingsController[idx]; [_mappingsController activateMapping:chosen]; } diff --git a/NJDeviceController.h b/NJDeviceController.h index 2769222..cfa6d99 100644 --- a/NJDeviceController.h +++ b/NJDeviceController.h @@ -15,14 +15,17 @@ IBOutlet NSOutlineView *outlineView; IBOutlet NJOutputController *outputController; IBOutlet NJMappingsController *mappingsController; + IBOutlet NSSegmentedControl *translatingEventsSetting; } -- (void)setup; -- (NJDevice *)findDeviceByRef:(IOHIDDeviceRef)device; - @property (nonatomic, readonly) NJInput *selectedInput; @property (nonatomic, assign) NSPoint mouseLoc; @property (nonatomic, assign) BOOL frontWindowOnly; @property (nonatomic, assign) BOOL translatingEvents; +- (void)setup; +- (NJDevice *)findDeviceByRef:(IOHIDDeviceRef)device; + +- (IBAction)translatingEventsChanged:(id)sender; + @end diff --git a/NJDeviceController.m b/NJDeviceController.m index e68cfdb..f5da6dd 100644 --- a/NJDeviceController.m +++ b/NJDeviceController.m @@ -224,6 +224,7 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn - (void)setTranslatingEvents:(BOOL)translatingEvents { if (translatingEvents != _translatingEvents) { _translatingEvents = translatingEvents; + translatingEventsSetting.selectedSegment = !!translatingEvents; NSString *name = translatingEvents ? NJEventTranslationActivated : NJEventTranslationDeactivated; @@ -232,4 +233,9 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn } } +- (IBAction)translatingEventsChanged:(id)sender { + self.translatingEvents = translatingEventsSetting.selectedSegment; +} + + @end diff --git a/NJMappingsController.h b/NJMappingsController.h index d793714..4867943 100644 --- a/NJMappingsController.h +++ b/NJMappingsController.h @@ -11,26 +11,30 @@ @interface NJMappingsController : NSObject { + NSOpenSavePanelDelegate, + NSFastEnumeration> +{ IBOutlet NSButton *removeButton; IBOutlet NSTableView *tableView; IBOutlet NJOutputController *outputController; + IBOutlet NSButton *popoverActivate; + IBOutlet NSPopover *popover; } @property (nonatomic, readonly) NJMapping *currentMapping; @property (nonatomic, readonly) NSArray *mappings; - (NJMapping *)objectForKeyedSubscript:(NSString *)name; +- (NJMapping *)objectAtIndexedSubscript:(NSUInteger)idx; +- (void)activateMapping:(NJMapping *)mapping; +- (void)activateMappingForProcess:(NSString *)processName; +- (void)save; +- (void)load; - +- (IBAction)mappingPressed:(id)sender; - (IBAction)addPressed:(id)sender; - (IBAction)removePressed:(id)sender; - (IBAction)importPressed:(id)sender; - (IBAction)exportPressed:(id)sender; -- (void)activateMapping:(NJMapping *)mapping; -- (void)activateMappingForProcess:(NSString *)processName; - -- (void)save; -- (void)load; @end diff --git a/NJMappingsController.m b/NJMappingsController.m index fe96462..193edfe 100644 --- a/NJMappingsController.m +++ b/NJMappingsController.m @@ -36,6 +36,19 @@ return nil; } +- (NJMapping *)objectAtIndexedSubscript:(NSUInteger)idx { + return idx < _mappings.count ? _mappings[idx] : nil; +} + +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state + objects:(__unsafe_unretained id [])buffer + count:(NSUInteger)len { + return [_mappings countByEnumeratingWithState:state + objects:buffer + count:len]; +} + + - (void)activateMappingForProcess:(NSString *)processName { NJMapping *oldMapping = manualMapping; NJMapping *newMapping = self[processName]; @@ -54,6 +67,7 @@ _currentMapping = mapping; [removeButton setEnabled:_mappings[0] != mapping]; [outputController loadCurrent]; + popoverActivate.title = _currentMapping.name; [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingChanged object:_currentMapping]; [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:[_mappings indexOfObject:mapping]] byExtendingSelection:NO]; @@ -86,11 +100,15 @@ } - (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index { - return [_mappings[index] name]; + return self[index].name; } -- (void)tableView:(NSTableView *)view setObjectValue:(NSString *)obj forTableColumn:(NSTableColumn *)col row:(NSInteger)index { - [(NJMapping *)_mappings[index] setName:obj]; +- (void)tableView:(NSTableView *)view + setObjectValue:(NSString *)obj + forTableColumn:(NSTableColumn *)col + row:(NSInteger)index { + self[index].name = obj; + [self save]; [tableView reloadData]; [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; } @@ -284,4 +302,8 @@ }]; } +- (IBAction)mappingPressed:(id)sender { + [popover showRelativeToRect:popoverActivate.bounds ofView:popoverActivate preferredEdge:NSMinXEdge]; +} + @end diff --git a/NJOutputController.m b/NJOutputController.m index 6725125..8f942c6 100644 --- a/NJOutputController.m +++ b/NJOutputController.m @@ -116,7 +116,7 @@ break; case 2: { NJOutputMapping *c = [[NJOutputMapping alloc] init]; - c.mapping = mappingsController.mappings[mappingPopup.indexOfSelectedItem]; + c.mapping = mappingsController[mappingPopup.indexOfSelectedItem]; return c; } case 3: { @@ -222,7 +222,7 @@ - (void)refreshMappings { NSInteger initialIndex = mappingPopup.indexOfSelectedItem; [mappingPopup.menu removeAllItems]; - for (NJMapping *mapping in mappingsController.mappings) { + for (NJMapping *mapping in mappingsController) { NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name action:@selector(mappingChosen:) keyEquivalent:@""]; -- 2.20.1 From 04a5164fec6b5d856b4ab181a2b7c870c2dc679a Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 14:06:53 +0100 Subject: [PATCH 03/16] Signal mappings menu entry by a tag, not a check for a separator. Remove dead code. --- English.lproj/MainMenu.xib | 28 +++++++++++++++++----------- EnjoyableApplicationDelegate.h | 1 - EnjoyableApplicationDelegate.m | 8 +------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 2e2b440..a110b51 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -240,6 +240,7 @@ 2147483647 + 1 @@ -336,6 +337,7 @@ {{0, 14}, {140, 25}} + _NS:9 YES @@ -386,6 +388,7 @@ {{5, 14}, {67, 25}} + _NS:9 YES @@ -461,7 +464,7 @@ - + @@ -695,6 +698,7 @@ {{227, 55}, {180, 24}} + _NS:9 YES @@ -1174,6 +1178,7 @@ {{67, 19}, {39, 28}} + YES 603979776 @@ -2379,27 +2384,28 @@ EnjoyableApplicationDelegate NSObject + + toggleActivity: + id + + + toggleActivity: + + toggleActivity: + id + + - NSMenuItem NSMenu - NSDrawer NJDeviceController NJMappingsController NJOutputController - - activeMenuItem - NSMenuItem - dockMenuBase NSMenu - - drawer - NSDrawer - inputController NJDeviceController diff --git a/EnjoyableApplicationDelegate.h b/EnjoyableApplicationDelegate.h index 17737e8..3e74418 100644 --- a/EnjoyableApplicationDelegate.h +++ b/EnjoyableApplicationDelegate.h @@ -11,7 +11,6 @@ @class NJMappingsController; @interface EnjoyableApplicationDelegate : NSObject { - IBOutlet NSMenuItem *activeMenuItem; IBOutlet NSMenu *dockMenuBase; } diff --git a/EnjoyableApplicationDelegate.m b/EnjoyableApplicationDelegate.m index 74e8265..0dbea22 100644 --- a/EnjoyableApplicationDelegate.m +++ b/EnjoyableApplicationDelegate.m @@ -39,9 +39,7 @@ name:NJEventTranslationDeactivated object:nil]; - mappingsMenuIndex = dockMenuBase.numberOfItems; - while (![dockMenuBase itemAtIndex:mappingsMenuIndex - 1].isSeparatorItem) - --mappingsMenuIndex; + while (![dockMenuBase itemAtIndex:mappingsMenuIndex++].tag); self.outputController.enabled = NO; [self.inputController setup]; @@ -69,10 +67,6 @@ NSLog(@"Ignoring application changes."); } -- (IBAction)toggleActivity:(id)sender { - self.inputController.translatingEvents = !self.inputController.translatingEvents; -} - - (void)mappingsChanged { NSInteger removeFrom = mappingsMenuIndex; while (dockMenuBase.numberOfItems > removeFrom) -- 2.20.1 From 692a4d66b4d6d9ae39a57d4c953dfbcbf939a166 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 14:43:51 +0100 Subject: [PATCH 04/16] Fix mismatched serialization code. --- NJOutputKeyPress.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NJOutputKeyPress.m b/NJOutputKeyPress.m index c2000d8..5371475 100644 --- a/NJOutputKeyPress.m +++ b/NJOutputKeyPress.m @@ -12,7 +12,7 @@ @implementation NJOutputKeyPress + (NSString *)serializationCode { - return @"key"; + return @"key press"; } - (NSDictionary *)serialize { -- 2.20.1 From 055557513f5608af99f6736a6ce40da3df8618a7 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 14:47:56 +0100 Subject: [PATCH 05/16] Use represented objects rather than index hackery. Remove the mapping name from the output title, since it's always on-screen now. --- NJOutputController.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NJOutputController.m b/NJOutputController.m index 8f942c6..25d04b1 100644 --- a/NJOutputController.m +++ b/NJOutputController.m @@ -172,7 +172,7 @@ for (id cur = input.base; cur; cur = cur.base) { inpFullName = [[NSString alloc] initWithFormat:@"%@ > %@", cur.name, inpFullName]; } - title.stringValue = [[NSString alloc] initWithFormat:@"%@ > %@", mappingsController.currentMapping.name, inpFullName]; + title.stringValue = inpFullName; } if ([output isKindOfClass:NJOutputKeyPress.class]) { @@ -180,8 +180,7 @@ keyInput.keyCode = [(NJOutputKeyPress*)output vk]; } else if ([output isKindOfClass:NJOutputMapping.class]) { [radioButtons selectCellAtRow:2 column:0]; - NSUInteger idx = [mappingsController.mappings - indexOfObject:[(NJOutputMapping *)output mapping]]; + NSUInteger idx = [mappingPopup indexOfItemWithRepresentedObject:[(NJOutputMapping *)output mapping]]; if (idx == NSNotFound) { [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0]; [mappingPopup selectItemAtIndex:-1]; @@ -220,16 +219,17 @@ } - (void)refreshMappings { - NSInteger initialIndex = mappingPopup.indexOfSelectedItem; + NJMapping *current = mappingPopup.selectedItem.representedObject; [mappingPopup.menu removeAllItems]; for (NJMapping *mapping in mappingsController) { NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name action:@selector(mappingChosen:) keyEquivalent:@""]; item.target = self; + item.representedObject = mapping; [mappingPopup.menu addItem:item]; } - [mappingPopup selectItemAtIndex:initialIndex]; + [mappingPopup selectItemAtIndex:[mappingPopup indexOfItemWithRepresentedObject:current]]; } @end -- 2.20.1 From 30e895677773cc087a4e9a75abc99d0c1233dddc Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 14:54:09 +0100 Subject: [PATCH 06/16] Fix old check for unset field. --- NJKeyInputField.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NJKeyInputField.m b/NJKeyInputField.m index 13aa138..b159aa3 100644 --- a/NJKeyInputField.m +++ b/NJKeyInputField.m @@ -27,7 +27,7 @@ CGKeyCode NJKeyInputFieldEmpty = 0xFFFF; } - (BOOL)hasKeyCode { - return self.keyCode >= 0; + return self.keyCode != NJKeyInputFieldEmpty; } + (NSString *)stringForKeyCode:(CGKeyCode)keyCode { -- 2.20.1 From c38397be0be3a8b0b5c502bf5a5bc24b3c0f61bb Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 15:13:34 +0100 Subject: [PATCH 07/16] Fix old method of unsetting field. --- NJOutputController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NJOutputController.m b/NJOutputController.m index 25d04b1..ed8fe2d 100644 --- a/NJOutputController.m +++ b/NJOutputController.m @@ -26,7 +26,7 @@ NSInteger row = radioButtons.selectedRow; if (row != 1) { - keyInput.keyCode = -1; + keyInput.keyCode = NJKeyInputFieldEmpty; [keyInput resignIfFirstResponder]; } -- 2.20.1 From 8ac97ce92f0607b38c14db63e6eabfd78729d473 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 16:01:38 +0100 Subject: [PATCH 08/16] Give accurate names to most of the items in the nib. Tweak button appearance on the popover to resemble e.g. System Preferences lists with add/remove. --- English.lproj/MainMenu.xib | 214 ++++++++++++++++++++----------------- 1 file changed, 113 insertions(+), 101 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index a110b51..e30e982 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -302,9 +302,6 @@ _NSMainMenu - - NSFontManager - 15 2 @@ -336,7 +333,6 @@ 268 {{0, 14}, {140, 25}} - _NS:9 YES @@ -387,7 +383,6 @@ 268 {{5, 14}, {67, 25}} - _NS:9 YES @@ -963,7 +958,7 @@ 13 16 - No action selected + No input selected @@ -1040,7 +1035,7 @@ 256 - {196, 256} + {198, 198} @@ -1086,7 +1081,7 @@ 20 - 48267264 + 44072960 1 @@ -1098,7 +1093,7 @@ -1 - {{2, 2}, {196, 256}} + {{1, 1}, {198, 198}} @@ -1132,11 +1127,11 @@ 0.98123324396782841 - {{0, 54}, {200, 260}} + {{0, 20}, {200, 200}} - 150035 + 150034 @@ -1145,28 +1140,57 @@ 4 1 + + + 268 + {{66, -1}, {134, 23}} + + + + _NS:22 + YES + + -2080374784 + 168034304 + + + LucidaGrande + 9 + 3614 + + _NS:22 + + 1221349376 + 162 + + + 400 + 75 + + NO + 292 - {{20, 19}, {39, 28}} + {{0, -1}, {34, 23}} YES 67108864 - 134217728 + 134479872 - + -2033958912 - 162 + 268435618 NSImage NSAddTemplate - + n 400 75 @@ -1175,32 +1199,32 @@ 292 - {{67, 19}, {39, 28}} + {{33, -1}, {34, 23}} - + YES - 603979776 - 134217728 + 67108864 + 134479872 - + -2033958912 - 162 + 268435618 NSImage NSRemoveTemplate - + CA 400 75 NO - {200, 314} + {200, 220} @@ -1366,30 +1390,6 @@ 859 - - - mainWindow - - - - 500 - - - - activeMenuItem - - - - 607 - - - - toggleActivity: - - - - 610 - dockMenuBase @@ -1422,14 +1422,6 @@ 825 - - - addPressed: - - - - 515 - removePressed: @@ -1502,6 +1494,14 @@ 857 + + + addPressed: + + + + 515 + dataSource @@ -1614,14 +1614,6 @@ 823 - - - mappingChosen: - - - - 824 - inputController @@ -1698,7 +1690,7 @@ - MainMenu + Main Menu 19 @@ -1838,11 +1830,6 @@ - - 420 - - - 450 @@ -1857,11 +1844,12 @@ - + + - Drawer Content View + Mapping List Popover Content 453 @@ -1898,6 +1886,7 @@ + Mapping List 461 @@ -1916,7 +1905,6 @@ 482 - ApplicationController 487 @@ -1928,19 +1916,6 @@ - - 507 - - - - - - - - 508 - - - 511 @@ -1948,6 +1923,7 @@ + Remove Mapping 512 @@ -1958,13 +1934,11 @@ 514 - ConfigsController 479 - JoystickController 606 @@ -1987,6 +1961,7 @@ + Input Devices Pane 634 @@ -2005,6 +1980,7 @@ + Input Device List 636 @@ -2023,6 +1999,7 @@ + Device/Input Name 642 @@ -2043,6 +2020,7 @@ + Output Editor Pane 686 @@ -2063,21 +2041,25 @@ + Output Types 657 + Disabled 658 + Key Press 699 + Switch Mapping 700 @@ -2086,6 +2068,7 @@ + Mapping Choice List 701 @@ -2108,6 +2091,7 @@ + Input Name 707 @@ -2128,16 +2112,19 @@ 733 + Mouse Movement 734 + Mouse Button 735 + Mouse Scroll 659 @@ -2151,6 +2138,7 @@ + Mouse Button Selector 745 @@ -2161,6 +2149,7 @@ 748 + Switch Mouse Mode 749 @@ -2169,6 +2158,7 @@ + Mouse Scroll Selector 750 @@ -2182,6 +2172,7 @@ + Mouse Motion Selector 755 @@ -2220,6 +2211,7 @@ + Mapping Selector 835 @@ -2241,6 +2233,7 @@ + Translation Switch 840 @@ -2270,6 +2263,35 @@ 851 + Mapping List Popover + + + 507 + + + + + + Add Mapping + + + 508 + + + + + 862 + + + + + + Gradient Space + + + 863 + + @@ -2291,7 +2313,6 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2371,30 +2392,21 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - 859 + 863 EnjoyableApplicationDelegate NSObject - - toggleActivity: - id - - - toggleActivity: - - toggleActivity: - id - - NSMenu NJDeviceController -- 2.20.1 From e23012ee44e26e9fd2bd43340a3fd806b084fa47 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 16:17:59 +0100 Subject: [PATCH 09/16] Turn popover activation button 'on' when the popover is up. --- English.lproj/MainMenu.xib | 18 +++++++++--------- NJMappingsController.h | 1 + NJMappingsController.m | 8 ++++++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index e30e982..353e905 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -325,19 +325,19 @@ 4AC66688-76E8-47ED-AC0A-7462220A4019 - Custom View - Custom View + Mapping Selector + Mapping Selector 268 {{0, 14}, {140, 25}} - + _NS:9 YES - -2080374784 + 67108864 134217728 (default) @@ -347,7 +347,7 @@ _NS:9 - -2034483200 + 918306816 163 NSImage @@ -375,15 +375,15 @@ 94389EFE-310F-4DB5-95F6-D4AEE8839979 - Custom View - Custom View + Translation Enabled + Translation Enabled 268 - {{5, 14}, {67, 25}} + {{23, 14}, {67, 25}} - + _NS:9 YES diff --git a/NJMappingsController.h b/NJMappingsController.h index 4867943..f0dab4f 100644 --- a/NJMappingsController.h +++ b/NJMappingsController.h @@ -12,6 +12,7 @@ @interface NJMappingsController : NSObject { IBOutlet NSButton *removeButton; diff --git a/NJMappingsController.m b/NJMappingsController.m index 193edfe..f1e068e 100644 --- a/NJMappingsController.m +++ b/NJMappingsController.m @@ -306,4 +306,12 @@ [popover showRelativeToRect:popoverActivate.bounds ofView:popoverActivate preferredEdge:NSMinXEdge]; } +- (void)popoverWillShow:(NSNotification *)notification { + popoverActivate.state = NSOnState; +} + +- (void)popoverWillClose:(NSNotification *)notification { + popoverActivate.state = NSOffState; +} + @end -- 2.20.1 From 1315dd378437c84891c795c9927ff40d42d74cb3 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 16:46:54 +0100 Subject: [PATCH 10/16] Remove mappingsChanged with a notification. MappingsController no longer needs to know about the app delegate. --- EnjoyableApplicationDelegate.h | 2 -- EnjoyableApplicationDelegate.m | 11 +++++++++-- NJEvents.h | 1 + NJMappingsController.m | 33 +++++++++++++++------------------ 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/EnjoyableApplicationDelegate.h b/EnjoyableApplicationDelegate.h index 3e74418..b77f799 100644 --- a/EnjoyableApplicationDelegate.h +++ b/EnjoyableApplicationDelegate.h @@ -18,6 +18,4 @@ @property (nonatomic, strong) IBOutlet NJOutputController *outputController; @property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController; -- (void)mappingsChanged; - @end diff --git a/EnjoyableApplicationDelegate.m b/EnjoyableApplicationDelegate.m index 0dbea22..8afbb5b 100644 --- a/EnjoyableApplicationDelegate.m +++ b/EnjoyableApplicationDelegate.m @@ -28,6 +28,11 @@ selector:@selector(mappingDidChange:) name:NJEventMappingChanged object:nil]; + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(mappingListDidChange:) + name:NJEventMappingListChanged + object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(eventTranslationActivated:) @@ -48,6 +53,7 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification { [NSUserDefaults.standardUserDefaults synchronize]; + [NSNotificationCenter.defaultCenter removeObserver:self]; } - (void)eventTranslationActivated:(NSNotification *)note { @@ -67,12 +73,13 @@ NSLog(@"Ignoring application changes."); } -- (void)mappingsChanged { +- (void)mappingListDidChange:(NSNotification *)note { + NSArray *mappings = note.object; NSInteger removeFrom = mappingsMenuIndex; while (dockMenuBase.numberOfItems > removeFrom) [dockMenuBase removeItemAtIndex:dockMenuBase.numberOfItems - 1]; int added = 0; - for (NJMapping *mapping in self.mappingsController) { + for (NJMapping *mapping in mappings) { NSString *keyEquiv = ++added < 10 ? @(added).stringValue : @""; [dockMenuBase addItemWithTitle:mapping.name action:@selector(chooseMapping:) diff --git a/NJEvents.h b/NJEvents.h index 84bdd82..ce87b24 100644 --- a/NJEvents.h +++ b/NJEvents.h @@ -7,5 +7,6 @@ // #define NJEventMappingChanged @"NJEventMappingChanged" +#define NJEventMappingListChanged @"NJEventMappingListChanged" #define NJEventTranslationActivated @"NJEventTranslationActivated" #define NJEventTranslationDeactivated @"NJEventTranslationDeactivated" diff --git a/NJMappingsController.m b/NJMappingsController.m index f1e068e..e2ac93c 100644 --- a/NJMappingsController.m +++ b/NJMappingsController.m @@ -7,7 +7,6 @@ #import "NJMappingsController.h" -#import "EnjoyableApplicationDelegate.h" #import "NJMapping.h" #import "NJMappingsController.h" #import "NJOutput.h" @@ -40,6 +39,14 @@ return idx < _mappings.count ? _mappings[idx] : nil; } +- (void)mappingsChanged { + [self save]; + [tableView reloadData]; + [NSNotificationCenter.defaultCenter + postNotificationName:NJEventMappingListChanged + object:_mappings]; +} + - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id [])buffer count:(NSUInteger)len { @@ -76,11 +83,9 @@ - (IBAction)addPressed:(id)sender { NJMapping *newMapping = [[NJMapping alloc] initWithName:@"Untitled"]; [_mappings addObject:newMapping]; - [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; - [tableView reloadData]; - [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_mappings.count - 1] byExtendingSelection:NO]; - [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES]; + [self mappingsChanged]; [self activateMapping:newMapping]; + [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES]; } - (IBAction)removePressed:(id)sender { @@ -88,15 +93,12 @@ return; [_mappings removeObjectAtIndex:tableView.selectedRow]; - [tableView reloadData]; - [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; + [self mappingsChanged]; [self activateMapping:_mappings[0]]; - [self save]; } -(void)tableViewSelectionDidChange:(NSNotification *)notify { - if (tableView.selectedRow >= 0) - [self activateMapping:_mappings[tableView.selectedRow]]; + [self activateMapping:self[tableView.selectedRow]]; } - (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index { @@ -108,9 +110,7 @@ forTableColumn:(NSTableColumn *)col row:(NSInteger)index { self[index].name = obj; - [self save]; - [tableView reloadData]; - [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; + [self mappingsChanged]; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { @@ -164,8 +164,7 @@ if (current >= newMappings.count) current = 0; _mappings = newMappings; - [tableView reloadData]; - [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; + [self mappingsChanged]; [self activateMapping:_mappings[current]]; } } @@ -248,11 +247,9 @@ mapping = mergeInto; } else { [_mappings addObject:mapping]; - [tableView reloadData]; } - [self save]; - [(EnjoyableApplicationDelegate *)NSApplication.sharedApplication.delegate mappingsChanged]; + [self mappingsChanged]; [self activateMapping:mapping]; [outputController loadCurrent]; -- 2.20.1 From 57a69924ef04692efe35eb75e3b27dd81af1c147 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 23:00:02 +0100 Subject: [PATCH 11/16] Tweak toolbar icons. --- English.lproj/MainMenu.xib | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 353e905..32c3a86 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -375,13 +375,13 @@ 94389EFE-310F-4DB5-95F6-D4AEE8839979 - Translation Enabled - Translation Enabled + Translation Switch + Translation Switch 268 - {{23, 14}, {67, 25}} + {{19, 14}, {67, 25}} _NS:9 @@ -397,9 +397,8 @@ 32 NSImage - NSPathTemplate + NSActionTemplate - Show and remap inputs YES 0 @@ -408,9 +407,8 @@ 32 NSImage - NSActionTemplate + NSRightFacingTriangleTemplate - Run mapped actions 1 0 @@ -464,7 +462,7 @@ - + @@ -2184,11 +2182,6 @@ - - 810 - - - 812 @@ -2293,6 +2286,11 @@ + + 810 + + + @@ -2386,7 +2384,7 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2400,7 +2398,7 @@ - 863 + 864 @@ -2657,9 +2655,9 @@ {11, 10} {11, 11} {10, 3} - {13, 10} {16, 15} {8, 8} + {9, 9} -- 2.20.1 From b46786face17680799d7fd9795dead8a801ae9c1 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Mon, 4 Mar 2013 23:00:21 +0100 Subject: [PATCH 12/16] Add some categories to better handle menus with represented objects, then use them for simpler menu handling. --- Enjoyable.xcodeproj/project.pbxproj | 6 ++++ EnjoyableApplicationDelegate.m | 33 ++++++++------------ Enjoyable_Prefix.pch | 3 +- NJMappingsController.m | 36 +++++++++++----------- NJOutputController.m | 10 +++--- NSMenu+RepresentedObjectAccessors.h | 47 ++++++++++++++++++++++++++++ NSMenu+RepresentedObjectAccessors.m | 48 +++++++++++++++++++++++++++++ 7 files changed, 138 insertions(+), 45 deletions(-) create mode 100644 NSMenu+RepresentedObjectAccessors.h create mode 100644 NSMenu+RepresentedObjectAccessors.m diff --git a/Enjoyable.xcodeproj/project.pbxproj b/Enjoyable.xcodeproj/project.pbxproj index ccdd256..c2f3246 100644 --- a/Enjoyable.xcodeproj/project.pbxproj +++ b/Enjoyable.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ D5F80A9D0FB0A2FF0006A4DE /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = D5617A080FAEAF8300928B3A /* icon.icns */; }; EE1D7C9216E01E7000B000EB /* NSView+FirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */; }; EE1D7C9616E0ECCF00B000EB /* NSError+Description.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1D7C9516E0ECCF00B000EB /* NSError+Description.m */; }; + EE96929416E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m in Sources */ = {isa = PBXBuildFile; fileRef = EE96929316E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -89,6 +90,8 @@ EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+FirstResponder.m"; sourceTree = ""; }; EE1D7C9416E0ECCF00B000EB /* NSError+Description.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Description.h"; sourceTree = ""; }; EE1D7C9516E0ECCF00B000EB /* NSError+Description.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+Description.m"; sourceTree = ""; }; + EE96929216E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMenu+RepresentedObjectAccessors.h"; sourceTree = ""; }; + EE96929316E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMenu+RepresentedObjectAccessors.m"; sourceTree = ""; }; EEF86B7316E2241000674B87 /* NJInputPathElement.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NJInputPathElement.h; sourceTree = ""; }; EEF86B7416E298CD00674B87 /* NJEvents.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NJEvents.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -227,6 +230,8 @@ EE1D7C9516E0ECCF00B000EB /* NSError+Description.m */, EE1D7C9016E01E7000B000EB /* NSView+FirstResponder.h */, EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */, + EE96929216E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.h */, + EE96929316E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m */, ); name = Categories; sourceTree = ""; @@ -319,6 +324,7 @@ 8BEFADA015C476DC00823AEC /* NJOutputSwitchMouseMode.m in Sources */, EE1D7C9216E01E7000B000EB /* NSView+FirstResponder.m in Sources */, EE1D7C9616E0ECCF00B000EB /* NSError+Description.m in Sources */, + EE96929416E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/EnjoyableApplicationDelegate.m b/EnjoyableApplicationDelegate.m index 8afbb5b..388103b 100644 --- a/EnjoyableApplicationDelegate.m +++ b/EnjoyableApplicationDelegate.m @@ -13,9 +13,7 @@ #import "NJOutputController.h" #import "NJEvents.h" -@implementation EnjoyableApplicationDelegate { - NSInteger mappingsMenuIndex; -} +@implementation EnjoyableApplicationDelegate - (void)didSwitchApplication:(NSNotification *)notification { NSRunningApplication *currentApp = notification.userInfo[NSWorkspaceApplicationKey]; @@ -44,9 +42,6 @@ name:NJEventTranslationDeactivated object:nil]; - while (![dockMenuBase itemAtIndex:mappingsMenuIndex++].tag); - - self.outputController.enabled = NO; [self.inputController setup]; [self.mappingsController load]; } @@ -75,31 +70,29 @@ - (void)mappingListDidChange:(NSNotification *)note { NSArray *mappings = note.object; - NSInteger removeFrom = mappingsMenuIndex; - while (dockMenuBase.numberOfItems > removeFrom) - [dockMenuBase removeItemAtIndex:dockMenuBase.numberOfItems - 1]; + while (dockMenuBase.lastItem.representedObject) + [dockMenuBase removeLastItem]; int added = 0; for (NJMapping *mapping in mappings) { NSString *keyEquiv = ++added < 10 ? @(added).stringValue : @""; - [dockMenuBase addItemWithTitle:mapping.name - action:@selector(chooseMapping:) - keyEquivalent:keyEquiv]; - + NSMenuItem *item = [dockMenuBase addItemWithTitle:mapping.name + action:@selector(chooseMapping:) + keyEquivalent:keyEquiv]; + item.representedObject = mapping; } [_outputController refreshMappings]; } - (void)mappingDidChange:(NSNotification *)note { NJMapping *current = note.object; - NSArray *mappings = self.mappingsController.mappings; - for (NSUInteger i = 0; i < mappings.count; ++i) - [dockMenuBase itemAtIndex:i + mappingsMenuIndex].state = mappings[i] == current; + for (NSMenuItem *item in dockMenuBase.itemArray) + if (item.representedObject) + item.state = item.representedObject == current; } -- (void)chooseMapping:(id)sender { - NSInteger idx = [dockMenuBase indexOfItem:sender] - mappingsMenuIndex; - NJMapping *chosen = self.mappingsController[idx]; - [_mappingsController activateMapping:chosen]; +- (void)chooseMapping:(NSMenuItem *)sender { + NJMapping *chosen = sender.representedObject; + [self.mappingsController activateMapping:chosen]; } @end diff --git a/Enjoyable_Prefix.pch b/Enjoyable_Prefix.pch index 86806fe..1057a2c 100644 --- a/Enjoyable_Prefix.pch +++ b/Enjoyable_Prefix.pch @@ -8,5 +8,6 @@ #import -#import "NSView+FirstResponder.h" #import "NSError+Description.h" +#import "NSMenu+RepresentedObjectAccessors.h" +#import "NSView+FirstResponder.h" diff --git a/NJMappingsController.m b/NJMappingsController.m index e2ac93c..26ef35f 100644 --- a/NJMappingsController.m +++ b/NJMappingsController.m @@ -42,6 +42,7 @@ - (void)mappingsChanged { [self save]; [tableView reloadData]; + popoverActivate.title = _currentMapping.name; [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingListChanged object:_mappings]; @@ -69,15 +70,19 @@ - (void)activateMapping:(NJMapping *)mapping { if (!mapping) mapping = manualMapping; + if (mapping == _currentMapping) + return; NSLog(@"Switching to mapping %@.", mapping.name); manualMapping = mapping; _currentMapping = mapping; [removeButton setEnabled:_mappings[0] != mapping]; [outputController loadCurrent]; popoverActivate.title = _currentMapping.name; + NSUInteger selected = [_mappings indexOfObject:mapping]; + [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selected] byExtendingSelection:NO]; + [NSUserDefaults.standardUserDefaults setInteger:selected forKey:@"selected"]; [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingChanged object:_currentMapping]; - [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:[_mappings indexOfObject:mapping]] byExtendingSelection:NO]; } - (IBAction)addPressed:(id)sender { @@ -118,28 +123,24 @@ } - (BOOL)tableView:(NSTableView *)view shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)index { - return index > 0; + return YES; } - (void)save { NSLog(@"Saving mappings to defaults."); - [NSUserDefaults.standardUserDefaults setValuesForKeysWithDictionary:[self dumpAll]]; -} - -- (void)load { - [self loadAllFrom:NSUserDefaults.standardUserDefaults.dictionaryRepresentation]; -} - -- (NSDictionary *)dumpAll { NSMutableArray *ary = [[NSMutableArray alloc] initWithCapacity:_mappings.count]; for (NJMapping *mapping in _mappings) [ary addObject:[mapping serialize]]; - NSUInteger current = _currentMapping ? [_mappings indexOfObject:_currentMapping] : 0; - return @{ @"mappings": ary, @"selected": @(current) }; + [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"]; +} + +- (void)load { + NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"]; + NSArray *mappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"]; + [self loadAllFrom:mappings andActivate:selected]; } -- (void)loadAllFrom:(NSDictionary*)envelope { - NSArray *storedMappings = envelope[@"mappings"]; +- (void)loadAllFrom:(NSArray *)storedMappings andActivate:(NSUInteger)selected { NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count]; // have to do two passes in case mapping1 refers to mapping2 via a NJOutputMapping @@ -160,12 +161,11 @@ } if (newMappings.count) { - unsigned current = [envelope[@"selected"] unsignedIntValue]; - if (current >= newMappings.count) - current = 0; _mappings = newMappings; + if (selected >= newMappings.count) + selected = 0; [self mappingsChanged]; - [self activateMapping:_mappings[current]]; + [self activateMapping:_mappings[selected]]; } } diff --git a/NJOutputController.m b/NJOutputController.m index ed8fe2d..5ceccba 100644 --- a/NJOutputController.m +++ b/NJOutputController.m @@ -180,12 +180,10 @@ keyInput.keyCode = [(NJOutputKeyPress*)output vk]; } else if ([output isKindOfClass:NJOutputMapping.class]) { [radioButtons selectCellAtRow:2 column:0]; - NSUInteger idx = [mappingPopup indexOfItemWithRepresentedObject:[(NJOutputMapping *)output mapping]]; - if (idx == NSNotFound) { + NSMenuItem *item = [mappingPopup itemWithRepresentedObject:[(NJOutputMapping *)output mapping]]; + [mappingPopup selectItem:item]; + if (!item) [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0]; - [mappingPopup selectItemAtIndex:-1]; - } else - [mappingPopup selectItemAtIndex:idx]; } else if ([output isKindOfClass:NJOutputMouseMove.class]) { [radioButtons selectCellAtRow:3 column:0]; @@ -229,7 +227,7 @@ item.representedObject = mapping; [mappingPopup.menu addItem:item]; } - [mappingPopup selectItemAtIndex:[mappingPopup indexOfItemWithRepresentedObject:current]]; + [mappingPopup selectItemWithRepresentedObject:current]; } @end diff --git a/NSMenu+RepresentedObjectAccessors.h b/NSMenu+RepresentedObjectAccessors.h new file mode 100644 index 0000000..ecb28a6 --- /dev/null +++ b/NSMenu+RepresentedObjectAccessors.h @@ -0,0 +1,47 @@ +// +// NSMenu+RepresentedObjectAccessors.h +// Enjoyable +// +// Created by Joe Wreschnig on 3/4/13. +// +// + +#import + +@interface NSMenu (RepresentedObjectAccessors) + // Helpers for using represented objects in menu items. + +- (NSMenuItem *)itemWithRepresentedObject:(id)object; + // Returns the first menu item in the receiver that has a given + // represented object. + +- (void)removeItemWithRepresentedObject:(id)object; + // Removes the first menu item representing the given object in the + // receiver. + // + // After it removes the menu item, this method posts an + // NSMenuDidRemoveItemNotification. + +- (NSMenuItem *)lastItem; + // Return the last menu item in the receiver, or nil if the menu + // has no items. + +- (void)removeLastItem; + // Removes the last menu item in the receiver, if there is one. + // + // After and if it removes the menu item, this method posts an + // NSMenuDidRemoveItemNotification. + +@end + +@interface NSPopUpButton (RepresentedObjectAccessors) + +- (NSMenuItem *)itemWithRepresentedObject:(id)object; + // Returns the first item in the receiver's menu that has a given + // represented object. + +- (void)selectItemWithRepresentedObject:(id)object; + // Selects the first item in the receiver's menu that has a give + // represented object. + +@end diff --git a/NSMenu+RepresentedObjectAccessors.m b/NSMenu+RepresentedObjectAccessors.m new file mode 100644 index 0000000..a63f083 --- /dev/null +++ b/NSMenu+RepresentedObjectAccessors.m @@ -0,0 +1,48 @@ +// +// NSMenu+RepresentedObjectAccessors.m +// Enjoyable +// +// Created by Joe Wreschnig on 3/4/13. +// +// + +#import "NSMenu+RepresentedObjectAccessors.h" + +@implementation NSMenu (RepresentedObjectAccessors) + +- (NSMenuItem *)itemWithRepresentedObject:(id)object { + for (NSMenuItem *item in self.itemArray) + if ([item.representedObject isEqual:object]) + return item; + return nil; +} + +- (void)removeItemWithRepresentedObject:(id)object { + NSInteger idx = [self indexOfItemWithRepresentedObject:object]; + if (idx != -1) + [self removeItemAtIndex:idx]; +} + +- (NSMenuItem *)lastItem { + return self.itemArray.lastObject; +} + +- (void)removeLastItem { + if (self.numberOfItems) + [self removeItemAtIndex:self.numberOfItems - 1]; +} + +@end + +@implementation NSPopUpButton (RepresentedObjectAccessors) + +- (NSMenuItem *)itemWithRepresentedObject:(id)object { + return [self.menu itemWithRepresentedObject:object]; +} + +- (void)selectItemWithRepresentedObject:(id)object { + [self selectItemAtIndex:[self indexOfItemWithRepresentedObject:object]]; +} + + +@end -- 2.20.1 From 6044e47a97de33531c47cd209b30d4405aa0530a Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Tue, 5 Mar 2013 01:45:48 +0100 Subject: [PATCH 13/16] Support sudden and automatic termination. --- English.lproj/MainMenu.xib | 29 +++++++++++++++++++---------- EnjoyableApplicationDelegate.h | 1 + EnjoyableApplicationDelegate.m | 25 +++++++++++++++++-------- Info.plist | 4 ++++ NJMappingsController.m | 2 ++ 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 32c3a86..00740ba 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -333,7 +333,6 @@ 268 {{0, 14}, {140, 25}} - _NS:9 YES @@ -383,7 +382,6 @@ 268 {{19, 14}, {67, 25}} - _NS:9 YES @@ -462,7 +460,7 @@ - + @@ -497,7 +495,7 @@ {200, 298} - + YES NO YES @@ -627,7 +625,7 @@ {202, 300} - + 150034 @@ -691,7 +689,6 @@ {{227, 55}, {180, 24}} - _NS:9 YES @@ -1036,7 +1033,7 @@ {198, 198} - + YES NO YES @@ -1128,7 +1125,7 @@ {{0, 20}, {200, 200}} - + 150034 @@ -1144,7 +1141,6 @@ {{66, -1}, {134, 23}} - _NS:22 YES @@ -1420,6 +1416,14 @@ 825 + + + window + + + + 865 + removePressed: @@ -2398,7 +2402,7 @@ - 864 + 865 @@ -2410,6 +2414,7 @@ NJDeviceController NJMappingsController NJOutputController + NSWindow @@ -2428,6 +2433,10 @@ outputController NJOutputController + + window + NSWindow + IBProjectSource diff --git a/EnjoyableApplicationDelegate.h b/EnjoyableApplicationDelegate.h index b77f799..6488135 100644 --- a/EnjoyableApplicationDelegate.h +++ b/EnjoyableApplicationDelegate.h @@ -12,6 +12,7 @@ @interface EnjoyableApplicationDelegate : NSObject { IBOutlet NSMenu *dockMenuBase; + IBOutlet NSWindow *window; } @property (nonatomic, strong) IBOutlet NJDeviceController *inputController; diff --git a/EnjoyableApplicationDelegate.m b/EnjoyableApplicationDelegate.m index 388103b..313ba9a 100644 --- a/EnjoyableApplicationDelegate.m +++ b/EnjoyableApplicationDelegate.m @@ -15,8 +15,8 @@ @implementation EnjoyableApplicationDelegate -- (void)didSwitchApplication:(NSNotification *)notification { - NSRunningApplication *currentApp = notification.userInfo[NSWorkspaceApplicationKey]; +- (void)didSwitchApplication:(NSNotification *)note { + NSRunningApplication *currentApp = note.userInfo[NSWorkspaceApplicationKey]; [self.mappingsController activateMappingForProcess:currentApp.localizedName]; } @@ -46,12 +46,18 @@ [self.mappingsController load]; } -- (void)applicationWillTerminate:(NSNotification *)aNotification { - [NSUserDefaults.standardUserDefaults synchronize]; - [NSNotificationCenter.defaultCenter removeObserver:self]; +- (void)applicationDidBecomeActive:(NSNotification *)notification { + [window makeKeyAndOrderFront:nil]; +} + +- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication + hasVisibleWindows:(BOOL)flag { + [window makeKeyAndOrderFront:nil]; + return NO; } - (void)eventTranslationActivated:(NSNotification *)note { + [NSProcessInfo.processInfo disableAutomaticTermination:@"Input translation is active."]; [NSWorkspace.sharedWorkspace.notificationCenter addObserver:self selector:@selector(didSwitchApplication:) @@ -61,6 +67,7 @@ } - (void)eventTranslationDeactivated:(NSNotification *)note { + [NSProcessInfo.processInfo enableAutomaticTermination:@"Input translation is active."]; [NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self name:NSWorkspaceDidActivateApplicationNotification @@ -75,10 +82,12 @@ int added = 0; for (NJMapping *mapping in mappings) { NSString *keyEquiv = ++added < 10 ? @(added).stringValue : @""; - NSMenuItem *item = [dockMenuBase addItemWithTitle:mapping.name - action:@selector(chooseMapping:) - keyEquivalent:keyEquiv]; + NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name + action:@selector(chooseMapping:) + keyEquivalent:keyEquiv]; item.representedObject = mapping; + item.state = mapping == self.mappingsController.currentMapping; + [dockMenuBase addItem:item]; } [_outputController refreshMappings]; } diff --git a/Info.plist b/Info.plist index 8deb6f0..2940aaf 100644 --- a/Info.plist +++ b/Info.plist @@ -2,6 +2,10 @@ + NSSupportsAutomaticTermination + YES + NSSupportsSuddenTermination + CFBundleDevelopmentRegion English CFBundleExecutable diff --git a/NJMappingsController.m b/NJMappingsController.m index 26ef35f..43f6282 100644 --- a/NJMappingsController.m +++ b/NJMappingsController.m @@ -281,6 +281,7 @@ if (result != NSFileHandlingPanelOKButton) return; [panel close]; + [NSProcessInfo.processInfo disableSuddenTermination]; NSError *error; NSDictionary *serialization = [mapping serialize]; NSData *json = [NSJSONSerialization dataWithJSONObject:serialization @@ -289,6 +290,7 @@ if (!error) [json writeToURL:panel.URL options:NSDataWritingAtomic error:&error]; + [NSProcessInfo.processInfo enableSuddenTermination]; if (error) { [window presentError:error modalForWindow:window -- 2.20.1 From 844a57be52a2e243832e3d83d148fa3cea6d5ad1 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Tue, 5 Mar 2013 01:56:13 +0100 Subject: [PATCH 14/16] Avoid repeating serialization codes. --- NJOutputKeyPress.m | 4 +++- NJOutputMapping.m | 2 +- NJOutputMouseButton.m | 2 +- NJOutputMouseMove.m | 2 +- NJOutputMouseScroll.m | 2 +- NJOutputSwitchMouseMode.m | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NJOutputKeyPress.m b/NJOutputKeyPress.m index 5371475..622cf41 100644 --- a/NJOutputKeyPress.m +++ b/NJOutputKeyPress.m @@ -16,7 +16,9 @@ } - (NSDictionary *)serialize { - return @{ @"type": @"key press", @"key": @(_vk) }; + return _vk != NJKeyInputFieldEmpty + ? @{ @"type": self.class.serializationCode, @"key": @(_vk) } + : nil; } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization diff --git a/NJOutputMapping.m b/NJOutputMapping.m index 5cd5d9f..6c1ba95 100644 --- a/NJOutputMapping.m +++ b/NJOutputMapping.m @@ -19,7 +19,7 @@ - (NSDictionary *)serialize { return _mapping - ? @{ @"type": @"mapping", @"name": _mapping.name } + ? @{ @"type": self.class.serializationCode, @"name": _mapping.name } : nil; } diff --git a/NJOutputMouseButton.m b/NJOutputMouseButton.m index 0cc403f..ad44b39 100644 --- a/NJOutputMouseButton.m +++ b/NJOutputMouseButton.m @@ -14,7 +14,7 @@ } - (NSDictionary *)serialize { - return @{ @"type": @"mouse button", @"button": @(_button) }; + return @{ @"type": self.class.serializationCode, @"button": @(_button) }; } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization diff --git a/NJOutputMouseMove.m b/NJOutputMouseMove.m index 3346fb2..8efb8cb 100644 --- a/NJOutputMouseMove.m +++ b/NJOutputMouseMove.m @@ -22,7 +22,7 @@ } - (NSDictionary *)serialize { - return @{ @"type": @"mouse move", @"axis": @(_axis) }; + return @{ @"type": self.class.serializationCode, @"axis": @(_axis) }; } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization diff --git a/NJOutputMouseScroll.m b/NJOutputMouseScroll.m index 2f6d2d6..4aa614d 100644 --- a/NJOutputMouseScroll.m +++ b/NJOutputMouseScroll.m @@ -16,7 +16,7 @@ } - (NSDictionary *)serialize { - return @{ @"type": @"mouse scroll", @"amount": @(_amount) }; + return @{ @"type": self.class.serializationCode, @"amount": @(_amount) }; } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization diff --git a/NJOutputSwitchMouseMode.m b/NJOutputSwitchMouseMode.m index 1750869..130a2a0 100644 --- a/NJOutputSwitchMouseMode.m +++ b/NJOutputSwitchMouseMode.m @@ -17,7 +17,7 @@ } - (NSDictionary *)serialize { - return @{ @"type": @"switch mouse mode" }; + return @{ @"type": self.class.serializationCode }; } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization -- 2.20.1 From 3eb4949fe4554cb4a32e1237571da4a96d26978c Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Tue, 5 Mar 2013 02:08:03 +0100 Subject: [PATCH 15/16] Subscribe the output controller to notifications directly. Application delegate has no more need to track the output controller. --- English.lproj/MainMenu.xib | 19 ++----------------- EnjoyableApplicationDelegate.h | 1 - EnjoyableApplicationDelegate.m | 1 - NJOutputController.h | 1 - NJOutputController.m | 21 +++++++++++++++++++-- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 00740ba..cc6ba01 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -329,10 +329,9 @@ Mapping Selector - + 268 {{0, 14}, {140, 25}} - _NS:9 YES @@ -378,10 +377,9 @@ Translation Switch - + 268 {{19, 14}, {67, 25}} - _NS:9 YES @@ -1408,14 +1406,6 @@ 820 - - - outputController - - - - 825 - window @@ -2413,7 +2403,6 @@ NSMenu NJDeviceController NJMappingsController - NJOutputController NSWindow @@ -2429,10 +2418,6 @@ mappingsController NJMappingsController - - outputController - NJOutputController - window NSWindow diff --git a/EnjoyableApplicationDelegate.h b/EnjoyableApplicationDelegate.h index 6488135..4615d12 100644 --- a/EnjoyableApplicationDelegate.h +++ b/EnjoyableApplicationDelegate.h @@ -16,7 +16,6 @@ } @property (nonatomic, strong) IBOutlet NJDeviceController *inputController; -@property (nonatomic, strong) IBOutlet NJOutputController *outputController; @property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController; @end diff --git a/EnjoyableApplicationDelegate.m b/EnjoyableApplicationDelegate.m index 313ba9a..1406115 100644 --- a/EnjoyableApplicationDelegate.m +++ b/EnjoyableApplicationDelegate.m @@ -89,7 +89,6 @@ item.state = mapping == self.mappingsController.currentMapping; [dockMenuBase addItem:item]; } - [_outputController refreshMappings]; } - (void)mappingDidChange:(NSNotification *)note { diff --git a/NJOutputController.h b/NJOutputController.h index 5b9a749..0c6a859 100644 --- a/NJOutputController.h +++ b/NJOutputController.h @@ -28,7 +28,6 @@ @property (assign) BOOL enabled; - (void)loadCurrent; -- (void)refreshMappings; - (IBAction)radioChanged:(id)sender; - (IBAction)mdirChanged:(id)sender; - (IBAction)mbtnChanged:(id)sender; diff --git a/NJOutputController.m b/NJOutputController.m index 5ceccba..0c301ff 100644 --- a/NJOutputController.m +++ b/NJOutputController.m @@ -10,6 +10,7 @@ #import "NJMappingsController.h" #import "NJMapping.h" #import "NJInput.h" +#import "NJEvents.h" #import "NJDeviceController.h" #import "NJKeyInputField.h" #import "NJOutputMapping.h" @@ -22,6 +23,21 @@ @implementation NJOutputController +- (id)init { + if ((self = [super init])) { + [NSNotificationCenter.defaultCenter + addObserver:self + selector:@selector(mappingListDidChange:) + name:NJEventMappingListChanged + object:nil]; + } + return self; +} + +- (void)dealloc { + [NSNotificationCenter.defaultCenter removeObserver:self]; +} + - (void)cleanUpInterface { NSInteger row = radioButtons.selectedRow; @@ -216,10 +232,11 @@ [keyInput resignIfFirstResponder]; } -- (void)refreshMappings { +- (void)mappingListDidChange:(NSNotification *)note { + NSArray *mappings = note.object; NJMapping *current = mappingPopup.selectedItem.representedObject; [mappingPopup.menu removeAllItems]; - for (NJMapping *mapping in mappingsController) { + for (NJMapping *mapping in mappings) { NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name action:@selector(mappingChosen:) keyEquivalent:@""]; -- 2.20.1 From ce24f5cc4eb879f248f3363663c5330a06b1046f Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Wed, 6 Mar 2013 01:04:31 +0100 Subject: [PATCH 16/16] Start help book. Tweak UI to deal with issues discovered trying to explain it. --- English.lproj/MainMenu.xib | 321 ++++++++++++++++-------- Enjoyable Help/Enjoyable Help.helpindex | Bin 0 -> 11228 bytes Enjoyable Help/Enjoyable Help.html | 73 ++++++ Enjoyable Help/gfx/Icon.png | Bin 0 -> 18084 bytes Enjoyable Help/pgs/keyboard.html | 59 +++++ Enjoyable Help/pgs/mappings.html | 49 ++++ Enjoyable Help/pgs/template.html | 41 +++ Enjoyable Help/sty/default.css | 1 + Enjoyable.xcodeproj/project.pbxproj | 4 + Info.plist | 4 + NJDeviceController.h | 3 +- NJDeviceController.m | 8 +- NJKeyInputField.m | 8 +- 13 files changed, 460 insertions(+), 111 deletions(-) create mode 100644 Enjoyable Help/Enjoyable Help.helpindex create mode 100644 Enjoyable Help/Enjoyable Help.html create mode 100644 Enjoyable Help/gfx/Icon.png create mode 100644 Enjoyable Help/pgs/keyboard.html create mode 100644 Enjoyable Help/pgs/mappings.html create mode 100644 Enjoyable Help/pgs/template.html create mode 100644 Enjoyable Help/sty/default.css diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index cc6ba01..402d345 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -62,7 +62,7 @@ Enjoyable - + CA 1048576 2147483647 @@ -299,6 +299,30 @@ _NSWindowsMenu + + + Help + + 2147483647 + + + submenuAction: + + Help + + + + Enjoyable Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + _NSMainMenu @@ -321,106 +345,100 @@ 2 1 - + - 4AC66688-76E8-47ED-AC0A-7462220A4019 + 2CB21E35-9CF1-4C67-9670-31139C914D10 - Mapping Selector - Mapping Selector + Enabled + Enabled - - + + 268 - {{0, 14}, {140, 25}} + {{7, 14}, {36, 25}} + + + _NS:9 YES - + 67108864 134217728 - (default) + LucidaGrande 13 1044 _NS:9 - - 918306816 + + -1228128256 163 - + NSImage - NSListViewTemplate + NSRightFacingTriangleTemplate - 400 - 75 + 200 + 25 NO - + - {13, 25} - {141, 25} + {36, 25} + {36, 25} YES - NO + YES 0 YES 0 - + - 94389EFE-310F-4DB5-95F6-D4AEE8839979 + 4AC66688-76E8-47ED-AC0A-7462220A4019 - Translation Switch - Translation Switch + Mapping Selector + Mapping Selector - - + + 268 - {{19, 14}, {67, 25}} + {{0, 14}, {140, 25}} + + + _NS:9 YES - + 67108864 - 0 + 134217728 + (default) _NS:9 - - - - 32 - - NSImage - NSActionTemplate - - Show and remap inputs - YES - 0 - - - 32 - - NSImage - NSRightFacingTriangleTemplate - - Run mapped actions - 1 - 0 - - - 4 + + 918306816 + 163 + + NSImage + NSListViewTemplate + + + + 400 + 75 NO - + - {67, 25} - {67, 25} + {13, 25} + {141, 25} YES - YES + NO 0 YES 0 @@ -455,13 +473,13 @@ - + - + @@ -493,7 +511,7 @@ {200, 298} - + YES NO YES @@ -623,7 +641,7 @@ {202, 300} - + 150034 @@ -687,6 +705,7 @@ {{227, 55}, {180, 24}} + _NS:9 YES @@ -824,7 +843,7 @@ 603979776 0 - Press a key: + Press a key 1211912448 @@ -852,7 +871,7 @@ 603979776 0 - Mouse movement + Move the mouse 1211912448 @@ -866,7 +885,7 @@ 603979776 0 - Mouse button + Press a mouse button 1211912448 @@ -880,7 +899,7 @@ 603979776 0 - Mouse scroll + Scroll the mouse 1211912448 @@ -1031,7 +1050,7 @@ {198, 198} - + YES NO YES @@ -1123,7 +1142,7 @@ {{0, 20}, {200, 200}} - + 150034 @@ -1139,6 +1158,7 @@ {{66, -1}, {134, 23}} + _NS:22 YES @@ -1270,6 +1290,14 @@ 732 + + + showHelp: + + + + 870 + orderFrontStandardAboutPanel: @@ -1366,21 +1394,29 @@ 826 + + + translatingEventsMenu + + + + 877 + translatingEventsChanged: - + - 858 + 878 - translatingEventsSetting + translatingEventsButton - + - 859 + 879 @@ -1622,6 +1658,14 @@ 818 + + + performClick: + + + + 871 + view @@ -1646,6 +1690,14 @@ 853 + + + performClick: + + + + 880 + @@ -1680,6 +1732,7 @@ + Main Menu @@ -1903,8 +1956,8 @@ - + @@ -2213,28 +2266,6 @@ - - 842 - - - - - - Translation Switch - - - 840 - - - - - - - - 841 - - - 849 @@ -2285,6 +2316,48 @@ + + 866 + + + + + + + + 867 + + + + + + + + 868 + + + + + 874 + + + + + + + + 872 + + + + + + + + 873 + + + @@ -2322,8 +2395,24 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Create a new mapping + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Remove the selected mapping + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2373,26 +2462,44 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Change the active mapping + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Enable mapped actions + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - 865 + 880 @@ -2446,7 +2553,8 @@ NJMappingsController NSOutlineView NJOutputController - NSSegmentedControl + NSButton + NSMenuItem @@ -2461,9 +2569,13 @@ outputController NJOutputController - - translatingEventsSetting - NSSegmentedControl + + translatingEventsButton + NSButton + + + translatingEventsMenu + NSMenuItem @@ -2644,7 +2756,6 @@ YES 3 - {15, 15} {8, 8} {11, 10} {11, 11} diff --git a/Enjoyable Help/Enjoyable Help.helpindex b/Enjoyable Help/Enjoyable Help.helpindex new file mode 100644 index 0000000000000000000000000000000000000000..54568b58fb0d72f2eb677575a670416ab7917f89 GIT binary patch literal 11228 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 IcIwoB0R^QXSpWb4 literal 0 HcmV?d00001 diff --git a/Enjoyable Help/Enjoyable Help.html b/Enjoyable Help/Enjoyable Help.html new file mode 100644 index 0000000..6a78ca4 --- /dev/null +++ b/Enjoyable Help/Enjoyable Help.html @@ -0,0 +1,73 @@ + + + + + Enjoyable Help + + + + + + + + + + + + +
+
+ Enjoyable Icon +
+
+

Enjoyable Help

+
+
+ +

+ Enjoyable helps you use a joystick or gamepad to control + applications which normally require a keyboard and mouse. +

+ +
+

Quick Start

+
    +
  • Connect a joystick or gamepad.
  • +
  • Press a button on it, then the keyboard key you want to use.
  • +
  • Press the ▶ button in the upper-right.
  • +
  • Start up your game and use your gamepad!
  • + +
+ +
+

+ + Keyboard Events +
+ Map buttons to keys on a keyboard. +

+

+ + Mouse Events +
+ Use analog axes and buttons to simulate a mouse. +

+

+ + Application Mappings +
+ Create and share mappings for different applications. +

+
+ +

+ + Visit the Enjoyable website. + +

+ + + diff --git a/Enjoyable Help/gfx/Icon.png b/Enjoyable Help/gfx/Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..36c4254a4eee7b7befe274333196bca2a6bcc0e7 GIT binary patch literal 18084 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 gh!7z{gfv$Ee^rP_!{7+&8vpk literal 0 HcmV?d00001 diff --git a/Enjoyable Help/pgs/keyboard.html b/Enjoyable Help/pgs/keyboard.html new file mode 100644 index 0000000..99c414d --- /dev/null +++ b/Enjoyable Help/pgs/keyboard.html @@ -0,0 +1,59 @@ + + + + + Keyboard Events + + + + + + + + + + +
+
+ Enjoyable Icon +
+

Keyboard Events

+
+ +

+ Enjoyable supports mapping joystick buttons, hat switches, and + axis thresholds to simulate keyboard keys. To do this, first + press the button on the joystick you want to map. This will + select it on the left-hand side of the screen. +

+ +

+ If the button wasn't mapped, or was mapped to a key press + already, the key input field activates and you can simply press + the key you want to use. Otherwise, click on the Press a + key label or input field, then press the key. +

+ +

Clearing the Selection

+

+ To clear a mapped key, either select the Do nothing + option, or press ⌥⌫ when the key input field is selected. +

+ +

Cancelling the Selection

+

+ If you select the key input field by mistake, you can press ⌥⎋ + to cancel the selection without changing the current setting. +

+ + diff --git a/Enjoyable Help/pgs/mappings.html b/Enjoyable Help/pgs/mappings.html new file mode 100644 index 0000000..c6d8af4 --- /dev/null +++ b/Enjoyable Help/pgs/mappings.html @@ -0,0 +1,49 @@ + + + + + Discover Sample App + + + + + + + + + +
+
+$APPNAME$$ Icon +
+
+

Manage Application Mappings

+
+
+ +

Changing Dynamically

+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas auctor leo in lorem dapibus eu tincidunt lacus viverra. Integer auctor tortor vel mauris pellentesque ultricies. Nulla lobortis, leo in facilisis cursus, elit felis viverra orci, ac luctus tellus sapien vel lectus. Aliquam ac accumsan risus. Nullam posuere, lectus commodo vestibulum luctus, mauris quam porta velit, ut pretium purus quam eu lacus. Nam in dui a sapien viverra euismod. Proin vel mauris nisi, sed tincidunt mi. Phasellus id ligula vitae mauris dapibus suscipit. Sed id erat nunc, in ultricies arcu. + +Nulla semper, magna non aliquam fringilla, turpis est convallis tortor, ut blandit elit orci nec elit. Phasellus id urna justo, a tristique mauris. Morbi sed nulla et lacus facilisis posuere et a purus. Morbi a dui quam. Nunc luctus ipsum ut purus sollicitudin cursus. Nulla facilisi. In vestibulum orci eu nunc euismod ut iaculis lacus commodo. Sed leo dolor, sagittis eu vulputate eget, accumsan eu leo. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas auctor leo in lorem dapibus eu tincidunt lacus viverra. Integer auctor tortor vel mauris pellentesque ultricies. Nulla lobortis, leo in facilisis cursus, elit felis viverra orci, ac luctus tellus sapien vel lectus. Aliquam ac accumsan risus. Nullam posuere, lectus commodo vestibulum luctus, mauris quam porta velit, ut pretium purus quam eu lacus. Nam in dui a sapien viverra euismod. Proin vel mauris nisi, sed tincidunt mi. Phasellus id ligula vitae mauris dapibus suscipit. Sed id erat nunc, in ultricies arcu. + +Nulla semper, magna non aliquam fringilla, turpis est convallis tortor, ut blandit elit orci nec elit. Phasellus id urna justo, a tristique mauris. Morbi sed nulla et lacus facilisis posuere et a purus. Morbi a dui quam. Nunc luctus ipsum ut purus sollicitudin cursus. Nulla facilisi. In vestibulum orci eu nunc euismod ut iaculis lacus commodo. Sed leo dolor, sagittis eu vulputate eget, accumsan eu leo. + + + +

Automatic Switching

+ +

Sharing Mappings

+ + + diff --git a/Enjoyable Help/pgs/template.html b/Enjoyable Help/pgs/template.html new file mode 100644 index 0000000..daba5e5 --- /dev/null +++ b/Enjoyable Help/pgs/template.html @@ -0,0 +1,41 @@ + + + + + Title + + + + + + + + + + +
+
+ Icon +
+

Title

+
+ +

+ Content starts here. +

+ + diff --git a/Enjoyable Help/sty/default.css b/Enjoyable Help/sty/default.css new file mode 100644 index 0000000..58b7747 --- /dev/null +++ b/Enjoyable Help/sty/default.css @@ -0,0 +1 @@ +body { font-size: 8pt; font-family: "Lucida Grande", Arial, sans-serif; line-height: 12pt; text-decoration: none; margin-right: 1em; margin-left: 1em; } #navbox { background-color: #f2f2f2; position: fixed; top: 0; left: 0; width: 100%; height: 1.5em; float: left; border-bottom: 1px solid #bfbfbf } #navleftbox { position: absolute; top: 1px; left: 15px } #navrightbox { background-color: #f2f2f2; padding-right: 25px; float: right; padding-bottom: 1px; border-left: 1px solid #bfbfbf } #navbox a { font-size: 8pt; color: #666; font-weight: normal; margin: -9px 0 -6px; } #headerbox { margin-top: 36px; padding-right: 6px; margin-bottom: 2em; } #iconbox { float: left; } h1 { margin-left: 40px; width: 88%; font-size: 15pt; line-height: 15pt; font-weight: bold; padding-top: 6px; margin-bottom: 0; } h2 { font-size: 11pt; line-height: 12pt; font-weight: bold; color: black; margin-top: 0; margin-bottom: 11px; } h3 { font-size: 8pt; font-weight: bold; letter-spacing: 0.1em; line-height: 8pt; color: #666; margin-top: 1em; margin-bottom: 0px; padding-bottom: 0.5em; } p { margin-left: 0px; margin-top: 0px; margin-bottom: 0.5em; } ul { margin-left: 2em; margin-top: 6px; margin-bottom: 0px; padding-left: 0px; } li { margin-left: 0px; } a { color: #778fbd; font-size: 9pt; font-weight: bold; text-decoration: none; } a:hover { text-decoration: underline; } .weblink { color: #666; font-weight: normal; } \ No newline at end of file diff --git a/Enjoyable.xcodeproj/project.pbxproj b/Enjoyable.xcodeproj/project.pbxproj index c2f3246..4537688 100644 --- a/Enjoyable.xcodeproj/project.pbxproj +++ b/Enjoyable.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ D594BF830FAE9661007A85F2 /* EnjoyableApplicationDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D594BF820FAE9661007A85F2 /* EnjoyableApplicationDelegate.m */; }; D5F809710FB093400006A4DE /* NJOutputMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = D5F809700FB093400006A4DE /* NJOutputMapping.m */; }; D5F80A9D0FB0A2FF0006A4DE /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = D5617A080FAEAF8300928B3A /* icon.icns */; }; + EE03150D16E63481002B2DCE /* Enjoyable Help in Resources */ = {isa = PBXBuildFile; fileRef = EE03150C16E63481002B2DCE /* Enjoyable Help */; }; EE1D7C9216E01E7000B000EB /* NSView+FirstResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */; }; EE1D7C9616E0ECCF00B000EB /* NSError+Description.m in Sources */ = {isa = PBXBuildFile; fileRef = EE1D7C9516E0ECCF00B000EB /* NSError+Description.m */; }; EE96929416E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m in Sources */ = {isa = PBXBuildFile; fileRef = EE96929316E54B480054A3C8 /* NSMenu+RepresentedObjectAccessors.m */; }; @@ -86,6 +87,7 @@ D594BF820FAE9661007A85F2 /* EnjoyableApplicationDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EnjoyableApplicationDelegate.m; sourceTree = ""; }; D5F8096F0FB093400006A4DE /* NJOutputMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJOutputMapping.h; sourceTree = ""; }; D5F809700FB093400006A4DE /* NJOutputMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJOutputMapping.m; sourceTree = ""; }; + EE03150C16E63481002B2DCE /* Enjoyable Help */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Enjoyable Help"; sourceTree = ""; }; EE1D7C9016E01E7000B000EB /* NSView+FirstResponder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSView+FirstResponder.h"; sourceTree = ""; }; EE1D7C9116E01E7000B000EB /* NSView+FirstResponder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSView+FirstResponder.m"; sourceTree = ""; }; EE1D7C9416E0ECCF00B000EB /* NSError+Description.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Description.h"; sourceTree = ""; }; @@ -205,6 +207,7 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + EE03150C16E63481002B2DCE /* Enjoyable Help */, D549CA4B0FBB441B00BC8203 /* Credits.rtf */, D5617A080FAEAF8300928B3A /* icon.icns */, 8D1107310486CEB800E47090 /* Info.plist */, @@ -293,6 +296,7 @@ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */, D5F80A9D0FB0A2FF0006A4DE /* icon.icns in Resources */, D549CA4C0FBB441B00BC8203 /* Credits.rtf in Resources */, + EE03150D16E63481002B2DCE /* Enjoyable Help in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Info.plist b/Info.plist index 2940aaf..4a530d9 100644 --- a/Info.plist +++ b/Info.plist @@ -2,6 +2,10 @@ + CFBundleHelpBookName + Enjoyable Help + CFBundleHelpBookFolder + Enjoyable Help NSSupportsAutomaticTermination YES NSSupportsSuddenTermination diff --git a/NJDeviceController.h b/NJDeviceController.h index cfa6d99..4e50fa4 100644 --- a/NJDeviceController.h +++ b/NJDeviceController.h @@ -15,7 +15,8 @@ IBOutlet NSOutlineView *outlineView; IBOutlet NJOutputController *outputController; IBOutlet NJMappingsController *mappingsController; - IBOutlet NSSegmentedControl *translatingEventsSetting; + IBOutlet NSButton *translatingEventsButton; + IBOutlet NSMenuItem *translatingEventsMenu; } @property (nonatomic, readonly) NJInput *selectedInput; diff --git a/NJDeviceController.m b/NJDeviceController.m index f5da6dd..7993842 100644 --- a/NJDeviceController.m +++ b/NJDeviceController.m @@ -224,7 +224,9 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn - (void)setTranslatingEvents:(BOOL)translatingEvents { if (translatingEvents != _translatingEvents) { _translatingEvents = translatingEvents; - translatingEventsSetting.selectedSegment = !!translatingEvents; + NSInteger state = translatingEvents ? NSOnState : NSOffState; + translatingEventsButton.state = state; + translatingEventsMenu.title = translatingEvents ? @"Disable" : @"Enable"; NSString *name = translatingEvents ? NJEventTranslationActivated : NJEventTranslationDeactivated; @@ -233,8 +235,8 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn } } -- (IBAction)translatingEventsChanged:(id)sender { - self.translatingEvents = translatingEventsSetting.selectedSegment; +- (IBAction)translatingEventsChanged:(NSButton *)sender { + self.translatingEvents = sender.state == NSOnState; } diff --git a/NJKeyInputField.m b/NJKeyInputField.m index b159aa3..ec08150 100644 --- a/NJKeyInputField.m +++ b/NJKeyInputField.m @@ -176,10 +176,14 @@ CGKeyCode NJKeyInputFieldEmpty = 0xFFFF; - (void)keyDown:(NSEvent *)theEvent { if (!theEvent.isARepeat) { if ((theEvent.modifierFlags & NSAlternateKeyMask) - && theEvent.keyCode == 0x35) { - // Allow Alt+Escape to clear the field. + && theEvent.keyCode == 0x33) { + // Allow Alt+Backspace to clear the field. self.keyCode = NJKeyInputFieldEmpty; [self.keyDelegate keyInputFieldDidClear:self]; + } else if ((theEvent.modifierFlags & NSAlternateKeyMask) + && theEvent.keyCode == 0x35) { + // Allow Alt+Escape to cancel. + ; } else { self.keyCode = theEvent.keyCode; [self.keyDelegate keyInputField:self didChangeKey:_keyCode]; -- 2.20.1