@class NJInputController;
@class TargetController;
-@class ConfigsController;
+@class NJMappingsController;
@interface ApplicationController : NSObject <NSApplicationDelegate> {
IBOutlet NSDrawer *drawer;
IBOutlet NSMenu *dockMenuBase;
}
-@property (nonatomic, strong) IBOutlet NJInputController *jsController;
+@property (nonatomic, strong) IBOutlet NJInputController *inputController;
@property (nonatomic, strong) IBOutlet TargetController *targetController;
-@property (nonatomic, strong) IBOutlet ConfigsController *configsController;
+@property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController;
- (IBAction)toggleActivity:(id)sender;
-- (void)configsChanged;
+- (void)mappingsChanged;
@end
#import "ApplicationController.h"
-#import "Config.h"
-#import "ConfigsController.h"
+#import "NJMapping.h"
+#import "NJMappingsController.h"
#import "NJInputController.h"
#import "TargetController.h"
#import "NJEvents.h"
- (void)didSwitchApplication:(NSNotification *)notification {
NSRunningApplication *currentApp = notification.userInfo[NSWorkspaceApplicationKey];
- [self.configsController activateConfigForProcess:currentApp.localizedName];
+ [self.mappingsController activateMappingForProcess:currentApp.localizedName];
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
[drawer open];
self.targetController.enabled = NO;
- [self.jsController setup];
- [self.configsController load];
+ [self.inputController setup];
+ [self.mappingsController load];
[NSNotificationCenter.defaultCenter
addObserver:self
selector:@selector(mappingDidChange:)
}
- (IBAction)toggleActivity:(id)sender {
- self.jsController.translatingEvents = !self.jsController.translatingEvents;
+ self.inputController.translatingEvents = !self.inputController.translatingEvents;
}
-- (NSInteger)firstConfigMenuIndex {
+- (NSInteger)firstMappingMenuIndex {
for (NSInteger i = dockMenuBase.numberOfItems - 1; i >= 0; --i)
if ([dockMenuBase itemAtIndex:i].isSeparatorItem)
return i + 1;
return dockMenuBase.numberOfItems;
}
-- (void)configsChanged {
- NSInteger removeFrom = self.firstConfigMenuIndex;
+- (void)mappingsChanged {
+ NSInteger removeFrom = self.firstMappingMenuIndex;
while (dockMenuBase.numberOfItems > removeFrom)
[dockMenuBase removeItemAtIndex:dockMenuBase.numberOfItems - 1];
int added = 0;
- for (Config *config in self.configsController.configs) {
+ for (NJMapping *mapping in self.mappingsController.mappings) {
NSString *keyEquiv = ++added < 10 ? @(added).stringValue : @"";
- [dockMenuBase addItemWithTitle:config.name
- action:@selector(chooseConfig:)
+ [dockMenuBase addItemWithTitle:mapping.name
+ action:@selector(chooseMapping:)
keyEquivalent:keyEquiv];
}
- [_targetController refreshConfigs];
+ [_targetController refreshMappings];
}
- (void)mappingDidChange:(NSNotification *)note {
- NSInteger firstConfig = self.firstConfigMenuIndex;
- Config *current = note.object;
- NSArray *configs = self.configsController.configs;
- for (NSUInteger i = 0; i < configs.count; ++i)
- [dockMenuBase itemAtIndex:i + firstConfig].state = configs[i] == current;
+ 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;
}
-- (void)chooseConfig:(id)sender {
- NSInteger idx = [dockMenuBase indexOfItem:sender] - self.firstConfigMenuIndex;
- Config *chosen = self.configsController.configs[idx];
- [_configsController activateConfig:chosen];
+- (void)chooseMapping:(id)sender {
+ NSInteger idx = [dockMenuBase indexOfItem:sender] - self.firstMappingMenuIndex;
+ NJMapping *chosen = self.mappingsController.mappings[idx];
+ [_mappingsController activateMapping:chosen];
}
@end
+++ /dev/null
-//
-// Config.h
-// Enjoy
-//
-// Created by Sam McCall on 4/05/09.
-// Copyright 2009 University of Otago. All rights reserved.
-//
-
-@class Target;
-@class NJInput;
-
-@interface Config : NSObject
-
-@property (nonatomic, copy) NSString *name;
-@property (nonatomic, readonly) NSMutableDictionary *entries;
-
-- (id)initWithName:(NSString *)name;
-- (Target *)objectForKeyedSubscript:(NJInput *)input;
-- (void)setObject:(Target *)target forKeyedSubscript:(NJInput *)input;
-- (NSDictionary *)serialize;
-
-@end
+++ /dev/null
-//
-// Config.m
-// Enjoy
-//
-// Created by Sam McCall on 4/05/09.
-//
-
-#import "Config.h"
-
-#import "NJInput.h"
-
-@implementation Config
-
-- (id)initWithName:(NSString *)name {
- if ((self = [super init])) {
- self.name = name ? name : @"Untitled";
- _entries = [[NSMutableDictionary alloc] init];
- }
- return self;
-}
-
-- (Target *)objectForKeyedSubscript:(NJInput *)input {
- return input ? _entries[input.uid] : nil;
-}
-
-- (void)setObject:(Target *)target forKeyedSubscript:(NJInput *)input {
- if (input) {
- if (target)
- _entries[input.uid] = target;
- else
- [_entries removeObjectForKey:input.uid];
- }
-}
-
-- (NSDictionary *)serialize {
- NSMutableDictionary* cfgEntries = [[NSMutableDictionary alloc] initWithCapacity:_entries.count];
- for (id key in _entries) {
- id serialized = [_entries[key] serialize];
- if (serialized)
- cfgEntries[key] = serialized;
- }
- return @{ @"name": _name, @"entries": cfgEntries };
-}
-
-@end
+++ /dev/null
-//
-// ConfigsController.h
-// Enjoy
-//
-// Created by Sam McCall on 4/05/09.
-// Copyright 2009 University of Otago. All rights reserved.
-//
-
-@class Config;
-@class TargetController;
-
-@interface ConfigsController : NSObject <NSTableViewDataSource, NSTableViewDelegate, NSOpenSavePanelDelegate> {
- IBOutlet NSButton *removeButton;
- IBOutlet NSTableView *tableView;
- IBOutlet TargetController *targetController;
-}
-
-@property (nonatomic, readonly) Config *currentConfig;
-@property (nonatomic, readonly) NSArray *configs;
-
-- (Config *)objectForKeyedSubscript:(NSString *)name;
-
-
-- (IBAction)addPressed:(id)sender;
-- (IBAction)removePressed:(id)sender;
-- (IBAction)importPressed:(id)sender;
-- (IBAction)exportPressed:(id)sender;
-- (void)activateConfig:(Config *)config;
-- (void)activateConfigForProcess:(NSString *)processName;
-
-- (void)save;
-- (void)load;
-
-@end
+++ /dev/null
-//
-// ConfigsController.m
-// Enjoy
-//
-// Created by Sam McCall on 4/05/09.
-//
-
-#import "ConfigsController.h"
-
-#import "ApplicationController.h"
-#import "Config.h"
-#import "ConfigsController.h"
-#import "Target.h"
-#import "TargetController.h"
-#import "NJEvents.h"
-
-@implementation ConfigsController {
- NSMutableArray *_configs;
- Config *manualConfig;
-}
-
-- (id)init {
- if ((self = [super init])) {
- _configs = [[NSMutableArray alloc] init];
- _currentConfig = [[Config alloc] initWithName:@"(default)"];
- manualConfig = _currentConfig;
- [_configs addObject:_currentConfig];
- }
- return self;
-}
-
-- (Config *)objectForKeyedSubscript:(NSString *)name {
- for (Config *config in _configs)
- if ([name isEqualToString:config.name])
- return config;
- return nil;
-}
-
-- (void)activateConfigForProcess:(NSString *)processName {
- Config *oldConfig = manualConfig;
- Config *newConfig = self[processName];
- if (!newConfig)
- newConfig = oldConfig;
- if (newConfig != _currentConfig)
- [self activateConfig:newConfig];
- manualConfig = oldConfig;
-}
-
-- (void)activateConfig:(Config *)config {
- if (!config)
- config = manualConfig;
- NSLog(@"Switching to mapping %@.", config.name);
- manualConfig = config;
- _currentConfig = config;
- [removeButton setEnabled:_configs[0] != config];
- [targetController loadCurrent];
- [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingChanged
- object:_currentConfig];
- [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:[_configs indexOfObject:config]] byExtendingSelection:NO];
-}
-
-- (IBAction)addPressed:(id)sender {
- Config *newConfig = [[Config alloc] initWithName:@"Untitled"];
- [_configs addObject:newConfig];
- [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
- [tableView reloadData];
- [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_configs.count - 1] byExtendingSelection:NO];
- [tableView editColumn:0 row:_configs.count - 1 withEvent:nil select:YES];
- [self activateConfig:newConfig];
-}
-
-- (IBAction)removePressed:(id)sender {
- if (tableView.selectedRow == 0)
- return;
-
- [_configs removeObjectAtIndex:tableView.selectedRow];
- [tableView reloadData];
- [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
- [self activateConfig:_configs[0]];
- [self save];
-}
-
--(void)tableViewSelectionDidChange:(NSNotification *)notify {
- if (tableView.selectedRow >= 0)
- [self activateConfig:_configs[tableView.selectedRow]];
-}
-
-- (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index {
- return [_configs[index] name];
-}
-
-- (void)tableView:(NSTableView *)view setObjectValue:(NSString *)obj forTableColumn:(NSTableColumn *)col row:(NSInteger)index {
- [(Config *)_configs[index] setName:obj];
- [tableView reloadData];
- [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
-}
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
- return _configs.count;
-}
-
-- (BOOL)tableView:(NSTableView *)view shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)index {
- return index > 0;
-}
-
-- (void)save {
- NSLog(@"Saving mappings to defaults.");
- [NSUserDefaults.standardUserDefaults setObject:[self dumpAll] forKey:@"configurations"];
-}
-
-- (void)load {
- [self loadAllFrom:[NSUserDefaults.standardUserDefaults objectForKey:@"configurations"]];
-}
-
-- (NSDictionary *)dumpAll {
- NSMutableArray *ary = [[NSMutableArray alloc] initWithCapacity:_configs.count];
- for (Config *config in _configs)
- [ary addObject:[config serialize]];
- NSUInteger current = _currentConfig ? [_configs indexOfObject:_currentConfig] : 0;
- return @{ @"configurations": ary, @"selected": @(current) };
-}
-
-- (void)loadAllFrom:(NSDictionary*) envelope{
- NSArray *storedConfigs = envelope[@"configurations"];
- NSMutableArray* newConfigs = [[NSMutableArray alloc] initWithCapacity:storedConfigs.count];
-
- // have to do two passes in case config1 refers to config2 via a TargetConfig
- for (NSDictionary *storedConfig in storedConfigs) {
- Config *cfg = [[Config alloc] initWithName:storedConfig[@"name"]];
- [newConfigs addObject:cfg];
- }
-
- for (unsigned i = 0; i < storedConfigs.count; ++i) {
- NSDictionary *entries = storedConfigs[i][@"entries"];
- Config *config = newConfigs[i];
- for (id key in entries) {
- Target *target = [Target targetDeserialize:entries[key]
- withConfigs:newConfigs];
- if (target)
- config.entries[key] = target;
- }
- }
-
- if (newConfigs.count) {
- unsigned current = [envelope[@"selected"] unsignedIntValue];
- if (current >= newConfigs.count)
- current = 0;
- _configs = newConfigs;
- [tableView reloadData];
- [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
- [self activateConfig:_configs[current]];
- }
-}
-
-- (Config *)configWithURL:(NSURL *)url error:(NSError **)error {
- NSInputStream *stream = [NSInputStream inputStreamWithURL:url];
- [stream open];
- NSDictionary *serialization = !*error
- ? [NSJSONSerialization JSONObjectWithStream:stream options:0 error:error]
- : nil;
- [stream close];
-
- if (!([serialization isKindOfClass:NSDictionary.class]
- && [serialization[@"name"] isKindOfClass:NSString.class]
- && [serialization[@"entries"] isKindOfClass:NSDictionary.class])) {
- *error = [NSError errorWithDomain:@"Enjoyable"
- code:0
- description:@"This isn't a valid mapping file."];
- return nil;
- }
-
- NSDictionary *entries = serialization[@"entries"];
- Config *cfg = [[Config alloc] initWithName:serialization[@"name"]];
- for (id key in entries) {
- NSDictionary *value = entries[key];
- if ([key isKindOfClass:NSString.class]) {
- Target *target = [Target targetDeserialize:value
- withConfigs:_configs];
- if (target)
- cfg.entries[key] = target;
- }
- }
- return cfg;
-}
-
-- (void)importPressed:(id)sender {
- NSOpenPanel *panel = [NSOpenPanel openPanel];
- panel.allowedFileTypes = @[ @"enjoyable", @"json", @"txt" ];
- NSWindow *window = NSApplication.sharedApplication.keyWindow;
- [panel beginSheetModalForWindow:window
- completionHandler:^(NSInteger result) {
- if (result != NSFileHandlingPanelOKButton)
- return;
-
- [panel close];
- NSError *error;
- Config *cfg = [self configWithURL:panel.URL error:&error];
-
- if (!error) {
- BOOL conflict;
- Config *mergeInto = self[cfg.name];
- for (id key in cfg.entries) {
- if (mergeInto.entries[key]
- && ![mergeInto.entries[key] isEqual:cfg.entries[key]]) {
- conflict = YES;
- break;
- }
- }
-
- if (conflict) {
- NSAlert *conflictAlert = [[NSAlert alloc] init];
- conflictAlert.messageText = @"Replace existing mappings?";
- conflictAlert.informativeText =
- [NSString stringWithFormat:
- @"This file contains inputs you've already mapped in \"%@\". Do you "
- @"want to merge them and replace your existing mappings, or import this "
- @"as a separate mapping?", cfg.name];
- [conflictAlert addButtonWithTitle:@"Merge"];
- [conflictAlert addButtonWithTitle:@"Cancel"];
- [conflictAlert addButtonWithTitle:@"New Mapping"];
- NSInteger res = [conflictAlert runModal];
- if (res == NSAlertSecondButtonReturn)
- return;
- else if (res == NSAlertThirdButtonReturn)
- mergeInto = nil;
- }
-
- if (mergeInto) {
- [mergeInto.entries addEntriesFromDictionary:cfg.entries];
- cfg = mergeInto;
- } else {
- [_configs addObject:cfg];
- [tableView reloadData];
- }
-
- [self save];
- [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
- [self activateConfig:cfg];
- [targetController loadCurrent];
-
- if (conflict && !mergeInto) {
- [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_configs.count - 1] byExtendingSelection:NO];
- [tableView editColumn:0 row:_configs.count - 1 withEvent:nil select:YES];
- }
- }
-
- if (error) {
- [window presentError:error
- modalForWindow:window
- delegate:nil
- didPresentSelector:nil
- contextInfo:nil];
- }
- }];
-
-}
-
-- (void)exportPressed:(id)sender {
- NSSavePanel *panel = [NSSavePanel savePanel];
- panel.allowedFileTypes = @[ @"enjoyable" ];
- Config *cfg = _currentConfig;
- panel.nameFieldStringValue = cfg.name;
- NSWindow *window = NSApplication.sharedApplication.keyWindow;
- [panel beginSheetModalForWindow:window
- completionHandler:^(NSInteger result) {
- if (result != NSFileHandlingPanelOKButton)
- return;
- [panel close];
- NSError *error;
- NSDictionary *serialization = [cfg serialize];
- NSData *json = [NSJSONSerialization dataWithJSONObject:serialization
- options:NSJSONWritingPrettyPrinted
- error:&error];
- if (!error)
- [json writeToURL:panel.URL options:NSDataWritingAtomic error:&error];
-
- if (error) {
- [window presentError:error
- modalForWindow:window
- delegate:nil
- didPresentSelector:nil
- contextInfo:nil];
- }
- }];
-}
-
-@end
<string key="NSClassName">ApplicationController</string>
</object>
<object class="NSCustomObject" id="468285243">
- <string key="NSClassName">ConfigsController</string>
+ <string key="NSClassName">NJMappingsController</string>
</object>
<object class="NSCustomObject" id="1007832501">
<string key="NSClassName">NJInputController</string>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
- <string key="label">configsController</string>
+ <string key="label">mappingsController</string>
<reference key="source" ref="1007832501"/>
<reference key="destination" ref="468285243"/>
</object>
- <int key="connectionID">717</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">jsController</string>
- <reference key="source" ref="207406104"/>
- <reference key="destination" ref="1007832501"/>
- </object>
- <int key="connectionID">484</int>
+ <int key="connectionID">822</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
- <string key="label">configsController</string>
+ <string key="label">dockMenuBase</string>
<reference key="source" ref="207406104"/>
- <reference key="destination" ref="468285243"/>
+ <reference key="destination" ref="720053764"/>
</object>
- <int key="connectionID">716</int>
+ <int key="connectionID">726</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
- <string key="label">dockMenuBase</string>
+ <string key="label">inputController</string>
<reference key="source" ref="207406104"/>
- <reference key="destination" ref="720053764"/>
+ <reference key="destination" ref="1007832501"/>
</object>
- <int key="connectionID">726</int>
+ <int key="connectionID">819</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">mappingsController</string>
+ <reference key="source" ref="207406104"/>
+ <reference key="destination" ref="468285243"/>
+ </object>
+ <int key="connectionID">820</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
</object>
<int key="connectionID">692</int>
</object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">configsController</string>
- <reference key="source" ref="801536542"/>
- <reference key="destination" ref="468285243"/>
- </object>
- <int key="connectionID">693</int>
- </object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">joystickController</string>
</object>
<int key="connectionID">709</int>
</object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
- <string key="label">configPopup</string>
- <reference key="source" ref="801536542"/>
- <reference key="destination" ref="194275224"/>
- </object>
- <int key="connectionID">713</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
- <string key="label">configChosen:</string>
- <reference key="source" ref="801536542"/>
- <reference key="destination" ref="194275224"/>
- </object>
- <int key="connectionID">714</int>
- </object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">radioChanged:</string>
</object>
<int key="connectionID">781</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">mappingsController</string>
+ <reference key="source" ref="801536542"/>
+ <reference key="destination" ref="468285243"/>
+ </object>
+ <int key="connectionID">821</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">mappingPopup</string>
+ <reference key="source" ref="801536542"/>
+ <reference key="destination" ref="194275224"/>
+ </object>
+ <int key="connectionID">823</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">mappingChosen:</string>
+ <reference key="source" ref="801536542"/>
+ <reference key="destination" ref="194275224"/>
+ </object>
+ <int key="connectionID">824</int>
+ </object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">keyDelegate</string>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
- <int key="maxID">818</int>
+ <int key="maxID">824</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
D549CA4C0FBB441B00BC8203 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = D549CA4B0FBB441B00BC8203 /* Credits.rtf */; };
- D5617A360FAEB74000928B3A /* ConfigsController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617A350FAEB74000928B3A /* ConfigsController.m */; };
- D5617A390FAEBA1800928B3A /* Config.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617A380FAEBA1800928B3A /* Config.m */; };
+ D5617A360FAEB74000928B3A /* NJMappingsController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617A350FAEB74000928B3A /* NJMappingsController.m */; };
+ D5617A390FAEBA1800928B3A /* NJMapping.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617A380FAEBA1800928B3A /* NJMapping.m */; };
D5617D1A0FAF568100928B3A /* NJInputButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617D190FAF568100928B3A /* NJInputButton.m */; };
D5617D260FAF579300928B3A /* NJInputHat.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617D250FAF579300928B3A /* NJInputHat.m */; };
D5617D2B0FAF579A00928B3A /* NJInputAnalog.m in Sources */ = {isa = PBXBuildFile; fileRef = D5617D2A0FAF579A00928B3A /* NJInputAnalog.m */; };
8D1107320486CEB800E47090 /* Enjoyable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Enjoyable.app; sourceTree = BUILT_PRODUCTS_DIR; };
D549CA4B0FBB441B00BC8203 /* Credits.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
D5617A080FAEAF8300928B3A /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = "<group>"; };
- D5617A340FAEB74000928B3A /* ConfigsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigsController.h; sourceTree = "<group>"; };
- D5617A350FAEB74000928B3A /* ConfigsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConfigsController.m; sourceTree = "<group>"; };
- D5617A370FAEBA1800928B3A /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = "<group>"; };
- D5617A380FAEBA1800928B3A /* Config.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Config.m; sourceTree = "<group>"; };
+ D5617A340FAEB74000928B3A /* NJMappingsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJMappingsController.h; sourceTree = "<group>"; };
+ D5617A350FAEB74000928B3A /* NJMappingsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJMappingsController.m; sourceTree = "<group>"; };
+ D5617A370FAEBA1800928B3A /* NJMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJMapping.h; sourceTree = "<group>"; };
+ D5617A380FAEBA1800928B3A /* NJMapping.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJMapping.m; sourceTree = "<group>"; };
D5617D180FAF568100928B3A /* NJInputButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJInputButton.h; sourceTree = "<group>"; };
D5617D190FAF568100928B3A /* NJInputButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NJInputButton.m; sourceTree = "<group>"; };
D5617D240FAF579300928B3A /* NJInputHat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NJInputHat.h; sourceTree = "<group>"; };
D594BEF80FAE6FF2007A85F2 /* NJInputController.m */,
D594BF810FAE9661007A85F2 /* ApplicationController.h */,
D594BF820FAE9661007A85F2 /* ApplicationController.m */,
- D5617A340FAEB74000928B3A /* ConfigsController.h */,
- D5617A350FAEB74000928B3A /* ConfigsController.m */,
- D5617A370FAEBA1800928B3A /* Config.h */,
- D5617A380FAEBA1800928B3A /* Config.m */,
+ D5617A340FAEB74000928B3A /* NJMappingsController.h */,
+ D5617A350FAEB74000928B3A /* NJMappingsController.m */,
+ D5617A370FAEBA1800928B3A /* NJMapping.h */,
+ D5617A380FAEBA1800928B3A /* NJMapping.m */,
D5F8096F0FB093400006A4DE /* TargetConfig.h */,
D5F809700FB093400006A4DE /* TargetConfig.m */,
D5617FD40FAFD06000928B3A /* Target.h */,
D594BE8A0FAE64AD007A85F2 /* NJInput.m in Sources */,
D594BEF90FAE6FF2007A85F2 /* NJInputController.m in Sources */,
D594BF830FAE9661007A85F2 /* ApplicationController.m in Sources */,
- D5617A360FAEB74000928B3A /* ConfigsController.m in Sources */,
- D5617A390FAEBA1800928B3A /* Config.m in Sources */,
+ D5617A360FAEB74000928B3A /* NJMappingsController.m in Sources */,
+ D5617A390FAEBA1800928B3A /* NJMapping.m in Sources */,
D5617D1A0FAF568100928B3A /* NJInputButton.m in Sources */,
D5617D260FAF579300928B3A /* NJInputHat.m in Sources */,
D5617D2B0FAF579A00928B3A /* NJInputAnalog.m in Sources */,
@class NJDevice;
@class NJInput;
-@class ConfigsController;
+@class NJMappingsController;
@class TargetController;
@interface NJInputController : NSObject <NSOutlineViewDataSource, NSOutlineViewDelegate> {
IBOutlet NSOutlineView *outlineView;
IBOutlet TargetController *targetController;
- IBOutlet ConfigsController *configsController;
+ IBOutlet NJMappingsController *mappingsController;
}
- (void)setup;
#import "NJInputController.h"
-#import "Config.h"
-#import "ConfigsController.h"
+#import "NJMapping.h"
+#import "NJMappingsController.h"
#import "NJDevice.h"
#import "NJInput.h"
#import "Target.h"
}
- (void)runTargetForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value {
- NJDevice *js = [self findJoystickByRef:device];
- NJInput *mainInput = [js inputForEvent:value];
+ NJDevice *dev = [self findJoystickByRef:device];
+ NJInput *mainInput = [dev inputForEvent:value];
[mainInput notifyEvent:value];
NSArray *children = mainInput.children ? mainInput.children : mainInput ? @[mainInput] : @[];
for (NJInput *subInput in children) {
- Target *target = configsController.currentConfig[subInput];
+ Target *target = mappingsController.currentMapping[subInput];
target.magnitude = mainInput.magnitude;
target.running = subInput.active;
if (target.running && target.isContinuous)
}
- (void)showTargetForDevice:(IOHIDDeviceRef)device value:(IOHIDValueRef)value {
- NJDevice *js = [self findJoystickByRef:device];
- NJInput *handler = [js handlerForEvent:value];
+ NJDevice *dev = [self findJoystickByRef:device];
+ NJInput *handler = [dev handlerForEvent:value];
if (!handler)
return;
}
}
-static int findAvailableIndex(NSArray *list, NJDevice *js) {
+static int findAvailableIndex(NSArray *list, NJDevice *dev) {
for (int index = 1; ; index++) {
BOOL available = YES;
for (NJDevice *used in list) {
- if ([used.productName isEqualToString:js.productName] && used.index == index) {
+ if ([used.productName isEqualToString:dev.productName] && used.index == index) {
available = NO;
break;
}
- (void)addJoystickForDevice:(IOHIDDeviceRef)device {
IOHIDDeviceRegisterInputValueCallback(device, input_callback, (__bridge void*)self);
- NJDevice *js = [[NJDevice alloc] initWithDevice:device];
- js.index = findAvailableIndex(_joysticks, js);
- [_joysticks addObject:js];
+ NJDevice *dev = [[NJDevice alloc] initWithDevice:device];
+ dev.index = findAvailableIndex(_joysticks, dev);
+ [_joysticks addObject:dev];
[outlineView reloadData];
}
}
- (NJDevice *)findJoystickByRef:(IOHIDDeviceRef)device {
- for (NJDevice *js in _joysticks)
- if (js.device == device)
- return js;
+ for (NJDevice *dev in _joysticks)
+ if (dev.device == device)
+ return dev;
return nil;
}
--- /dev/null
+//
+// NJMapping.h
+// Enjoy
+//
+// Created by Sam McCall on 4/05/09.
+// Copyright 2009 University of Otago. All rights reserved.
+//
+
+@class Target;
+@class NJInput;
+
+@interface NJMapping : NSObject
+
+@property (nonatomic, copy) NSString *name;
+@property (nonatomic, readonly) NSMutableDictionary *entries;
+
+- (id)initWithName:(NSString *)name;
+- (Target *)objectForKeyedSubscript:(NJInput *)input;
+- (void)setObject:(Target *)target forKeyedSubscript:(NJInput *)input;
+- (NSDictionary *)serialize;
+
+@end
--- /dev/null
+//
+// NJMapping.m
+// Enjoy
+//
+// Created by Sam McCall on 4/05/09.
+//
+
+#import "NJMapping.h"
+
+#import "NJInput.h"
+
+@implementation NJMapping
+
+- (id)initWithName:(NSString *)name {
+ if ((self = [super init])) {
+ self.name = name ? name : @"Untitled";
+ _entries = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (Target *)objectForKeyedSubscript:(NJInput *)input {
+ return input ? _entries[input.uid] : nil;
+}
+
+- (void)setObject:(Target *)target forKeyedSubscript:(NJInput *)input {
+ if (input) {
+ if (target)
+ _entries[input.uid] = target;
+ else
+ [_entries removeObjectForKey:input.uid];
+ }
+}
+
+- (NSDictionary *)serialize {
+ NSMutableDictionary *entries = [[NSMutableDictionary alloc] initWithCapacity:_entries.count];
+ for (id key in _entries) {
+ id serialized = [_entries[key] serialize];
+ if (serialized)
+ entries[key] = serialized;
+ }
+ return @{ @"name": _name, @"entries": entries };
+}
+
+@end
--- /dev/null
+//
+// NJMappingsController.h
+// Enjoy
+//
+// Created by Sam McCall on 4/05/09.
+// Copyright 2009 University of Otago. All rights reserved.
+//
+
+@class NJMapping;
+@class TargetController;
+
+@interface NJMappingsController : NSObject <NSTableViewDataSource,
+ NSTableViewDelegate,
+ NSOpenSavePanelDelegate> {
+ IBOutlet NSButton *removeButton;
+ IBOutlet NSTableView *tableView;
+ IBOutlet TargetController *targetController;
+}
+
+@property (nonatomic, readonly) NJMapping *currentMapping;
+@property (nonatomic, readonly) NSArray *mappings;
+
+- (NJMapping *)objectForKeyedSubscript:(NSString *)name;
+
+
+- (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
--- /dev/null
+//
+// NJMappingsController.m
+// Enjoy
+//
+// Created by Sam McCall on 4/05/09.
+//
+
+#import "NJMappingsController.h"
+
+#import "ApplicationController.h"
+#import "NJMapping.h"
+#import "NJMappingsController.h"
+#import "Target.h"
+#import "TargetController.h"
+#import "NJEvents.h"
+
+@implementation NJMappingsController {
+ NSMutableArray *_mappings;
+ NJMapping *manualMapping;
+}
+
+- (id)init {
+ if ((self = [super init])) {
+ _mappings = [[NSMutableArray alloc] init];
+ _currentMapping = [[NJMapping alloc] initWithName:@"(default)"];
+ manualMapping = _currentMapping;
+ [_mappings addObject:_currentMapping];
+ }
+ return self;
+}
+
+- (NJMapping *)objectForKeyedSubscript:(NSString *)name {
+ for (NJMapping *mapping in _mappings)
+ if ([name isEqualToString:mapping.name])
+ return mapping;
+ return nil;
+}
+
+- (void)activateMappingForProcess:(NSString *)processName {
+ NJMapping *oldMapping = manualMapping;
+ NJMapping *newMapping = self[processName];
+ if (!newMapping)
+ newMapping = oldMapping;
+ if (newMapping != _currentMapping)
+ [self activateMapping:newMapping];
+ manualMapping = oldMapping;
+}
+
+- (void)activateMapping:(NJMapping *)mapping {
+ if (!mapping)
+ mapping = manualMapping;
+ NSLog(@"Switching to mapping %@.", mapping.name);
+ manualMapping = mapping;
+ _currentMapping = mapping;
+ [removeButton setEnabled:_mappings[0] != mapping];
+ [targetController loadCurrent];
+ [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingChanged
+ object:_currentMapping];
+ [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:[_mappings indexOfObject:mapping]] byExtendingSelection:NO];
+}
+
+- (IBAction)addPressed:(id)sender {
+ NJMapping *newMapping = [[NJMapping alloc] initWithName:@"Untitled"];
+ [_mappings addObject:newMapping];
+ [(ApplicationController *)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 activateMapping:newMapping];
+}
+
+- (IBAction)removePressed:(id)sender {
+ if (tableView.selectedRow == 0)
+ return;
+
+ [_mappings removeObjectAtIndex:tableView.selectedRow];
+ [tableView reloadData];
+ [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged];
+ [self activateMapping:_mappings[0]];
+ [self save];
+}
+
+-(void)tableViewSelectionDidChange:(NSNotification *)notify {
+ if (tableView.selectedRow >= 0)
+ [self activateMapping:_mappings[tableView.selectedRow]];
+}
+
+- (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index {
+ return [_mappings[index] name];
+}
+
+- (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];
+}
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
+ return _mappings.count;
+}
+
+- (BOOL)tableView:(NSTableView *)view shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)index {
+ return index > 0;
+}
+
+- (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) };
+}
+
+- (void)loadAllFrom:(NSDictionary*)envelope {
+ NSArray *storedMappings = envelope[@"mappings"];
+ NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count];
+
+ // have to do two passes in case mapping1 refers to mapping2 via a TargetMapping
+ for (NSDictionary *storedMapping in storedMappings) {
+ NJMapping *mapping = [[NJMapping alloc] initWithName:storedMapping[@"name"]];
+ [newMappings addObject:mapping];
+ }
+
+ for (unsigned i = 0; i < storedMappings.count; ++i) {
+ NSDictionary *entries = storedMappings[i][@"entries"];
+ NJMapping *mapping = newMappings[i];
+ for (id key in entries) {
+ Target *target = [Target targetDeserialize:entries[key]
+ withMappings:newMappings];
+ if (target)
+ mapping.entries[key] = target;
+ }
+ }
+
+ if (newMappings.count) {
+ unsigned current = [envelope[@"selected"] unsignedIntValue];
+ if (current >= newMappings.count)
+ current = 0;
+ _mappings = newMappings;
+ [tableView reloadData];
+ [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged];
+ [self activateMapping:_mappings[current]];
+ }
+}
+
+- (NJMapping *)mappingWithURL:(NSURL *)url error:(NSError **)error {
+ NSInputStream *stream = [NSInputStream inputStreamWithURL:url];
+ [stream open];
+ NSDictionary *serialization = !*error
+ ? [NSJSONSerialization JSONObjectWithStream:stream options:0 error:error]
+ : nil;
+ [stream close];
+
+ if (!([serialization isKindOfClass:NSDictionary.class]
+ && [serialization[@"name"] isKindOfClass:NSString.class]
+ && [serialization[@"entries"] isKindOfClass:NSDictionary.class])) {
+ *error = [NSError errorWithDomain:@"Enjoyable"
+ code:0
+ description:@"This isn't a valid mapping file."];
+ return nil;
+ }
+
+ NSDictionary *entries = serialization[@"entries"];
+ NJMapping *mapping = [[NJMapping alloc] initWithName:serialization[@"name"]];
+ for (id key in entries) {
+ NSDictionary *value = entries[key];
+ if ([key isKindOfClass:NSString.class]) {
+ Target *target = [Target targetDeserialize:value
+ withMappings:_mappings];
+ if (target)
+ mapping.entries[key] = target;
+ }
+ }
+ return mapping;
+}
+
+- (void)importPressed:(id)sender {
+ NSOpenPanel *panel = [NSOpenPanel openPanel];
+ panel.allowedFileTypes = @[ @"enjoyable", @"json", @"txt" ];
+ NSWindow *window = NSApplication.sharedApplication.keyWindow;
+ [panel beginSheetModalForWindow:window
+ completionHandler:^(NSInteger result) {
+ if (result != NSFileHandlingPanelOKButton)
+ return;
+
+ [panel close];
+ NSError *error;
+ NJMapping *mapping = [self mappingWithURL:panel.URL error:&error];
+
+ if (!error) {
+ BOOL conflict = NO;
+ NJMapping *mergeInto = self[mapping.name];
+ for (id key in mapping.entries) {
+ if (mergeInto.entries[key]
+ && ![mergeInto.entries[key] isEqual:mapping.entries[key]]) {
+ conflict = YES;
+ break;
+ }
+ }
+
+ if (conflict) {
+ NSAlert *conflictAlert = [[NSAlert alloc] init];
+ conflictAlert.messageText = @"Replace existing mappings?";
+ conflictAlert.informativeText =
+ [NSString stringWithFormat:
+ @"This file contains inputs you've already mapped in \"%@\". Do you "
+ @"want to merge them and replace your existing mappings, or import this "
+ @"as a separate mapping?", mapping.name];
+ [conflictAlert addButtonWithTitle:@"Merge"];
+ [conflictAlert addButtonWithTitle:@"Cancel"];
+ [conflictAlert addButtonWithTitle:@"New Mapping"];
+ NSInteger res = [conflictAlert runModal];
+ if (res == NSAlertSecondButtonReturn)
+ return;
+ else if (res == NSAlertThirdButtonReturn)
+ mergeInto = nil;
+ }
+
+ if (mergeInto) {
+ [mergeInto.entries addEntriesFromDictionary:mapping.entries];
+ mapping = mergeInto;
+ } else {
+ [_mappings addObject:mapping];
+ [tableView reloadData];
+ }
+
+ [self save];
+ [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged];
+ [self activateMapping:mapping];
+ [targetController loadCurrent];
+
+ if (conflict && !mergeInto) {
+ [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_mappings.count - 1] byExtendingSelection:NO];
+ [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES];
+ }
+ }
+
+ if (error) {
+ [window presentError:error
+ modalForWindow:window
+ delegate:nil
+ didPresentSelector:nil
+ contextInfo:nil];
+ }
+ }];
+
+}
+
+- (void)exportPressed:(id)sender {
+ NSSavePanel *panel = [NSSavePanel savePanel];
+ panel.allowedFileTypes = @[ @"enjoyable" ];
+ NJMapping *mapping = _currentMapping;
+ panel.nameFieldStringValue = mapping.name;
+ NSWindow *window = NSApplication.sharedApplication.keyWindow;
+ [panel beginSheetModalForWindow:window
+ completionHandler:^(NSInteger result) {
+ if (result != NSFileHandlingPanelOKButton)
+ return;
+ [panel close];
+ NSError *error;
+ NSDictionary *serialization = [mapping serialize];
+ NSData *json = [NSJSONSerialization dataWithJSONObject:serialization
+ options:NSJSONWritingPrettyPrinted
+ error:&error];
+ if (!error)
+ [json writeToURL:panel.URL options:NSDataWritingAtomic error:&error];
+
+ if (error) {
+ [window presentError:error
+ modalForWindow:window
+ delegate:nil
+ didPresentSelector:nil
+ contextInfo:nil];
+ }
+ }];
+}
+
+@end
- (NSDictionary *)serialize;
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs;
+ withMappings:(NSArray *)mappings;
+ (NSString *)serializationCode;
@end
}
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
- // Don't crash loading old configs (but don't load them either).
+ withMappings:(NSArray *)mappings {
+ // Don't crash loading old/bad mappings (but don't load them either).
if (![serialization isKindOfClass:NSDictionary.class])
return nil;
NSString *type = serialization[@"type"];
TargetToggleMouseScope.class
]) {
if ([type isEqualToString:cls.serializationCode])
- return [cls targetDeserialize:serialization withConfigs:configs];
+ return [cls targetDeserialize:serialization withMappings:mappings];
}
return nil;
#import "Target.h"
-@class Config;
+@class NJMapping;
@interface TargetConfig : Target
-@property (nonatomic, weak) Config *config;
+@property (nonatomic, weak) NJMapping *mapping;
@end
#import "TargetConfig.h"
#import "ApplicationController.h"
-#import "Config.h"
-#import "ConfigsController.h"
+#import "NJMapping.h"
+#import "NJMappingsController.h"
@implementation TargetConfig
+ (NSString *)serializationCode {
- return @"cfg";
+ return @"mapping";
}
- (NSDictionary *)serialize {
- return _config
- ? @{ @"type": @"cfg", @"name": _config.name }
+ return _mapping
+ ? @{ @"type": @"mapping", @"name": _mapping.name }
: nil;
}
+ (TargetConfig *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
+ withMappings:(NSArray *)mappings {
NSString *name = serialization[@"name"];
TargetConfig *target = [[TargetConfig alloc] init];
- for (Config *config in configs) {
- if ([config.name isEqualToString:name]) {
- target.config = config;
+ for (NJMapping *mapping in mappings) {
+ if ([mapping.name isEqualToString:name]) {
+ target.mapping = mapping;
return target;
}
}
- (void)trigger {
ApplicationController *ctrl = NSApplication.sharedApplication.delegate;
- [ctrl.configsController activateConfig:_config];
+ [ctrl.mappingsController activateMapping:_mapping];
}
@end
#import "NJKeyInputField.h"
-@class ConfigsController;
+@class NJMappingsController;
@class NJInputController;
@class Target;
@class TargetMouseMove;
IBOutlet NSSegmentedControl *mouseBtnSelect;
IBOutlet NSSegmentedControl *scrollDirSelect;
IBOutlet NSTextField *title;
- IBOutlet NSPopUpButton *configPopup;
- IBOutlet ConfigsController *configsController;
+ IBOutlet NSPopUpButton *mappingPopup;
+ IBOutlet NJMappingsController *mappingsController;
IBOutlet NJInputController *joystickController;
}
@property (assign) BOOL enabled;
- (void)loadCurrent;
-- (void)refreshConfigs;
-- (IBAction)configChosen:(id)sender;
+- (void)refreshMappings;
- (IBAction)radioChanged:(id)sender;
- (IBAction)mdirChanged:(id)sender;
- (IBAction)mbtnChanged:(id)sender;
#import "TargetController.h"
-#import "ConfigsController.h"
-#import "Config.h"
+#import "NJMappingsController.h"
+#import "NJMapping.h"
#import "NJInput.h"
#import "NJInputController.h"
#import "NJKeyInputField.h"
}
if (row != 2) {
- [configPopup selectItemAtIndex:-1];
- [configPopup resignIfFirstResponder];
- } else if (!configPopup.selectedItem)
- [configPopup selectItemAtIndex:0];
+ [mappingPopup selectItemAtIndex:-1];
+ [mappingPopup resignIfFirstResponder];
+ } else if (!mappingPopup.selectedItem)
+ [mappingPopup selectItemAtIndex:0];
if (row != 3) {
mouseDirSelect.selectedSegment = -1;
[self commit];
}
-- (void)configChosen:(id)sender {
+- (void)mappingChosen:(id)sender {
[radioButtons selectCellAtRow:2 column:0];
- [configPopup.window makeFirstResponder:configPopup];
+ [mappingPopup.window makeFirstResponder:mappingPopup];
[self commit];
}
}
- (Target *)currentTarget {
- return configsController.currentConfig[joystickController.selectedInput];
+ return mappingsController.currentMapping[joystickController.selectedInput];
}
- (Target *)makeTarget {
break;
case 2: {
TargetConfig *c = [[TargetConfig alloc] init];
- c.config = configsController.configs[configPopup.indexOfSelectedItem];
+ c.mapping = mappingsController.mappings[mappingPopup.indexOfSelectedItem];
return c;
}
case 3: {
- (void)commit {
[self cleanUpInterface];
- configsController.currentConfig[joystickController.selectedInput] = [self makeTarget];
- [configsController save];
+ mappingsController.currentMapping[joystickController.selectedInput] = [self makeTarget];
+ [mappingsController save];
}
- (BOOL)enabled {
- (void)setEnabled:(BOOL)enabled {
[radioButtons setEnabled:enabled];
[keyInput setEnabled:enabled];
- [configPopup setEnabled:enabled];
+ [mappingPopup setEnabled:enabled];
[mouseDirSelect setEnabled:enabled];
[mouseBtnSelect setEnabled:enabled];
[scrollDirSelect setEnabled:enabled];
for (id <NJInputPathElement> cur = input.base; cur; cur = cur.base) {
inpFullName = [[NSString alloc] initWithFormat:@"%@ > %@", cur.name, inpFullName];
}
- title.stringValue = [[NSString alloc] initWithFormat:@"%@ > %@", configsController.currentConfig.name, inpFullName];
+ title.stringValue = [[NSString alloc] initWithFormat:@"%@ > %@", mappingsController.currentMapping.name, inpFullName];
}
if ([target isKindOfClass:TargetKeyboard.class]) {
keyInput.keyCode = [(TargetKeyboard*)target vk];
} else if ([target isKindOfClass:TargetConfig.class]) {
[radioButtons selectCellAtRow:2 column:0];
- NSUInteger idx = [configsController.configs
- indexOfObject:[(TargetConfig *)target config]];
+ NSUInteger idx = [mappingsController.mappings
+ indexOfObject:[(TargetConfig *)target mapping]];
if (idx == NSNotFound) {
[radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
- [configPopup selectItemAtIndex:-1];
+ [mappingPopup selectItemAtIndex:-1];
} else
- [configPopup selectItemAtIndex:idx];
+ [mappingPopup selectItemAtIndex:idx];
}
else if ([target isKindOfClass:TargetMouseMove.class]) {
[radioButtons selectCellAtRow:3 column:0];
[keyInput resignIfFirstResponder];
}
-- (void)refreshConfigs {
- NSInteger initialIndex = configPopup.indexOfSelectedItem;
- [configPopup.menu removeAllItems];
- for (Config *config in configsController.configs) {
- NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:config.name
- action:@selector(configChosen:)
+- (void)refreshMappings {
+ NSInteger initialIndex = mappingPopup.indexOfSelectedItem;
+ [mappingPopup.menu removeAllItems];
+ for (NJMapping *mapping in mappingsController.mappings) {
+ NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name
+ action:@selector(mappingChosen:)
keyEquivalent:@""];
item.target = self;
- [configPopup.menu addItem:item];
+ [mappingPopup.menu addItem:item];
}
- [configPopup selectItemAtIndex:initialIndex];
+ [mappingPopup selectItemAtIndex:initialIndex];
}
@end
}
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
+ withMappings:(NSArray *)mappings {
TargetKeyboard *target = [[TargetKeyboard alloc] init];
target.vk = [serialization[@"key"] intValue];
return target;
}
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
+ withMappings:(NSArray *)mappings {
TargetMouseBtn *target = [[TargetMouseBtn alloc] init];
target.button = [serialization[@"button"] intValue];
return target;
}
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
+ withMappings:(NSArray *)mappings {
TargetMouseMove *target = [[TargetMouseMove alloc] init];
target.axis = [serialization[@"axis"] intValue];
return target;
}
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
+ withMappings:(NSArray *)mappings {
TargetMouseScroll *target = [[TargetMouseScroll alloc] init];
target.amount = [serialization[@"amount"] intValue];
return target;
}
+ (Target *)targetDeserialize:(NSDictionary *)serialization
- withConfigs:(NSArray *)configs {
+ withMappings:(NSArray *)mappings {
TargetToggleMouseScope *target = [[TargetToggleMouseScope alloc] init];
return target;
}
// 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.jsController;
+ NJInputController *jc = ac.inputController;
jc.frontWindowOnly = !jc.frontWindowOnly;
}