X-Git-Url: https://git.yukkurigames.com/?p=enjoyable.git;a=blobdiff_plain;f=Classes%2FNJMappingsController.m;h=44a9c43e1eb2819e20f050350d9b8de4434907ad;hp=5faa4bf47d0384dac19695592aacf51335fa36c9;hb=6a7c78afa7b8a34901f59a79afe41d18855734bc;hpb=52fbe3168fcb8237252bdc2a723c08eb7c1a8741 diff --git a/Classes/NJMappingsController.m b/Classes/NJMappingsController.m index 5faa4bf..44a9c43 100644 --- a/Classes/NJMappingsController.m +++ b/Classes/NJMappingsController.m @@ -8,12 +8,9 @@ #import "NJMappingsController.h" #import "NJMapping.h" -#import "NJMappingsController.h" #import "NJOutput.h" #import "NJEvents.h" -#define PB_ROW @"com.yukkurigames.Enjoyable.MappingRow" - @implementation NJMappingsController { NSMutableArray *_mappings; NJMapping *_manualMapping; @@ -22,18 +19,14 @@ - (id)init { if ((self = [super init])) { _mappings = [[NSMutableArray alloc] init]; - _currentMapping = [[NJMapping alloc] initWithName:@"(default)"]; + _currentMapping = [[NJMapping alloc] initWithName: + NSLocalizedString(@"(default)", @"default name for first the mapping")]; _manualMapping = _currentMapping; [_mappings addObject:_currentMapping]; } 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]) @@ -45,10 +38,8 @@ return idx < _mappings.count ? _mappings[idx] : nil; } -- (void)mappingsChanged { - [self save]; - [tableView reloadData]; - [self updateInterfaceForCurrentMapping]; +- (void)mappingsSet { + [self postLoadProcess]; [NSNotificationCenter.defaultCenter postNotificationName:NJEventMappingListChanged object:self @@ -56,6 +47,11 @@ NJMappingKey: _currentMapping }]; } +- (void)mappingsChanged { + [self save]; + [self mappingsSet]; +} + - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id [])buffer count:(NSUInteger)len { @@ -79,7 +75,9 @@ if (!found) { [self activateMapping:oldMapping]; - if ([oldMapping.name.lowercaseString isEqualToString:@"@application"]) { + if ([oldMapping.name.lowercaseString isEqualToString:@"@application"] + || [oldMapping.name.lowercaseString isEqualToString: + NSLocalizedString(@"@Application", nil).lowercaseString]) { oldMapping.name = app.bestMappingName; [self mappingsChanged]; } @@ -87,14 +85,15 @@ _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)activateMappingForcibly:(NJMapping *)mapping { + NSLog(@"Switching to mapping %@.", mapping.name); + _currentMapping = mapping; + NSUInteger idx = [self indexOfMapping:_currentMapping]; + [NSNotificationCenter.defaultCenter + postNotificationName:NJEventMappingChanged + object:self + userInfo:@{ NJMappingKey : _currentMapping, + NJMappingIndexKey: @(idx) }]; } - (void)activateMapping:(NJMapping *)mapping { @@ -102,56 +101,8 @@ mapping = _manualMapping; if (mapping == _currentMapping) return; - NSLog(@"Switching to mapping %@.", mapping.name); _manualMapping = mapping; - _currentMapping = mapping; - [self updateInterfaceForCurrentMapping]; - [NSNotificationCenter.defaultCenter - postNotificationName:NJEventMappingChanged - object:self - userInfo:@{ NJMappingKey : _currentMapping }]; -} - -- (IBAction)addPressed:(id)sender { - NJMapping *newMapping = [[NJMapping alloc] initWithName:@"Untitled"]; - [_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; + [self activateMappingForcibly:mapping]; } - (void)save { @@ -162,249 +113,70 @@ [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"]; } -- (void)load { - NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"]; - NSArray *mappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"]; - [self loadAllFrom:mappings andActivate:selected]; +- (void)postLoadProcess { + for (NJMapping *mapping in self) + [mapping postLoadProcess:self]; } -- (void)loadAllFrom:(NSArray *)storedMappings andActivate:(NSUInteger)selected { +- (void)load { + NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"]; + NSArray *storedMappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"]; NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count]; - // Requires two passes to deal with inter-mapping references. First make - // an empty mapping for each serialized mapping. Then, deserialize the - // data pointing to the empty mappings. Then merge that data back into - // its equivalent empty one, which is the one we finally use. - for (NSDictionary *storedMapping in storedMappings) { - NJMapping *mapping = [[NJMapping alloc] initWithName:storedMapping[@"name"]]; - [newMappings addObject:mapping]; - } - - for (unsigned i = 0; i < storedMappings.count; ++i) { - NJMapping *realMapping = [[NJMapping alloc] initWithSerialization:storedMappings[i] - mappings:newMappings]; - [newMappings[i] mergeEntriesFrom:realMapping]; - } + for (NSDictionary *serialization in storedMappings) + [newMappings addObject: + [[NJMapping alloc] initWithSerialization:serialization]]; if (newMappings.count) { _mappings = newMappings; if (selected >= newMappings.count) selected = 0; [self activateMapping:_mappings[selected]]; - [self mappingsChanged]; - } -} - -- (void)mappingConflictDidResolve:(NSAlert *)alert - returnCode:(NSInteger)returnCode - contextInfo:(void *)contextInfo { - NSDictionary *userInfo = CFBridgingRelease(contextInfo); - NJMapping *oldMapping = userInfo[@"old mapping"]; - NJMapping *newMapping = userInfo[@"new mapping"]; - switch (returnCode) { - case NSAlertFirstButtonReturn: // Merge - [oldMapping mergeEntriesFrom:newMapping]; - [self activateMapping:oldMapping]; - [self mappingsChanged]; - break; - case NSAlertThirdButtonReturn: // New Mapping - [_mappings addObject:newMapping]; - [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]; - - if (mapping && !error) { - NJMapping *mergeInto = self[mapping.name]; - if ([mergeInto hasConflictWith:mapping]) { - 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"]; - [conflictAlert beginSheetModalForWindow:popoverActivate.window - modalDelegate:self - didEndSelector:@selector(mappingConflictDidResolve:returnCode:contextInfo:) - contextInfo:(void *)CFBridgingRetain(@{ @"old mapping": mergeInto, - @"new mapping": mapping })]; - } else { - [_mappings addObject:mapping]; - [self activateMapping:mapping]; - [self mappingsChanged]; - } - } - - if (error) { - [window presentError:error - modalForWindow:window - delegate:nil - didPresentSelector:nil - contextInfo:nil]; + [self mappingsSet]; } } -- (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)indexOfMapping:(NJMapping *)mapping { + return [_mappings indexOfObjectIdenticalTo:mapping]; } -- (void)popoverWillShow:(NSNotification *)notification { - popoverActivate.state = NSOnState; -} - -- (void)popoverWillClose:(NSNotification *)notification { - popoverActivate.state = NSOffState; +- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing { + [existing mergeEntriesFrom:mapping]; + [self mappingsChanged]; + if (existing == _currentMapping) + [self activateMappingForcibly:mapping]; } -- (IBAction)moveUpPressed:(id)sender { - if ([_mappings moveFirstwards:_currentMapping upTo:1]) - [self mappingsChanged]; +- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name { + mapping.name = name; + [self mappingsChanged]; + if (mapping == _currentMapping) + [self activateMappingForcibly:mapping]; } -- (IBAction)moveDownPressed:(id)sender { - if ([_mappings moveLastwards:_currentMapping]) - [self mappingsChanged]; +- (void)addMapping:(NJMapping *)mapping { + [self insertMapping:mapping atIndex:_mappings.count]; } -- (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; - } +- (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx { + [_mappings insertObject:mapping atIndex:idx]; + [self mappingsChanged]; } -- (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)removeMappingAtIndex:(NSInteger)idx { + NSInteger currentIdx = [self indexOfMapping:_currentMapping]; + [_mappings removeObjectAtIndex:idx]; + [self activateMapping:self[MIN(currentIdx, _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]; - } +- (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx { + [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx]; + [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; - } +- (NSUInteger)count { + return _mappings.count; } @end