App delegate now controls communication between device / mapping controllers and...
[enjoyable.git] / Classes / NJMappingsController.m
index 531de12..44a9c43 100644 (file)
@@ -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;
 }
 
 - (void)mappingsSet {
+    [self postLoadProcess];
     [NSNotificationCenter.defaultCenter
         postNotificationName:NJEventMappingListChanged
                       object:self
                     userInfo:@{ NJMappingListKey: _mappings,
                                 NJMappingKey: _currentMapping }];
-    [self.mvc changedActiveMappingToIndex:[_mappings indexOfObjectIdenticalTo:_currentMapping]];
 }
 
 - (void)mappingsChanged {
     _manualMapping = oldMapping;
 }
 
+- (void)activateMappingForcibly:(NJMapping *)mapping {
+    NSLog(@"Switching to mapping %@.", mapping.name);
+    _currentMapping = mapping;
+    NSUInteger idx = [self indexOfMapping:_currentMapping];
+    [NSNotificationCenter.defaultCenter
+     postNotificationName:NJEventMappingChanged
+                  object:self
+                userInfo:@{ NJMappingKey : _currentMapping,
+                            NJMappingIndexKey: @(idx) }];
+}
+
 - (void)activateMapping:(NJMapping *)mapping {
     if (!mapping)
         mapping = _manualMapping;
     if (mapping == _currentMapping)
         return;
-    NSLog(@"Switching to mapping %@.", mapping.name);
     _manualMapping = mapping;
-    _currentMapping = mapping;
-    [self.mvc changedActiveMappingToIndex:[_mappings indexOfObjectIdenticalTo:_currentMapping]];
-    [NSNotificationCenter.defaultCenter
-         postNotificationName:NJEventMappingChanged
-                       object:self
-                     userInfo:@{ NJMappingKey : _currentMapping }];
+    [self activateMappingForcibly:mapping];
 }
 
 - (void)save {
     [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"];
 }
 
+- (void)postLoadProcess {
+    for (NJMapping *mapping in self)
+        [mapping postLoadProcess:self];
+}
+
 - (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.mvc reloadData];
         [self activateMapping:_mappings[selected]];
         [self mappingsSet];
     }
 }
 
-- (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];
-            _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];
-            break;
-        default: // Cancel, other.
-            break;
-    }
+- (NSInteger)indexOfMapping:(NJMapping *)mapping {
+    return [_mappings indexOfObjectIdenticalTo:mapping];
 }
 
-- (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]) {
-            NSAlert *conflictAlert = [[NSAlert alloc] init];
-            conflictAlert.messageText = NSLocalizedString(@"import conflict prompt", @"Title of import conflict alert");
-            conflictAlert.informativeText =
-            [NSString stringWithFormat:NSLocalizedString(@"import conflict in %@", @"Explanation of import conflict"),
-                                       mapping.name];
-            [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:window
-                                      modalDelegate:self
-                                     didEndSelector:@selector(mappingConflictDidResolve:returnCode:contextInfo:)
-                                        contextInfo:(void *)CFBridgingRetain(@{ @"old mapping": mergeInto,
-                                                                                @"new mapping": mapping })];
-        } else if (mergeInto) {
-            [mergeInto mergeEntriesFrom:mapping];
-            [self activateMapping:mergeInto];
-            [self mappingsChanged];
-        } else {
-            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];
-        }
-    }
-}
-
-- (NSInteger)numberOfMappings:(NJMappingsViewController *)dvc {
-    return _mappings.count;
-}
-
-- (NJMapping *)mappingsViewController:(NJMappingsViewController *)dvc
-                      mappingForIndex:(NSUInteger)idx {
-    return _mappings[idx];
-}
-
-- (void)mappingsViewController:(NJMappingsViewController *)mvc
-          editedMappingAtIndex:(NSInteger)index {
+- (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing {
+    [existing mergeEntriesFrom:mapping];
     [self mappingsChanged];
+    if (existing == _currentMapping)
+        [self activateMappingForcibly:mapping];
 }
 
-- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc
-       canMoveMappingFromIndex:(NSInteger)fromIdx
-                       toIndex:(NSInteger)toIdx {
-    return fromIdx != toIdx && fromIdx != 0 && toIdx != 0 && toIdx < (NSInteger)_mappings.count;
+- (void)renameMapping:(NJMapping *)mapping to:(NSString *)name {
+    mapping.name = name;
+    [self mappingsChanged];
+    if (mapping == _currentMapping)
+        [self activateMappingForcibly:mapping];
 }
 
-- (void)mappingsViewController:(NJMappingsViewController *)mvc
-          moveMappingFromIndex:(NSInteger)fromIdx
-                       toIndex:(NSInteger)toIdx {
-    [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx];
-    [self mappingsChanged];
+- (void)addMapping:(NJMapping *)mapping {
+    [self insertMapping:mapping atIndex:_mappings.count];
 }
 
-- (BOOL)mappingsViewController:(NJMappingsViewController *)mvc
-       canRemoveMappingAtIndex:(NSInteger)idx {
-    return idx != 0;
+- (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx {
+    [_mappings insertObject:mapping atIndex:idx];
+    [self mappingsChanged];    
 }
 
-- (void)mappingsViewController:(NJMappingsViewController *)mvc
-          removeMappingAtIndex:(NSInteger)idx {
-    NJMapping *old = self[idx];
-    [self.mvc.mappingList beginUpdates];
+- (void)removeMappingAtIndex:(NSInteger)idx {
+    NSInteger currentIdx = [self indexOfMapping:_currentMapping];
     [_mappings removeObjectAtIndex:idx];
-    [self.mvc removedMappingAtIndex:idx];
-    [self.mvc.mappingList endUpdates];
-    if (old == _currentMapping)
-        [self activateMapping:self[MIN(idx, _mappings.count - 1)]];
+    [self activateMapping:self[MIN(currentIdx, _mappings.count - 1)]];
     [self mappingsChanged];
 }
 
-- (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];
+- (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx {
+    [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx];
     [self mappingsChanged];
 }
 
-- (void)mappingsViewController:(NJMappingsViewController *)mvc
-                  choseMappingAtIndex:(NSInteger)idx {
-    [self activateMapping:self[idx]];
+- (NSUInteger)count {
+    return _mappings.count;
 }
 
 @end