#import "NJMappingMenuController.h"
#import "NJMappingsViewController.h"
+#import "NJDeviceViewController.h"
+#import "NJOutputController.h"
+#import "NJDeviceController.h"
@interface EnjoyableApplicationDelegate : NSObject <NSApplicationDelegate,
+ NJDeviceControllerDelegate,
+ NJDeviceViewControllerDelegate,
NJMappingsViewControllerDelegate,
NJMappingMenuDelegate,
NSWindowDelegate> {
}
@property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController;
+@property (nonatomic, strong) IBOutlet NJDeviceController *deviceController;
+@property (nonatomic, strong) IBOutlet NJOutputController *outputController;
@property (nonatomic, strong) IBOutlet NJMappingsViewController *mvc;
+@property (nonatomic, strong) IBOutlet NJDeviceViewController *dvc;
- (IBAction)restoreToForeground:(id)sender;
- (IBAction)importMappingClicked:(id)sender;
[self.mappingsController activateMapping:self.mappingsController[idx]];
}
+- (id)deviceViewController:(NJDeviceViewController *)dvc
+ elementForUID:(NSString *)uid {
+ return self.deviceController[uid];
+}
+
+- (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)dvc {
+ [self.outputController loadInput:dvc.selectedHandler];
+}
+
+- (void)deviceViewController:(NJDeviceViewController *)dvc
+ didSelectBranch:(NJInputPathElement *)handler {
+ [self.outputController loadInput:dvc.selectedHandler];
+}
+
+- (void)deviceViewController:(NJDeviceViewController *)dvc
+ didSelectHandler:(NJInputPathElement *)handler {
+ [self.outputController loadInput:dvc.selectedHandler];
+}
+
+- (void)deviceViewController:(NJDeviceViewController *)dvc
+ didSelectDevice:(NJInputPathElement *)device {
+ [self.outputController loadInput:dvc.selectedHandler];
+}
+
+- (void)deviceController:(NJDeviceController *)dc
+ didAddDevice:(NJDevice *)device {
+ [self.dvc addedDevice:device atIndex:dc.count - 1];
+}
+
+- (void)deviceController:(NJDeviceController *)dc
+ didRemoveDeviceAtIndex:(NSInteger)idx {
+ [self.dvc removedDeviceAtIndex:idx];
+}
+
+- (void)deviceControllerDidStartHID:(NJDeviceController *)dc {
+ [self.dvc hidStarted];
+}
+
+- (void)deviceControllerDidStopHID:(NJDeviceController *)dc {
+ [self.dvc hidStopped];
+}
+
+- (void)deviceController:(NJDeviceController *)dc didInput:(NJInput *)input {
+ [self.outputController loadInput:input];
+ [self.outputController focusKey];
+}
+
+- (void)deviceController:(NJDeviceController *)dc didError:(NSError *)error {
+ // Since the error shows the window, it can trigger another attempt
+ // to re-open the HID manager, which will also probably fail and error,
+ // so don't bother repeating ourselves.
+ if (!window.attachedSheet) {
+ [NSApplication.sharedApplication activateIgnoringOtherApps:YES];
+ [window makeKeyAndOrderFront:nil];
+ [window presentError:error
+ modalForWindow:window
+ delegate:nil
+ didPresentSelector:nil
+ contextInfo:nil];
+ }
+}
+
+- (NSInteger)numberOfDevicesInDeviceList:(NJDeviceViewController *)dvc {
+ return self.deviceController.count;
+}
+
+- (NJDevice *)deviceViewController:(NJDeviceViewController *)dvc
+ deviceForIndex:(NSUInteger)idx {
+ return self.deviceController[idx];
+}
+
@end
@class NJInput;
@class NJMappingsController;
-@class NJOutputController;
-@interface NJDeviceController : NSObject <NJDeviceViewControllerDelegate,
- NJHIDManagerDelegate> {
- IBOutlet NJOutputController *outputController;
+@protocol NJDeviceControllerDelegate;
+
+@interface NJDeviceController : NSObject <NJHIDManagerDelegate> {
IBOutlet NJMappingsController *mappingsController;
IBOutlet NSButton *simulatingEventsButton;
- IBOutlet NJDeviceViewController *devicesViewController;
}
-@property (nonatomic, readonly) NJInput *selectedInput;
+@property (nonatomic, weak) IBOutlet id <NJDeviceControllerDelegate> delegate;
+
@property (nonatomic, assign) NSPoint mouseLoc;
@property (nonatomic, assign) BOOL simulatingEvents;
- (IBAction)simulatingEventsChanged:(NSButton *)sender;
+- (NJDevice *)objectAtIndexedSubscript:(NSUInteger)idx;
+- (NJInputPathElement *)objectForKeyedSubscript:(NSString *)uid;
+- (NSUInteger)count;
+
+@end
+
+@protocol NJDeviceControllerDelegate
+
+- (void)deviceController:(NJDeviceController *)dc didAddDevice:(NJDevice *)device;
+- (void)deviceController:(NJDeviceController *)dc didRemoveDeviceAtIndex:(NSInteger)idx;
+- (void)deviceController:(NJDeviceController *)dc didInput:(NJInput *)input;
+- (void)deviceControllerDidStartHID:(NJDeviceController *)dc;
+- (void)deviceControllerDidStopHID:(NJDeviceController *)dc;
+- (void)deviceController:(NJDeviceController *)dc didError:(NSError *)error;
+
@end
#import "NJDevice.h"
#import "NJInput.h"
#import "NJOutput.h"
-#import "NJOutputController.h"
#import "NJEvents.h"
#import "NJDeviceViewController.h"
[_continuousOutputsTick invalidate];
}
+- (NJDevice *)objectAtIndexedSubscript:(NSUInteger)idx {
+ return idx < _devices.count ? _devices[idx] : nil;
+}
+
+- (NSUInteger)count {
+ return _devices.count;
+}
+
- (void)addRunningOutput:(NJOutput *)output {
// Axis events will trigger every small movement, don't keep
// re-adding them or they trigger multiple times each time.
if (!handler)
return;
- [devicesViewController expandAndSelectItem:handler];
- [outputController focusKey];
+ [self.delegate deviceController:self didInput:handler];
}
- (void)hidManager:(NJHIDManager *)manager
- (void)hidManager:(NJHIDManager *)manager deviceAdded:(IOHIDDeviceRef)device {
NJDevice *match = [[NJDevice alloc] initWithDevice:device];
- [devicesViewController beginUpdates];
[self addDevice:match];
- [devicesViewController addedDevice:match atIndex:_devices.count - 1];
- [devicesViewController endUpdates];
+ [self.delegate deviceController:self didAddDevice:match];
}
- (NJDevice *)findDeviceByRef:(IOHIDDeviceRef)device {
- (void)hidManager:(NJHIDManager *)manager deviceRemoved:(IOHIDDeviceRef)device {
NJDevice *match = [self findDeviceByRef:device];
- IOHIDDeviceRegisterInputValueCallback(device, NULL, NULL);
if (match) {
NSInteger idx = [_devices indexOfObjectIdenticalTo:match];
- [devicesViewController beginUpdates];
[_devices removeObjectAtIndex:idx];
- [devicesViewController removedDevice:match atIndex:idx];
- [devicesViewController endUpdates];
+ [self.delegate deviceController:self didRemoveDeviceAtIndex:idx];
}
}
}
- (void)hidManager:(NJHIDManager *)manager didError:(NSError *)error {
- // Since the error shows the window, it can trigger another attempt
- // to re-open the HID manager, which will also probably fail and error,
- // so don't bother repeating ourselves.
- if (!simulatingEventsButton.window.attachedSheet) {
- [NSApplication.sharedApplication activateIgnoringOtherApps:YES];
- [simulatingEventsButton.window makeKeyAndOrderFront:nil];
- [simulatingEventsButton.window presentError:error
- modalForWindow:simulatingEventsButton.window
- delegate:nil
- didPresentSelector:nil
- contextInfo:nil];
- }
+ [self.delegate deviceController:self didError:error];
self.simulatingEvents = NO;
}
- (void)hidManagerDidStart:(NJHIDManager *)manager {
- [devicesViewController hidStarted];
+ [self.delegate deviceControllerDidStartHID:self];
}
- (void)hidManagerDidStop:(NJHIDManager *)manager {
[_devices removeAllObjects];
- [devicesViewController hidStopped];
+ [self.delegate deviceControllerDidStopHID:self];
}
- (void)startHid {
[_hidManager stop];
}
-- (NJInput *)selectedInput {
- return (NJInput *)devicesViewController.selectedHandler;
-}
-
- (void)setSimulatingEvents:(BOOL)simulatingEvents {
if (simulatingEvents != _simulatingEvents) {
_simulatingEvents = simulatingEvents;
return _devices[idx];
}
-- (id)deviceViewController:(NJDeviceViewController *)dvc
- elementForUID:(NSString *)uid {
+- (NJInputPathElement *)objectForKeyedSubscript:(NSString *)uid {
for (NJDevice *dev in _devices) {
id item = [dev elementForUID:uid];
if (item)
return nil;
}
-- (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)dvc {
- [outputController loadCurrent];
-}
-
-- (void)deviceViewController:(NJDeviceViewController *)dvc
- didSelectBranch:(NJInputPathElement *)handler {
- [outputController loadCurrent];
-}
-
-- (void)deviceViewController:(NJDeviceViewController *)dvc
- didSelectHandler:(NJInputPathElement *)handler {
- [outputController loadCurrent];
-}
-
-- (void)deviceViewController:(NJDeviceViewController *)dvc
- didSelectDevice:(NJInputPathElement *)device {
- [outputController loadCurrent];
-}
-
@end
//
@class NJDevice;
+@class NJInput;
@class NJInputPathElement;
@protocol NJDeviceViewControllerDelegate;
@property (nonatomic, weak) IBOutlet id <NJDeviceViewControllerDelegate> delegate;
- (void)addedDevice:(NJDevice *)device atIndex:(NSUInteger)idx;
-- (void)removedDevice:(NJDevice *)device atIndex:(NSUInteger)idx;
- // But using these will animate nicely.
+- (void)removedDeviceAtIndex:(NSUInteger)idx;
- (void)hidStarted;
- (void)hidStopped;
-- (void)beginUpdates;
-- (void)endUpdates;
-
- (void)expandAndSelectItem:(NJInputPathElement *)item;
-- (NJInputPathElement *)selectedHandler;
+- (NJInput *)selectedHandler;
@end
[self expandRecursive:[self.delegate deviceViewController:self elementForUID:uid]];
}
-- (void)beginUpdates {
- [self.inputsTree beginUpdates];
-}
-
-- (void)endUpdates {
- [self.inputsTree endUpdates];
-}
-
- (void)reexpandAll {
for (NSString *uid in [_expanded copy])
[self expandRecursiveByUID:uid];
}
- (void)addedDevice:(NJDevice *)device atIndex:(NSUInteger)idx {
+ [self.inputsTree beginUpdates];
[self.inputsTree insertItemsAtIndexes:[[NSIndexSet alloc] initWithIndex:idx]
inParent:nil
withAnimation:NSTableViewAnimationEffectFade];
[self reexpandAll];
+ [self.inputsTree endUpdates];
self.noDevicesNotice.hidden = YES;
}
-- (void)removedDevice:(NJDevice *)device atIndex:(NSUInteger)idx {
+- (void)removedDeviceAtIndex:(NSUInteger)idx {
BOOL anyDevices = !![self.delegate numberOfDevicesInDeviceList:self];
+ [self.inputsTree beginUpdates];
[self.inputsTree removeItemsAtIndexes:[[NSIndexSet alloc] initWithIndex:idx]
inParent:nil
withAnimation:NSTableViewAnimationEffectFade];
+ [self.inputsTree endUpdates];
self.noDevicesNotice.hidden = anyDevices || !self.hidStoppedNotice.isHidden;
}
return ![self outlineView:outlineView isGroupItem:item];
}
-- (NJInputPathElement *)selectedHandler {
+- (NJInput *)selectedHandler {
NJInputPathElement *element = self.inputsTree.selectedItem;
- return element.children ? nil : element;
+ return element.children ? nil : (NJInput *)element;
}
-
-
@end
_manualMapping = oldMapping;
}
+- (void)activateMappingForcibly:(NJMapping *)mapping {
+ NSLog(@"Switching to mapping %@.", mapping.name);
+ _currentMapping = mapping;
+ NSUInteger idx = [self indexOfMapping:_currentMapping];
+ [NSNotificationCenter.defaultCenter
+ postNotificationName:NJEventMappingChanged
+ object:self
+ userInfo:@{ NJMappingKey : _currentMapping,
+ NJMappingIndexKey: @(idx) }];
+}
+
- (void)activateMapping:(NJMapping *)mapping {
if (!mapping)
mapping = _manualMapping;
if (mapping == _currentMapping)
return;
- NSLog(@"Switching to mapping %@.", mapping.name);
_manualMapping = mapping;
- _currentMapping = mapping;
- NSUInteger idx = [self indexOfMapping:_currentMapping];
- [NSNotificationCenter.defaultCenter
- postNotificationName:NJEventMappingChanged
- object:self
- userInfo:@{ NJMappingKey : _currentMapping,
- NJMappingIndexKey: @(idx) }];
+ [self activateMappingForcibly:mapping];
}
- (void)save {
- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing {
[existing mergeEntriesFrom:mapping];
[self mappingsChanged];
- if (existing == _currentMapping) {
- // FIXME: Hack to trigger updates in the rest of the UI.
- _currentMapping = nil;
- NJMapping *manual = _manualMapping;
- [self activateMapping:existing];
- _manualMapping = manual;
- }
+ if (existing == _currentMapping)
+ [self activateMappingForcibly:mapping];
}
- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name {
mapping.name = name;
[self mappingsChanged];
- if (mapping == _currentMapping) {
- // FIXME: Hack to trigger updates in the rest of the UI.
- _currentMapping = nil;
- NJMapping *manual = _manualMapping;
- [self activateMapping:mapping];
- _manualMapping = manual;
- }
+ if (mapping == _currentMapping)
+ [self activateMappingForcibly:mapping];
}
- (void)addMapping:(NJMapping *)mapping {
@class NJMappingsController;
@class NJDeviceController;
@class NJOutput;
-@class NJOutputMouseMove;
+@class NJInput;
@interface NJOutputController : NSObject <NJKeyInputFieldDelegate> {
IBOutlet NJKeyInputField *keyInput;
IBOutlet NSTextField *title;
IBOutlet NSPopUpButton *mappingPopup;
IBOutlet NJMappingsController *mappingsController;
- IBOutlet NJDeviceController *inputController;
IBOutlet NSButton *smoothCheck;
IBOutlet NSButton *unknownMapping;
}
@property (assign) BOOL enabled;
-- (void)loadCurrent;
+- (void)loadInput:(NJInput *)input;
- (IBAction)radioChanged:(id)sender;
- (IBAction)mdirChanged:(id)sender;
- (IBAction)mbtnChanged:(id)sender;
#import "NJOutputMouseMove.h"
#import "NJOutputMouseScroll.h"
-@implementation NJOutputController
+@implementation NJOutputController {
+ NJInput *_input;
+}
- (id)init {
if ((self = [super init])) {
}
- (NJOutput *)currentOutput {
- return mappingsController.currentMapping[inputController.selectedInput];
+ return mappingsController.currentMapping[_input];
}
- (NJOutput *)makeOutput {
- (void)commit {
[self cleanUpInterface];
- mappingsController.currentMapping[inputController.selectedInput] = [self makeOutput];
+ mappingsController.currentMapping[_input] = [self makeOutput];
[mappingsController save];
}
[self cleanUpInterface];
}
-- (void)loadCurrent {
- [self loadOutput:self.currentOutput forInput:inputController.selectedInput];
+- (void)loadInput:(NJInput *)input {
+ _input = input;
+ [self loadOutput:self.currentOutput forInput:input];
}
- (void)focusKey {
}
- (void)mappingDidChange:(NSNotification *)note {
- [self loadCurrent];
+ [self loadInput:_input];
}
@end
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>526</string>
+ <string>535</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>NSHumanReadableCopyright</key>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
- <string key="label">devicesViewController</string>
+ <string key="label">delegate</string>
<reference key="source" ref="1007832501"/>
- <reference key="destination" ref="647344717"/>
+ <reference key="destination" ref="207406104"/>
</object>
- <int key="connectionID">992</int>
+ <int key="connectionID">1029</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
</object>
<int key="connectionID">1024</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">dvc</string>
+ <reference key="source" ref="207406104"/>
+ <reference key="destination" ref="647344717"/>
+ </object>
+ <int key="connectionID">1025</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">deviceController</string>
+ <reference key="source" ref="207406104"/>
+ <reference key="destination" ref="1007832501"/>
+ </object>
+ <int key="connectionID">1026</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">outputController</string>
+ <reference key="source" ref="207406104"/>
+ <reference key="destination" ref="801536542"/>
+ </object>
+ <int key="connectionID">1027</int>
+ </object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">performClick:</string>
</object>
<int key="connectionID">821</int>
</object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">inputController</string>
- <reference key="source" ref="801536542"/>
- <reference key="destination" ref="1007832501"/>
- </object>
- <int key="connectionID">828</int>
- </object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">mouseDirSelect</string>
</object>
<int key="connectionID">969</int>
</object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">delegate</string>
- <reference key="source" ref="647344717"/>
- <reference key="destination" ref="1007832501"/>
- </object>
- <int key="connectionID">984</int>
- </object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">hidStoppedNotice</string>
</object>
<int key="connectionID">989</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="647344717"/>
+ <reference key="destination" ref="207406104"/>
+ </object>
+ <int key="connectionID">1028</int>
+ </object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">view</string>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
- <int key="maxID">1024</int>
+ <int key="maxID">1029</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>