From: Joe Wreschnig Date: Sun, 17 Mar 2013 17:06:08 +0000 (+0100) Subject: Split NJMappingController view handling off into NJMappingViewController. This is... X-Git-Tag: version-1.1~20 X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=commitdiff_plain;h=b14d8429658dd6f3f7b4904301031addb502b22c Split NJMappingController view handling off into NJMappingViewController. This is still buggy. --- diff --git a/Categories/NSMutableArray+MoveObject.h b/Categories/NSMutableArray+MoveObject.h index ce62234..e8ac0b0 100644 --- a/Categories/NSMutableArray+MoveObject.h +++ b/Categories/NSMutableArray+MoveObject.h @@ -11,10 +11,9 @@ @interface NSMutableArray (MoveObject) - (void)moveObjectAtIndex:(NSUInteger)src toIndex:(NSUInteger)dst; - // Move the object at index src to (pre-move) index dst. Other + // Move the object at index src to (post-move) index dst. Other // objects shift up or down as necessary to make room, as in - // insertObject:atIndex:. Because the object is also removed from - // the source index, its resulting index may be one less than dst. + // insertObject:atIndex:. - (BOOL)moveFirstwards:(id)object upTo:(NSUInteger)minIndex; - (BOOL)moveLastwards:(id)object upTo:(NSUInteger)maxIndex; diff --git a/Categories/NSMutableArray+MoveObject.m b/Categories/NSMutableArray+MoveObject.m index 6c7987e..a02b98b 100644 --- a/Categories/NSMutableArray+MoveObject.m +++ b/Categories/NSMutableArray+MoveObject.m @@ -13,7 +13,7 @@ - (void)moveObjectAtIndex:(NSUInteger)src toIndex:(NSUInteger)dst { id obj = self[src]; [self removeObjectAtIndex:src]; - [self insertObject:obj atIndex:dst > src ? dst - 1 : dst]; + [self insertObject:obj atIndex:dst]; } - (BOOL)moveFirstwards:(id)object upTo:(NSUInteger)minIndex { diff --git a/Classes/EnjoyableApplicationDelegate.h b/Classes/EnjoyableApplicationDelegate.h index acea8a9..b28269b 100644 --- a/Classes/EnjoyableApplicationDelegate.h +++ b/Classes/EnjoyableApplicationDelegate.h @@ -21,5 +21,7 @@ @property (nonatomic, strong) IBOutlet NJMappingsController *mappingsController; - (IBAction)restoreToForeground:(id)sender; +- (IBAction)importMappingClicked:(id)sender; +- (IBAction)exportMappingClicked:(id)sender; @end diff --git a/Classes/EnjoyableApplicationDelegate.m b/Classes/EnjoyableApplicationDelegate.m index db62f53..fe781ef 100644 --- a/Classes/EnjoyableApplicationDelegate.m +++ b/Classes/EnjoyableApplicationDelegate.m @@ -135,9 +135,22 @@ - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { [self restoreToForeground:sender]; - NSURL *url = [NSURL fileURLWithPath:filename]; - [self.mappingsController addMappingWithContentsOfURL:url]; - return YES; + NSError *error; + NSURL *URL = [NSURL fileURLWithPath:filename]; + NJMapping *mapping = [NJMapping mappingWithContentsOfURL:URL + mappings:self.mappingsController + error:&error]; + if (mapping) { + [self.mappingsController addOrMergeMapping:mapping]; + return YES; + } else { + [window presentError:error + modalForWindow:window + delegate:nil + didPresentSelector:nil + contextInfo:nil]; + return NO; + } } - (void)mappingWasChosen:(NJMapping *)mapping { @@ -146,7 +159,7 @@ - (void)mappingListShouldOpen { [self restoreToForeground:self]; - [self.mappingsController mappingPressed:self]; + [self.mappingsController.mvc mappingTriggerClicked:self]; } - (void)loginItemPromptDidEnd:(NSWindow *)sheet @@ -190,5 +203,52 @@ return NO; } +- (void)importMappingClicked:(id)sender { + NSOpenPanel *panel = [NSOpenPanel openPanel]; + panel.allowedFileTypes = @[ @"enjoyable", @"json", @"txt" ]; + [panel beginSheetModalForWindow:window + completionHandler:^(NSInteger result) { + if (result != NSFileHandlingPanelOKButton) + return; + [panel close]; + NSError *error; + NJMapping *mapping = [NJMapping mappingWithContentsOfURL:panel.URL + mappings:self.mappingsController + error:&error]; + if (mapping) { + [self.mappingsController addOrMergeMapping:mapping]; + } else { + [window presentError:error + modalForWindow:window + delegate:nil + didPresentSelector:nil + contextInfo:nil]; + } + }]; + +} + +- (void)exportMappingClicked:(id)sender { + NSSavePanel *panel = [NSSavePanel savePanel]; + panel.allowedFileTypes = @[ @"enjoyable" ]; + NJMapping *mapping = self.mappingsController.currentMapping; + panel.nameFieldStringValue = [mapping.name stringByFixingPathComponent]; + [panel beginSheetModalForWindow:window + completionHandler:^(NSInteger result) { + if (result != NSFileHandlingPanelOKButton) + return; + [panel close]; + NSError *error; + if (![mapping writeToURL:panel.URL error:&error]) { + [window presentError:error + modalForWindow:window + delegate:nil + didPresentSelector:nil + contextInfo:nil]; + } + }]; +} + + @end diff --git a/Classes/NJDeviceController.h b/Classes/NJDeviceController.h index fcc09ef..29b8b38 100644 --- a/Classes/NJDeviceController.h +++ b/Classes/NJDeviceController.h @@ -9,11 +9,9 @@ #import "NJHIDManager.h" #import "NJDeviceViewController.h" -@class NJDevice; @class NJInput; @class NJMappingsController; @class NJOutputController; -@class NJDeviceViewController; @interface NJDeviceController : NSObject { diff --git a/Classes/NJDeviceController.m b/Classes/NJDeviceController.m index b0e8de3..329b353 100644 --- a/Classes/NJDeviceController.m +++ b/Classes/NJDeviceController.m @@ -68,15 +68,6 @@ [_continuousOutputsTick invalidate]; } -- (id)elementForUID:(NSString *)uid { - for (NJDevice *dev in _devices) { - id item = [dev elementForUID:uid]; - if (item) - return item; - } - return nil; -} - - (void)addRunningOutput:(NJOutput *)output { // Axis events will trigger every small movement, don't keep // re-adding them or they trigger multiple times each time. @@ -238,21 +229,40 @@ self.simulatingEvents = sender.state == NSOnState; } -- (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)devices { +- (NSInteger)numberOfDevicesInDeviceList:(NJDeviceViewController *)dvc { + return _devices.count; +} + +- (NJDevice *)deviceViewController:(NJDeviceViewController *)dvc + deviceForIndex:(NSUInteger)idx { + return _devices[idx]; +} + +- (id)deviceViewController:(NJDeviceViewController *)dvc + elementForUID:(NSString *)uid { + for (NJDevice *dev in _devices) { + id item = [dev elementForUID:uid]; + if (item) + return item; + } + return nil; +} + +- (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)dvc { [outputController loadCurrent]; } -- (void)deviceViewController:(NJDeviceViewController *)devices +- (void)deviceViewController:(NJDeviceViewController *)dvc didSelectBranch:(NJInputPathElement *)handler { [outputController loadCurrent]; } -- (void)deviceViewController:(NJDeviceViewController *)devices +- (void)deviceViewController:(NJDeviceViewController *)dvc didSelectHandler:(NJInputPathElement *)handler { [outputController loadCurrent]; } -- (void)deviceViewController:(NJDeviceViewController *)devices +- (void)deviceViewController:(NJDeviceViewController *)dvc didSelectDevice:(NJInputPathElement *)device { [outputController loadCurrent]; } diff --git a/Classes/NJDeviceViewController.h b/Classes/NJDeviceViewController.h index 9e1a43f..6d039af 100644 --- a/Classes/NJDeviceViewController.h +++ b/Classes/NJDeviceViewController.h @@ -20,9 +20,6 @@ @property (nonatomic, weak) IBOutlet id delegate; -@property (nonatomic, copy) NSArray *devices; - // Assigning directly will trigger a full reload. - - (void)addedDevice:(NJDevice *)device atIndex:(NSUInteger)idx; - (void)removedDevice:(NJDevice *)device atIndex:(NSUInteger)idx; // But using these will animate nicely. @@ -38,12 +35,19 @@ @protocol NJDeviceViewControllerDelegate -- (void)deviceViewController:(NJDeviceViewController *)devices +- (NSInteger)numberOfDevicesInDeviceList:(NJDeviceViewController *)dvc; +- (NJDevice *)deviceViewController:(NJDeviceViewController *)dvc + deviceForIndex:(NSUInteger)idx; +- (NJInputPathElement *)deviceViewController:(NJDeviceViewController *)dvc + elementForUID:(NSString *)uid; + + +- (void)deviceViewController:(NJDeviceViewController *)dvc didSelectDevice:(NJInputPathElement *)device; -- (void)deviceViewController:(NJDeviceViewController *)devices +- (void)deviceViewController:(NJDeviceViewController *)dvc didSelectBranch:(NJInputPathElement *)handler; -- (void)deviceViewController:(NJDeviceViewController *)devices +- (void)deviceViewController:(NJDeviceViewController *)dvc didSelectHandler:(NJInputPathElement *)handler; -- (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)devices; +- (void)deviceViewControllerDidSelectNothing:(NJDeviceViewController *)dvc; @end diff --git a/Classes/NJDeviceViewController.m b/Classes/NJDeviceViewController.m index 3d20e65..dfb2dca 100644 --- a/Classes/NJDeviceViewController.m +++ b/Classes/NJDeviceViewController.m @@ -11,7 +11,6 @@ #import "NJInputPathElement.h" @implementation NJDeviceViewController { - NSMutableArray *_devices; NSMutableArray *_expanded; } @@ -22,7 +21,6 @@ expanded = @[]; _expanded = [[NSMutableArray alloc] initWithCapacity:MAX(16, _expanded.count)]; [_expanded addObjectsFromArray:expanded]; - _devices = [[NSMutableArray alloc] initWithCapacity:16]; } return self; } @@ -34,17 +32,8 @@ } } -- (id)elementForUID:(NSString *)uid { - for (NJInputPathElement *dev in _devices) { - id item = [dev elementForUID:uid]; - if (item) - return item; - } - return nil; -} - - (void)expandRecursiveByUID:(NSString *)uid { - [self expandRecursive:[self elementForUID:uid]]; + [self expandRecursive:[self.delegate deviceViewController:self elementForUID:uid]]; } - (void)reexpandAll { @@ -52,23 +41,12 @@ [self expandRecursiveByUID:uid]; if (self.inputsTree.selectedRow == -1) { NSString *selectedUid = [NSUserDefaults.standardUserDefaults objectForKey:@"selected input"]; - id item = [self elementForUID:selectedUid]; + id item = [self.delegate deviceViewController:self elementForUID:selectedUid]; [self.inputsTree selectItem:item]; } } -- (void)setDevices:(NSArray *)devices { - _devices = [devices mutableCopy]; - id item = self.inputsTree.selectedItem; - [self.inputsTree selectItem:nil]; - [self.inputsTree reloadData]; - [self reexpandAll]; - [self.inputsTree selectItem:item]; - self.noDevicesNotice.hidden = self.devices.count || !self.hidStoppedNotice.isHidden; -} - - (void)addedDevice:(NJDevice *)device atIndex:(NSUInteger)idx { - [_devices insertObject:device atIndex:idx]; [self.inputsTree beginUpdates]; [self.inputsTree insertItemsAtIndexes:[[NSIndexSet alloc] initWithIndex:idx] inParent:nil @@ -79,23 +57,24 @@ } - (void)removedDevice:(NJDevice *)device atIndex:(NSUInteger)idx { - [_devices removeObjectAtIndex:idx]; + BOOL anyDevices = !![self.delegate numberOfDevicesInDeviceList:self]; [self.inputsTree beginUpdates]; [self.inputsTree removeItemsAtIndexes:[[NSIndexSet alloc] initWithIndex:idx] inParent:nil withAnimation:NSTableViewAnimationSlideLeft]; [self.inputsTree endUpdates]; - self.noDevicesNotice.hidden = self.devices.count || !self.hidStoppedNotice.isHidden; + self.noDevicesNotice.hidden = anyDevices || !self.hidStoppedNotice.isHidden; } - (void)hidStarted { - self.noDevicesNotice.hidden = !!self.devices.count; + self.noDevicesNotice.hidden = !![self.delegate numberOfDevicesInDeviceList:self]; self.hidStoppedNotice.hidden = YES; } - (void)hidStopped { + self.noDevicesNotice.hidden = YES; self.hidStoppedNotice.hidden = NO; - self.devices = @[]; + [self.inputsTree reloadData]; } - (void)expandAndSelectItem:(NJInputPathElement *)item { @@ -110,18 +89,25 @@ - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(NJInputPathElement *)item { - return item ? item.children.count : _devices.count; + if (item) + return item.children.count; + else + return [self.delegate numberOfDevicesInDeviceList:self]; + } - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(NJInputPathElement *)item { - return item ? [[item children] count] > 0: YES; + return item ? item.children.count > 0: YES; } - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(NJInputPathElement *)item { - return item ? item.children[index] : _devices[index]; + if (item) + return item.children[index]; + else + return [self.delegate deviceViewController:self deviceForIndex:index]; } - (id)outlineView:(NSOutlineView *)outlineView @@ -152,13 +138,15 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn - (void)outlineViewItemDidExpand:(NSNotification *)notification { NSString *uid = [notification.userInfo[@"NSObject"] uid]; - if (![_expanded containsObject:uid]) + if (![_expanded containsObject:uid]) { [_expanded addObject:uid]; - + [NSUserDefaults.standardUserDefaults setObject:_expanded forKey:@"expanded rows"]; + } } - (void)outlineViewItemDidCollapse:(NSNotification *)notification { [_expanded removeObject:[notification.userInfo[@"NSObject"] uid]]; + [NSUserDefaults.standardUserDefaults setObject:_expanded forKey:@"expanded rows"]; } - (BOOL)outlineView:(NSOutlineView *)outlineView diff --git a/Classes/NJMapping.h b/Classes/NJMapping.h index 8b80012..0d5db89 100644 --- a/Classes/NJMapping.h +++ b/Classes/NJMapping.h @@ -15,12 +15,12 @@ @property (nonatomic, readonly) NSUInteger count; + (id)mappingWithContentsOfURL:(NSURL *)url - mappings:(NSArray *)mappings + mappings:(id )mappings error:(NSError **)error; - (id)initWithName:(NSString *)name; - (id)initWithSerialization:(NSDictionary *)serialization - mappings:(NSArray *)mappings; + mappings:(id )mappings; - (NJOutput *)objectForKeyedSubscript:(NJInput *)input; - (void)setObject:(NJOutput *)output forKeyedSubscript:(NJInput *)input; diff --git a/Classes/NJMapping.m b/Classes/NJMapping.m index 0e67cd3..04f6e68 100644 --- a/Classes/NJMapping.m +++ b/Classes/NJMapping.m @@ -34,7 +34,7 @@ } - (id)initWithSerialization:(NSDictionary *)serialization - mappings:(NSArray *)mappings { + mappings:(id )mappings { if ((self = [self initWithName:serialization[@"name"]])) { NSDictionary *entries = serialization[@"entries"]; if ([entries isKindOfClass:NSDictionary.class]) { @@ -100,7 +100,7 @@ return NO; } -+ (id)mappingWithContentsOfURL:(NSURL *)url mappings:(NSArray *)mappings error:(NSError **)error { ++ (id)mappingWithContentsOfURL:(NSURL *)url mappings:(id )mappings error:(NSError **)error { NSInputStream *stream = [NSInputStream inputStreamWithURL:url]; [stream open]; NSDictionary *serialization = stream && !*error diff --git a/Classes/NJMappingsController.h b/Classes/NJMappingsController.h index a4d9c18..39aaf79 100644 --- a/Classes/NJMappingsController.h +++ b/Classes/NJMappingsController.h @@ -9,36 +9,20 @@ @class NJMapping; @class NJOutputController; -@interface NJMappingsController : NSObject -{ - IBOutlet NSButton *removeButton; - IBOutlet NSTableView *tableView; - IBOutlet NSButton *popoverActivate; - IBOutlet NSPopover *popover; - IBOutlet NSButton *moveUp; - IBOutlet NSButton *moveDown; -} +#import "NJMappingsViewController.h" + +@interface NJMappingsController : NSObject @property (nonatomic, readonly) NJMapping *currentMapping; +@property (nonatomic, strong) IBOutlet NJMappingsViewController *mvc; - (NJMapping *)objectForKeyedSubscript:(NSString *)name; - (NJMapping *)objectAtIndexedSubscript:(NSUInteger)idx; -- (void)addMappingWithContentsOfURL:(NSURL *)url; - (void)activateMapping:(NJMapping *)mapping; - (void)activateMappingForProcess:(NSRunningApplication *)app; +- (void)addOrMergeMapping:(NJMapping *)mapping; - (void)save; - (void)load; -- (IBAction)mappingPressed:(id)sender; -- (IBAction)addPressed:(id)sender; -- (IBAction)removePressed:(id)sender; -- (IBAction)moveUpPressed:(id)sender; -- (IBAction)moveDownPressed:(id)sender; -- (IBAction)importPressed:(id)sender; -- (IBAction)exportPressed:(id)sender; - @end diff --git a/Classes/NJMappingsController.m b/Classes/NJMappingsController.m index c3209ac..531de12 100644 --- a/Classes/NJMappingsController.m +++ b/Classes/NJMappingsController.m @@ -30,11 +30,6 @@ return self; } -- (void)awakeFromNib { - [tableView registerForDraggedTypes:@[PB_ROW, NSURLPboardType]]; - [tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO]; -} - - (NJMapping *)objectForKeyedSubscript:(NSString *)name { for (NJMapping *mapping in _mappings) if ([name isEqualToString:mapping.name]) @@ -47,13 +42,12 @@ } - (void)mappingsSet { - [tableView reloadData]; - [self updateInterfaceForCurrentMapping]; [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingListChanged object:self userInfo:@{ NJMappingListKey: _mappings, NJMappingKey: _currentMapping }]; + [self.mvc changedActiveMappingToIndex:[_mappings indexOfObjectIdenticalTo:_currentMapping]]; } - (void)mappingsChanged { @@ -94,16 +88,6 @@ _manualMapping = oldMapping; } -- (void)updateInterfaceForCurrentMapping { - NSUInteger selected = [_mappings indexOfObject:_currentMapping]; - removeButton.enabled = selected != 0; - moveUp.enabled = selected > 1; - moveDown.enabled = selected && selected != _mappings.count - 1; - popoverActivate.title = _currentMapping.name; - [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selected] byExtendingSelection:NO]; - [NSUserDefaults.standardUserDefaults setInteger:selected forKey:@"selected"]; -} - - (void)activateMapping:(NJMapping *)mapping { if (!mapping) mapping = _manualMapping; @@ -112,56 +96,13 @@ NSLog(@"Switching to mapping %@.", mapping.name); _manualMapping = mapping; _currentMapping = mapping; - [self updateInterfaceForCurrentMapping]; + [self.mvc changedActiveMappingToIndex:[_mappings indexOfObjectIdenticalTo:_currentMapping]]; [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingChanged object:self userInfo:@{ NJMappingKey : _currentMapping }]; } -- (IBAction)addPressed:(id)sender { - [self mappingPressed:sender]; - NJMapping *newMapping = [[NJMapping alloc] init]; - [_mappings addObject:newMapping]; - [self activateMapping:newMapping]; - [self mappingsChanged]; - [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES]; -} - -- (IBAction)removePressed:(id)sender { - if (tableView.selectedRow == 0) - return; - - NSInteger selectedRow = tableView.selectedRow; - [_mappings removeObjectAtIndex:selectedRow]; - [self activateMapping:_mappings[MIN(selectedRow, _mappings.count - 1)]]; - [self mappingsChanged]; -} - -- (void)tableViewSelectionDidChange:(NSNotification *)notify { - [self activateMapping:self[tableView.selectedRow]]; -} - -- (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index { - return self[index].name; -} - -- (void)tableView:(NSTableView *)view - setObjectValue:(NSString *)obj - forTableColumn:(NSTableColumn *)col - row:(NSInteger)index { - self[index].name = obj; - [self mappingsChanged]; -} - -- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { - return _mappings.count; -} - -- (BOOL)tableView:(NSTableView *)view shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)index { - return YES; -} - - (void)save { NSLog(@"Saving mappings to defaults."); NSMutableArray *ary = [[NSMutableArray alloc] initWithCapacity:_mappings.count]; @@ -194,6 +135,7 @@ _mappings = newMappings; if (selected >= newMappings.count) selected = 0; + [self.mvc reloadData]; [self activateMapping:_mappings[selected]]; [self mappingsSet]; } @@ -208,29 +150,29 @@ switch (returnCode) { case NSAlertFirstButtonReturn: // Merge [oldMapping mergeEntriesFrom:newMapping]; + _currentMapping = nil; [self activateMapping:oldMapping]; [self mappingsChanged]; break; case NSAlertThirdButtonReturn: // New Mapping + [self.mvc.mappingList beginUpdates]; [_mappings addObject:newMapping]; + [self.mvc addedMappingAtIndex:_mappings.count - 1 startEditing:NO]; + [self.mvc.mappingList endUpdates]; [self activateMapping:newMapping]; [self mappingsChanged]; - [self mappingPressed:alert]; - [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_mappings.count - 1] byExtendingSelection:NO]; - [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES]; break; default: // Cancel, other. break; } } -- (void)addMappingWithContentsOfURL:(NSURL *)url { - NSWindow *window = popoverActivate.window; - NSError *error; - NJMapping *mapping = [NJMapping mappingWithContentsOfURL:url - mappings:_mappings - error:&error]; - +- (void)addOrMergeMapping:(NJMapping *)mapping { + [self addOrMergeMapping:mapping atIndex:-1]; +} + +- (void)addOrMergeMapping:(NJMapping *)mapping atIndex:(NSInteger)idx { + NSWindow *window = NSApplication.sharedApplication.keyWindow; if (mapping) { NJMapping *mergeInto = self[mapping.name]; if ([mergeInto hasConflictWith:mapping]) { @@ -242,7 +184,7 @@ [conflictAlert addButtonWithTitle:NSLocalizedString(@"import and merge", @"button to merge imported mappings")]; [conflictAlert addButtonWithTitle:NSLocalizedString(@"cancel import", @"button to cancel import")]; [conflictAlert addButtonWithTitle:NSLocalizedString(@"import new mapping", @"button to import as new mapping")]; - [conflictAlert beginSheetModalForWindow:popoverActivate.window + [conflictAlert beginSheetModalForWindow:window modalDelegate:self didEndSelector:@selector(mappingConflictDidResolve:returnCode:contextInfo:) contextInfo:(void *)CFBridgingRetain(@{ @"old mapping": mergeInto, @@ -252,163 +194,86 @@ [self activateMapping:mergeInto]; [self mappingsChanged]; } else { - [_mappings addObject:mapping]; + if (idx == -1) + idx = _mappings.count - 1; + [self.mvc.mappingList beginUpdates]; + [_mappings insertObject:mapping atIndex:idx]; + [self.mvc addedMappingAtIndex:idx startEditing:NO]; + [self.mvc.mappingList endUpdates]; [self activateMapping:mapping]; [self mappingsChanged]; } - } else { - [window presentError:error - modalForWindow:window - delegate:nil - didPresentSelector:nil - contextInfo:nil]; } } -- (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]; - [self addMappingWithContentsOfURL:panel.URL]; - }]; - -} - -- (void)exportPressed:(id)sender { - NSSavePanel *panel = [NSSavePanel savePanel]; - panel.allowedFileTypes = @[ @"enjoyable" ]; - NJMapping *mapping = _currentMapping; - panel.nameFieldStringValue = [mapping.name stringByFixingPathComponent]; - NSWindow *window = NSApplication.sharedApplication.keyWindow; - [panel beginSheetModalForWindow:window - completionHandler:^(NSInteger result) { - if (result != NSFileHandlingPanelOKButton) - return; - [panel close]; - NSError *error; - [mapping writeToURL:panel.URL error:&error]; - if (error) { - [window presentError:error - modalForWindow:window - delegate:nil - didPresentSelector:nil - contextInfo:nil]; - } - }]; -} - -- (IBAction)mappingPressed:(id)sender { - [popover showRelativeToRect:popoverActivate.bounds - ofView:popoverActivate - preferredEdge:NSMinXEdge]; +- (NSInteger)numberOfMappings:(NJMappingsViewController *)dvc { + return _mappings.count; } -- (void)popoverWillShow:(NSNotification *)notification { - popoverActivate.state = NSOnState; +- (NJMapping *)mappingsViewController:(NJMappingsViewController *)dvc + mappingForIndex:(NSUInteger)idx { + return _mappings[idx]; } -- (void)popoverWillClose:(NSNotification *)notification { - popoverActivate.state = NSOffState; +- (void)mappingsViewController:(NJMappingsViewController *)mvc + editedMappingAtIndex:(NSInteger)index { + [self mappingsChanged]; } -- (IBAction)moveUpPressed:(id)sender { - if ([_mappings moveFirstwards:_currentMapping upTo:1]) - [self mappingsChanged]; +- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc + canMoveMappingFromIndex:(NSInteger)fromIdx + toIndex:(NSInteger)toIdx { + return fromIdx != toIdx && fromIdx != 0 && toIdx != 0 && toIdx < (NSInteger)_mappings.count; } -- (IBAction)moveDownPressed:(id)sender { - if ([_mappings moveLastwards:_currentMapping]) - [self mappingsChanged]; +- (void)mappingsViewController:(NJMappingsViewController *)mvc + moveMappingFromIndex:(NSInteger)fromIdx + toIndex:(NSInteger)toIdx { + [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx]; + [self mappingsChanged]; } -- (BOOL)tableView:(NSTableView *)tableView_ - acceptDrop:(id )info - row:(NSInteger)row - dropOperation:(NSTableViewDropOperation)dropOperation { - NSPasteboard *pboard = [info draggingPasteboard]; - if ([pboard.types containsObject:PB_ROW]) { - NSString *value = [pboard stringForType:PB_ROW]; - NSUInteger srcRow = [value intValue]; - [_mappings moveObjectAtIndex:srcRow toIndex:row]; - [self mappingsChanged]; - return YES; - } else if ([pboard.types containsObject:NSURLPboardType]) { - NSURL *url = [NSURL URLFromPasteboard:pboard]; - NSError *error; - NJMapping *mapping = [NJMapping mappingWithContentsOfURL:url - mappings:_mappings - error:&error]; - if (error) { - [tableView_ presentError:error]; - return NO; - } else { - [_mappings insertObject:mapping atIndex:row]; - [self mappingsChanged]; - return YES; - } - } else { - return NO; - } +- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc + canRemoveMappingAtIndex:(NSInteger)idx { + return idx != 0; } -- (NSDragOperation)tableView:(NSTableView *)tableView_ - validateDrop:(id )info - proposedRow:(NSInteger)row - proposedDropOperation:(NSTableViewDropOperation)dropOperation { - NSPasteboard *pboard = [info draggingPasteboard]; - if ([pboard.types containsObject:PB_ROW]) { - [tableView_ setDropRow:MAX(1, row) dropOperation:NSTableViewDropAbove]; - return NSDragOperationMove; - } else if ([pboard.types containsObject:NSURLPboardType]) { - NSURL *url = [NSURL URLFromPasteboard:pboard]; - if ([url.pathExtension isEqualToString:@"enjoyable"]) { - [tableView_ setDropRow:MAX(1, row) dropOperation:NSTableViewDropAbove]; - return NSDragOperationCopy; - } else { - return NSDragOperationNone; - } - } else { - return NSDragOperationNone; - } +- (void)mappingsViewController:(NJMappingsViewController *)mvc + removeMappingAtIndex:(NSInteger)idx { + NJMapping *old = self[idx]; + [self.mvc.mappingList beginUpdates]; + [_mappings removeObjectAtIndex:idx]; + [self.mvc removedMappingAtIndex:idx]; + [self.mvc.mappingList endUpdates]; + if (old == _currentMapping) + [self activateMapping:self[MIN(idx, _mappings.count - 1)]]; + [self mappingsChanged]; } -- (NSArray *)tableView:(NSTableView *)tableView_ -namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination -forDraggedRowsWithIndexes:(NSIndexSet *)indexSet { - NJMapping *toSave = self[indexSet.firstIndex]; - NSString *filename = [[toSave.name stringByFixingPathComponent] - stringByAppendingPathExtension:@"enjoyable"]; - NSURL *dst = [dropDestination URLByAppendingPathComponent:filename]; - dst = [NSFileManager.defaultManager generateUniqueURLWithBase:dst]; - NSError *error; - if (![toSave writeToURL:dst error:&error]) { - [tableView_ presentError:error]; - return @[]; - } else { - return @[dst.lastPathComponent]; - } +- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc + importMappingFromURL:(NSURL *)url + atIndex:(NSInteger)index + error:(NSError **)error { + NJMapping *mapping = [NJMapping mappingWithContentsOfURL:url + mappings:_mappings + error:error]; + [self addOrMergeMapping:mapping atIndex:index]; + return !!mapping; +} + +- (void)mappingsViewController:(NJMappingsViewController *)mvc + addMapping:(NJMapping *)mapping { + [self.mvc.mappingList beginUpdates]; + [_mappings addObject:mapping]; + [self.mvc addedMappingAtIndex:_mappings.count - 1 startEditing:YES]; + [self.mvc.mappingList endUpdates]; + [self activateMapping:mapping]; + [self mappingsChanged]; } -- (BOOL)tableView:(NSTableView *)tableView_ -writeRowsWithIndexes:(NSIndexSet *)rowIndexes - toPasteboard:(NSPasteboard *)pboard { - if (rowIndexes.count == 1 && rowIndexes.firstIndex != 0) { - [pboard declareTypes:@[PB_ROW, NSFilesPromisePboardType] owner:nil]; - [pboard setString:@(rowIndexes.firstIndex).stringValue forType:PB_ROW]; - [pboard setPropertyList:@[@"enjoyable"] forType:NSFilesPromisePboardType]; - return YES; - } else if (rowIndexes.count == 1 && rowIndexes.firstIndex == 0) { - [pboard declareTypes:@[NSFilesPromisePboardType] owner:nil]; - [pboard setPropertyList:@[@"enjoyable"] forType:NSFilesPromisePboardType]; - return YES; - } else { - return NO; - } +- (void)mappingsViewController:(NJMappingsViewController *)mvc + choseMappingAtIndex:(NSInteger)idx { + [self activateMapping:self[idx]]; } @end diff --git a/Classes/NJMappingsViewController.h b/Classes/NJMappingsViewController.h new file mode 100644 index 0000000..2d0bd25 --- /dev/null +++ b/Classes/NJMappingsViewController.h @@ -0,0 +1,72 @@ +// +// NJMappingsViewController.h +// Enjoyable +// +// Created by Joe Wreschnig on 3/17/13. +// +// + +@class NJMapping; +@protocol NJMappingsViewControllerDelegate; + +@interface NJMappingsViewController : NSViewController + +@property (nonatomic, weak) IBOutlet id delegate; + +@property (nonatomic, strong) IBOutlet NSButton *removeMapping; +@property (nonatomic, strong) IBOutlet NSTableView *mappingList; +@property (nonatomic, strong) IBOutlet NSButton *mappingListTrigger; +@property (nonatomic, strong) IBOutlet NSPopover *mappingListPopover; +@property (nonatomic, strong) IBOutlet NSButton *moveUp; +@property (nonatomic, strong) IBOutlet NSButton *moveDown; + +- (IBAction)addClicked:(id)sender; +- (IBAction)removeClicked:(id)sender; +- (IBAction)moveUpClicked:(id)sender; +- (IBAction)moveDownClicked:(id)sender; +- (IBAction)mappingTriggerClicked:(id)sender; + +- (void)addedMappingAtIndex:(NSInteger)index startEditing:(BOOL)startEditing; +- (void)removedMappingAtIndex:(NSInteger)index; +- (void)changedActiveMappingToIndex:(NSInteger)index; + +- (void)reloadData; + +@end + +@protocol NJMappingsViewControllerDelegate + +- (NSInteger)numberOfMappings:(NJMappingsViewController *)dvc; +- (NJMapping *)mappingsViewController:(NJMappingsViewController *)dvc + mappingForIndex:(NSUInteger)idx; + + +- (void)mappingsViewController:(NJMappingsViewController *)mvc + editedMappingAtIndex:(NSInteger)index; + +- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc + canMoveMappingFromIndex:(NSInteger)fromIdx + toIndex:(NSInteger)toIdx; +- (void)mappingsViewController:(NJMappingsViewController *)mvc + moveMappingFromIndex:(NSInteger)fromIdx + toIndex:(NSInteger)toIdx; + +- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc + canRemoveMappingAtIndex:(NSInteger)idx; +- (void)mappingsViewController:(NJMappingsViewController *)mvc + removeMappingAtIndex:(NSInteger)idx; + +- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc + importMappingFromURL:(NSURL *)url + atIndex:(NSInteger)index + error:(NSError **)error; +- (void)mappingsViewController:(NJMappingsViewController *)mvc + addMapping:(NJMapping *)mapping; + +- (void)mappingsViewController:(NJMappingsViewController *)mvc + choseMappingAtIndex:(NSInteger)idx; + +@end diff --git a/Classes/NJMappingsViewController.m b/Classes/NJMappingsViewController.m new file mode 100644 index 0000000..fd9ce41 --- /dev/null +++ b/Classes/NJMappingsViewController.m @@ -0,0 +1,233 @@ +// +// NJMappingsViewController.m +// Enjoyable +// +// Created by Joe Wreschnig on 3/17/13. +// +// + +#import "NJMappingsViewController.h" + +#import "NJMapping.h" + +#define PB_ROW @"com.yukkurigames.Enjoyable.MappingRow" + + +@implementation NJMappingsViewController + +- (void)awakeFromNib { + [self.mappingList registerForDraggedTypes:@[PB_ROW, NSURLPboardType]]; + [self.mappingList setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO]; +} + +- (IBAction)addClicked:(id)sender { + NJMapping *newMapping = [[NJMapping alloc] init]; + [self.delegate mappingsViewController:self addMapping:newMapping]; +} + +- (IBAction)removeClicked:(id)sender { + [self.delegate mappingsViewController:self + removeMappingAtIndex:self.mappingList.selectedRow]; +} + +- (IBAction)moveUpClicked:(id)sender { + NSInteger fromIdx = self.mappingList.selectedRow; + NSInteger toIdx = fromIdx - 1; + [self.delegate mappingsViewController:self + moveMappingFromIndex:fromIdx + toIndex:toIdx]; + [self.mappingList beginUpdates]; + [self.mappingList moveRowAtIndex:fromIdx toIndex:toIdx]; + [self.mappingList endUpdates]; + [self.mappingList scrollRowToVisible:toIdx]; + [self.mappingList selectRowIndexes:[[NSIndexSet alloc] initWithIndex:toIdx] + byExtendingSelection:NO]; +} + +- (IBAction)moveDownClicked:(id)sender { + NSInteger fromIdx = self.mappingList.selectedRow; + NSInteger toIdx = fromIdx + 1; + [self.delegate mappingsViewController:self + moveMappingFromIndex:fromIdx + toIndex:toIdx]; + [self.mappingList beginUpdates]; + [self.mappingList moveRowAtIndex:fromIdx toIndex:toIdx]; + [self.mappingList endUpdates]; + [self.mappingList scrollRowToVisible:toIdx]; + [self.mappingList selectRowIndexes:[[NSIndexSet alloc] initWithIndex:toIdx] + byExtendingSelection:NO]; +} + +- (IBAction)mappingTriggerClicked:(id)sender { + [self.mappingListPopover showRelativeToRect:self.mappingListTrigger.bounds + ofView:self.mappingListTrigger + preferredEdge:NSMinXEdge]; + self.mappingListTrigger.state = NSOnState; +} + +- (void)popoverWillShow:(NSNotification *)notification { + self.mappingListTrigger.state = NSOnState; +} + +- (void)popoverWillClose:(NSNotification *)notification { + self.mappingListTrigger.state = NSOffState; +} + +- (void)addedMappingAtIndex:(NSInteger)index startEditing:(BOOL)startEditing { + [self.mappingList abortEditing]; + [self.mappingList beginUpdates]; + [self.mappingList insertRowsAtIndexes:[[NSIndexSet alloc] initWithIndex:index] + withAnimation:startEditing ? 0 : NSTableViewAnimationSlideLeft]; + [self.mappingList endUpdates]; + if (startEditing) { + [self.mappingListTrigger performClick:self]; + [self.mappingList editColumn:0 row:index withEvent:nil select:YES]; + [self.mappingList scrollRowToVisible:index]; + } +} + +- (void)removedMappingAtIndex:(NSInteger)index { + [self.mappingList abortEditing]; + [self.mappingList beginUpdates]; + [self.mappingList removeRowsAtIndexes:[[NSIndexSet alloc] initWithIndex:index] + withAnimation:NSTableViewAnimationEffectFade]; + [self.mappingList endUpdates]; +} + +- (void)changedActiveMappingToIndex:(NSInteger)index { + NJMapping *mapping = [self.delegate mappingsViewController:self + mappingForIndex:index]; + self.removeMapping.enabled = [self.delegate mappingsViewController:self + canRemoveMappingAtIndex:index]; + self.moveUp.enabled = [self.delegate mappingsViewController:self + canMoveMappingFromIndex:index toIndex:index - 1]; + self.moveDown.enabled = [self.delegate mappingsViewController:self + canMoveMappingFromIndex:index toIndex:index + 1]; + self.mappingListTrigger.title = mapping.name; + [self.mappingList selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO]; + [self.mappingList scrollRowToVisible:index]; + [NSUserDefaults.standardUserDefaults setInteger:index forKey:@"selected"]; + +} + +- (void)tableViewSelectionDidChange:(NSNotification *)note { + [self.mappingList abortEditing]; + NSTableView *tableView = note.object; + [self.delegate mappingsViewController:self + choseMappingAtIndex:tableView.selectedRow]; +} + +- (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index { + return [self.delegate mappingsViewController:self + mappingForIndex:index].name; +} + +- (void)tableView:(NSTableView *)view + setObjectValue:(NSString *)obj + forTableColumn:(NSTableColumn *)col + row:(NSInteger)index { + NJMapping *mapping = [self.delegate mappingsViewController:self + mappingForIndex:index]; + mapping.name = obj; + [self.delegate mappingsViewController:self editedMappingAtIndex:index]; +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { + return [self.delegate numberOfMappings:self]; +} + +- (BOOL)tableView:(NSTableView *)tableView + acceptDrop:(id )info + row:(NSInteger)row + dropOperation:(NSTableViewDropOperation)dropOperation { + NSPasteboard *pboard = [info draggingPasteboard]; + if ([pboard.types containsObject:PB_ROW]) { + NSString *value = [pboard stringForType:PB_ROW]; + NSInteger srcRow = [value intValue]; + row -= srcRow < row; + [self.mappingList beginUpdates]; + [self.mappingList moveRowAtIndex:srcRow toIndex:row]; + [self.mappingList endUpdates]; + [self.delegate mappingsViewController:self + moveMappingFromIndex:srcRow + toIndex:row]; + return YES; + } else if ([pboard.types containsObject:NSURLPboardType]) { + NSURL *url = [NSURL URLFromPasteboard:pboard]; + NSError *error; + if (![self.delegate mappingsViewController:self + importMappingFromURL:url + atIndex:row + error:&error]) { + [tableView presentError:error]; + return NO; + } else { + return YES; + } + } else { + return NO; + } +} + +- (NSDragOperation)tableView:(NSTableView *)tableView + validateDrop:(id )info + proposedRow:(NSInteger)row + proposedDropOperation:(NSTableViewDropOperation)dropOperation { + NSPasteboard *pboard = [info draggingPasteboard]; + if ([pboard.types containsObject:PB_ROW]) { + [tableView setDropRow:MAX(1, row) dropOperation:NSTableViewDropAbove]; + return NSDragOperationMove; + } else if ([pboard.types containsObject:NSURLPboardType]) { + NSURL *url = [NSURL URLFromPasteboard:pboard]; + if ([url.pathExtension isEqualToString:@"enjoyable"]) { + [tableView setDropRow:MAX(1, row) dropOperation:NSTableViewDropAbove]; + return NSDragOperationCopy; + } else { + return NSDragOperationNone; + } + } else { + return NSDragOperationNone; + } +} + +- (NSArray *)tableView:(NSTableView *)tableView +namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination +forDraggedRowsWithIndexes:(NSIndexSet *)indexSet { + NJMapping *toSave = [self.delegate mappingsViewController:self + mappingForIndex:indexSet.firstIndex]; + NSString *filename = [[toSave.name stringByFixingPathComponent] + stringByAppendingPathExtension:@"enjoyable"]; + NSURL *dst = [dropDestination URLByAppendingPathComponent:filename]; + dst = [NSFileManager.defaultManager generateUniqueURLWithBase:dst]; + NSError *error; + if (![toSave writeToURL:dst error:&error]) { + [tableView presentError:error]; + return @[]; + } else { + return @[dst.lastPathComponent]; + } +} + +- (BOOL)tableView:(NSTableView *)tableView +writeRowsWithIndexes:(NSIndexSet *)rowIndexes + toPasteboard:(NSPasteboard *)pboard { + if (rowIndexes.count == 1 && rowIndexes.firstIndex != 0) { + [pboard declareTypes:@[PB_ROW, NSFilesPromisePboardType] owner:nil]; + [pboard setString:@(rowIndexes.firstIndex).stringValue forType:PB_ROW]; + [pboard setPropertyList:@[@"enjoyable"] forType:NSFilesPromisePboardType]; + return YES; + } else if (rowIndexes.count == 1 && rowIndexes.firstIndex == 0) { + [pboard declareTypes:@[NSFilesPromisePboardType] owner:nil]; + [pboard setPropertyList:@[@"enjoyable"] forType:NSFilesPromisePboardType]; + return YES; + } else { + return NO; + } +} + +- (void)reloadData { + [self.mappingList reloadData]; +} + +@end + diff --git a/Classes/NJOutput.h b/Classes/NJOutput.h index b82c4e7..5d4d470 100644 --- a/Classes/NJOutput.h +++ b/Classes/NJOutput.h @@ -20,7 +20,7 @@ - (NSDictionary *)serialize; + (NJOutput *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings; + withMappings:(id )mappings; + (NSString *)serializationCode; @end diff --git a/Classes/NJOutput.m b/Classes/NJOutput.m index 409b3e6..35a56d9 100644 --- a/Classes/NJOutput.m +++ b/Classes/NJOutput.m @@ -37,7 +37,7 @@ } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings { + withMappings:(id )mappings { // Don't crash loading old/bad mappings (but don't load them either). if (![serialization isKindOfClass:NSDictionary.class]) return nil; diff --git a/Classes/NJOutputKeyPress.m b/Classes/NJOutputKeyPress.m index 1cc7e65..e80aba5 100644 --- a/Classes/NJOutputKeyPress.m +++ b/Classes/NJOutputKeyPress.m @@ -22,7 +22,7 @@ } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings { + withMappings:(id )mappings { NJOutputKeyPress *output = [[NJOutputKeyPress alloc] init]; output.keyCode = [serialization[@"key"] intValue]; return output; diff --git a/Classes/NJOutputMapping.m b/Classes/NJOutputMapping.m index fa8fda1..28a84ab 100644 --- a/Classes/NJOutputMapping.m +++ b/Classes/NJOutputMapping.m @@ -24,7 +24,7 @@ } + (NJOutputMapping *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings { + withMappings:(id )mappings { NSString *name = serialization[@"name"]; NJOutputMapping *output = [[NJOutputMapping alloc] init]; for (NJMapping *mapping in mappings) { diff --git a/Classes/NJOutputMouseButton.m b/Classes/NJOutputMouseButton.m index 5ddb69d..e01e763 100644 --- a/Classes/NJOutputMouseButton.m +++ b/Classes/NJOutputMouseButton.m @@ -37,7 +37,7 @@ } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings { + withMappings:(id )mappings { NJOutputMouseButton *output = [[NJOutputMouseButton alloc] init]; output.button = [serialization[@"button"] intValue]; return output; diff --git a/Classes/NJOutputMouseMove.m b/Classes/NJOutputMouseMove.m index be8b076..8591923 100644 --- a/Classes/NJOutputMouseMove.m +++ b/Classes/NJOutputMouseMove.m @@ -23,7 +23,7 @@ } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings { + withMappings:(id )mappings { NJOutputMouseMove *output = [[NJOutputMouseMove alloc] init]; output.axis = [serialization[@"axis"] intValue]; output.speed = [serialization[@"speed"] floatValue]; diff --git a/Classes/NJOutputMouseScroll.m b/Classes/NJOutputMouseScroll.m index b97a3e7..6fdc918 100644 --- a/Classes/NJOutputMouseScroll.m +++ b/Classes/NJOutputMouseScroll.m @@ -22,7 +22,7 @@ } + (NJOutput *)outputDeserialize:(NSDictionary *)serialization - withMappings:(NSArray *)mappings { + withMappings:(id )mappings { NJOutputMouseScroll *output = [[NJOutputMouseScroll alloc] init]; output.direction = [serialization[@"direction"] intValue]; output.speed = [serialization[@"speed"] floatValue]; diff --git a/Enjoyable.xcodeproj/project.pbxproj b/Enjoyable.xcodeproj/project.pbxproj index e633c35..27ca44a 100644 --- a/Enjoyable.xcodeproj/project.pbxproj +++ b/Enjoyable.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ EE52145C16F3E8BD00E3C574 /* NSOutlineView+ItemAccessors.m in Sources */ = {isa = PBXBuildFile; fileRef = EE52145B16F3E8BD00E3C574 /* NSOutlineView+ItemAccessors.m */; }; EE52145F16F404D500E3C574 /* NJDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE52145E16F404D500E3C574 /* NJDeviceViewController.m */; }; EE6A122E16E8F46300EDBD32 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EE6A122D16E8F46300EDBD32 /* Icon.icns */; }; + EE83ACEC16F545EA00083E94 /* NJMappingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE83ACEB16F545EA00083E94 /* NJMappingsViewController.m */; }; EE8455DD16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m in Sources */ = {isa = PBXBuildFile; fileRef = EE8455DC16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m */; }; EED4CE6E16ED692400C65AA8 /* NJMappingMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = EED4CE6D16ED692400C65AA8 /* NJMappingMenuController.m */; }; EED4CE7716EE195100C65AA8 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EED4CE7616EE195100C65AA8 /* Sparkle.framework */; }; @@ -85,6 +86,8 @@ EE52145D16F404D500E3C574 /* NJDeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJDeviceViewController.h; path = Classes/NJDeviceViewController.h; sourceTree = ""; }; EE52145E16F404D500E3C574 /* NJDeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJDeviceViewController.m; path = Classes/NJDeviceViewController.m; sourceTree = ""; }; EE6A122D16E8F46300EDBD32 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; }; + EE83ACEA16F545EA00083E94 /* NJMappingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJMappingsViewController.h; path = Classes/NJMappingsViewController.h; sourceTree = ""; }; + EE83ACEB16F545EA00083E94 /* NJMappingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJMappingsViewController.m; path = Classes/NJMappingsViewController.m; sourceTree = ""; }; EE8455DB16F0E46B00F32A01 /* NSRunningApplication+LoginItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSRunningApplication+LoginItem.h"; path = "Categories/NSRunningApplication+LoginItem.h"; sourceTree = ""; }; EE8455DC16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSRunningApplication+LoginItem.m"; path = "Categories/NSRunningApplication+LoginItem.m"; sourceTree = ""; }; EED4CE6C16ED692400C65AA8 /* NJMappingMenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJMappingMenuController.h; path = Classes/NJMappingMenuController.h; sourceTree = ""; }; @@ -210,6 +213,8 @@ EEE703DB16F089FE002FDD69 /* NJHIDManager.m */, EE52145D16F404D500E3C574 /* NJDeviceViewController.h */, EE52145E16F404D500E3C574 /* NJDeviceViewController.m */, + EE83ACEA16F545EA00083E94 /* NJMappingsViewController.h */, + EE83ACEB16F545EA00083E94 /* NJMappingsViewController.m */, ); name = Classes; sourceTree = ""; @@ -454,6 +459,7 @@ EE8455DD16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m in Sources */, EE52145C16F3E8BD00E3C574 /* NSOutlineView+ItemAccessors.m in Sources */, EE52145F16F404D500E3C574 /* NJDeviceViewController.m in Sources */, + EE83ACEC16F545EA00083E94 /* NJMappingsViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Info.plist b/Info.plist index 0b9f61d..673fcbd 100644 --- a/Info.plist +++ b/Info.plist @@ -46,7 +46,7 @@ CFBundleSignature ???? CFBundleVersion - 328 + 444 LSApplicationCategoryType public.app-category.utilities NSHumanReadableCopyright diff --git a/Resources/English.lproj/MainMenu.xib b/Resources/English.lproj/MainMenu.xib index 48ed439..6afbc50 100644 --- a/Resources/English.lproj/MainMenu.xib +++ b/Resources/English.lproj/MainMenu.xib @@ -37,7 +37,6 @@ NSToolbarFlexibleSpaceItem NSToolbarItem NSView - NSViewController NSWindowTemplate @@ -567,7 +566,7 @@ aW5nLg {232, 321} - + YES NO YES @@ -697,7 +696,7 @@ aW5nLg {234, 323} - + 150034 @@ -767,7 +766,6 @@ aW5nLg {{343, 31}, {70, 18}} - _NS:9 YES @@ -1192,7 +1190,7 @@ aW5nLg YES - + 256 @@ -1208,6 +1206,7 @@ aW5nLg 256 {198, 198} + YES NO @@ -1265,6 +1264,7 @@ aW5nLg {{1, 1}, {198, 198}} + @@ -1275,6 +1275,7 @@ aW5nLg -2147483392 {{306, 1}, {15, 403}} + NO @@ -1286,6 +1287,7 @@ aW5nLg -2147483392 {{-100, -100}, {366, 16}} + NO 1 @@ -1296,6 +1298,7 @@ aW5nLg {{0, 20}, {200, 200}} + 150034 @@ -1311,6 +1314,7 @@ aW5nLg 268 {{66, -1}, {68, 23}} + _NS:22 YES @@ -1339,6 +1343,7 @@ aW5nLg 292 {{0, -1}, {34, 23}} + YES @@ -1365,6 +1370,7 @@ aW5nLg 292 {{166, -1}, {34, 23}} + YES 67108864 @@ -1386,6 +1392,7 @@ aW5nLg 292 {{133, -1}, {34, 23}} + YES @@ -1408,6 +1415,7 @@ aW5nLg 292 {{33, -1}, {34, 23}} + YES @@ -1431,6 +1439,8 @@ aW5nLg {200, 220} + + NSView @@ -1446,7 +1456,6 @@ aW5nLg NJOutputController - 0 @@ -1542,6 +1551,9 @@ aW5nLg NJDeviceViewController + + NJMappingsViewController + @@ -1643,19 +1655,19 @@ aW5nLg - delegate + dataSource - + - 517 + 1001 - dataSource + delegate - + - 518 + 1002 @@ -1763,115 +1775,35 @@ aW5nLg - removePressed: - - - - 516 - - - - removeButton - - - - 519 - - - - tableView - - - - 520 - - - - exportPressed: - + exportMappingClicked: + - 815 + 1015 - importPressed: - + importMappingClicked: + - 816 - - - - mappingPressed: - - - - 855 - - - - popover - - - - 856 - - - - popoverActivate - - - - 857 - - - - addPressed: - - - - 515 + 1016 - moveUpPressed: - - - - 899 - - - - moveDownPressed: - - - - 900 - - - - moveUp - - + performClick: + + - 901 + 1012 - moveDown - - - - 902 - - - - addPressed: + mvc - + - 971 + 995 @@ -2057,29 +1989,21 @@ aW5nLg 871 - - - view - - - - 854 - contentViewController - + - 852 + 996 delegate - + - 853 + 1004 @@ -2217,6 +2141,110 @@ aW5nLg 989 + + + delegate + + + + 994 + + + + view + + + + 997 + + + + mappingTriggerClicked: + + + + 998 + + + + mappingListTrigger + + + + 999 + + + + mappingListPopover + + + + 1000 + + + + mappingList + + + + 1003 + + + + removeClicked: + + + + 1005 + + + + removeMapping + + + + 1006 + + + + addClicked: + + + + 1007 + + + + moveDownClicked: + + + + 1008 + + + + moveUpClicked: + + + + 1009 + + + + moveDown + + + + 1010 + + + + moveUp + + + + 1011 + @@ -2555,12 +2583,6 @@ aW5nLg - - 850 - - - Popover View Controller - 851 @@ -3052,6 +3074,11 @@ aW5nLg + + 993 + + + @@ -3163,7 +3190,6 @@ aW5nLg com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3304,29 +3330,38 @@ aW5nLg com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin - 992 + 1016 EnjoyableApplicationDelegate NSObject - - restoreToForeground: - id - - - restoreToForeground: - + + id + id + id + + + + exportMappingClicked: + id + + + importMappingClicked: + id + + restoreToForeground: id - + NSMenu NJMappingsController @@ -3480,54 +3515,80 @@ aW5nLg NJMappingsController NSObject + + mvc + NJMappingsViewController + + + mvc + + mvc + NJMappingsViewController + + + + IBProjectSource + ./Classes/NJMappingsController.h + + + + NJMappingsViewController + NSViewController - id - id - id - id - id - id - id + id + id + id + id + id - - addPressed: + + addClicked: id - - exportPressed: + + mappingTriggerClicked: id - - importPressed: + + moveDownClicked: id - - mappingPressed: + + moveUpClicked: id - - moveDownPressed: - id - - - moveUpPressed: - id - - - removePressed: + + removeClicked: id + id + NSTableView + NSPopover + NSButton NSButton NSButton - NSPopover - NSButton - NSButton - NSTableView + NSButton + + delegate + id + + + mappingList + NSTableView + + + mappingListPopover + NSPopover + + + mappingListTrigger + NSButton + moveDown NSButton @@ -3536,26 +3597,14 @@ aW5nLg moveUp NSButton - - popover - NSPopover - - - popoverActivate - NSButton - - - removeButton + + removeMapping NSButton - - tableView - NSTableView - IBProjectSource - ./Classes/NJMappingsController.h + ./Classes/NJMappingsViewController.h