Implement equality checks for Targets. Don't consider equal targets as conflicting...
[enjoyable.git] / ConfigsController.m
index a3b8bcd..fb50bc3 100644 (file)
@@ -12,6 +12,7 @@
 #import "ConfigsController.h"
 #import "Target.h"
 #import "TargetController.h"
+#import "NJEvents.h"
 
 @implementation ConfigsController {
     NSMutableArray *_configs;
 
 - (void)activateConfigForProcess:(NSString *)processName {
     Config *oldConfig = manualConfig;
-    [self activateConfig:self[processName]];
+    Config *newConfig = self[processName];
+    if (!newConfig)
+        newConfig = oldConfig;
+    if (newConfig != _currentConfig)
+        [self activateConfig:newConfig];
     manualConfig = oldConfig;
 }
 
 - (void)activateConfig:(Config *)config {
     if (!config)
         config = manualConfig;
-    if (_currentConfig == config)
-        return;
+    NSLog(@"Switching to mapping %@.", config.name);
     manualConfig = config;
     _currentConfig = config;
     [removeButton setEnabled:_configs[0] != config];
     [targetController loadCurrent];
-    [(ApplicationController *)[[NSApplication sharedApplication] delegate] configChanged];
+    [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];
+    [(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 {
@@ -69,7 +75,7 @@
     
     [_configs removeObjectAtIndex:tableView.selectedRow];
     [tableView reloadData];
-    [(ApplicationController *)[[NSApplication sharedApplication] delegate] configsChanged];
+    [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
     [self activateConfig:_configs[0]];
     [self save];
 }
@@ -86,7 +92,7 @@
 - (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];
+    [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
 }
 
 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
 }
 
 - (void)save {
-    NSLog(@"Saving defaults.");
-    [[NSUserDefaults standardUserDefaults] setObject:[self dumpAll] forKey:@"configurations"];
+    NSLog(@"Saving mappings to defaults.");
+    [NSUserDefaults.standardUserDefaults setObject:[self dumpAll] forKey:@"configurations"];
 }
 
 - (void)load {
-    [self loadAllFrom:[[NSUserDefaults standardUserDefaults] objectForKey:@"configurations"]];
+    [self loadAllFrom:[NSUserDefaults.standardUserDefaults objectForKey:@"configurations"]];
 }
 
 - (NSDictionary *)dumpAll {
             current = 0;
         _configs = newConfigs;
         [tableView reloadData];
-        [(ApplicationController *)[[NSApplication sharedApplication] delegate] configsChanged];
+        [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
         [self activateConfig:_configs[current]];
     }
 }
         : nil;
     [stream close];
     
-    if (!([serialization isKindOfClass:[NSDictionary class]]
-          && serialization[@"entries"])) {
+    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."];
+                                     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)
-        cfg.entries[key] = [Target targetDeserialize:entries[key]
-                                         withConfigs:_configs];
+    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;
 }
 
                           BOOL conflict;
                           Config *mergeInto = self[cfg.name];
                           for (id key in cfg.entries) {
-                              if (mergeInto.entries[key]) {
+                              if (mergeInto.entries[key]
+                                  && ![mergeInto.entries[key] isEqual:cfg.entries[key]]) {
                                   conflict = YES;
                                   break;
                               }
                           }
                           
                           [self save];
-                          [(ApplicationController *)[[NSApplication sharedApplication] delegate] configsChanged];
+                          [(ApplicationController *)NSApplication.sharedApplication.delegate configsChanged];
                           [self activateConfig:cfg];
                           [targetController loadCurrent];
                           
                       }
                       
                       if (error) {
-                          [[NSAlert alertWithError:error] beginSheetModalForWindow:window
-                                                                     modalDelegate:nil
-                                                                    didEndSelector:nil
-                                                                       contextInfo:nil];
+                          [window presentError:error
+                                modalForWindow:window
+                                      delegate:nil
+                            didPresentSelector:nil
+                                   contextInfo:nil];
                       }
                   }];
      
     NSWindow *window = NSApplication.sharedApplication.keyWindow;
     [panel beginSheetModalForWindow:window
                   completionHandler:^(NSInteger result) {
-                      if (result == NSFileHandlingPanelOKButton) {
-                          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) {
-                              // FIXME: Ideally, this sheet is attached to the
-                              // panel, and the panel doesn't close, so you
-                              // can maybe fix what is wrong and try saving
-                              // again. But it seems to be impossible to force
-                              // the panel to stay open.
-                              [panel close];
-                              [[NSAlert alertWithError:error] beginSheetModalForWindow:window
-                                                                         modalDelegate:nil
-                                                                        didEndSelector:nil
-                                                                           contextInfo:nil];
-                          }
+                      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];
                       }
                   }];
 }