Support sudden and automatic termination.
[enjoyable.git] / NJMappingsController.m
index e5b2b7d..43f6282 100644 (file)
@@ -7,11 +7,10 @@
 
 #import "NJMappingsController.h"
 
-#import "ApplicationController.h"
 #import "NJMapping.h"
 #import "NJMappingsController.h"
-#import "Target.h"
-#import "TargetController.h"
+#import "NJOutput.h"
+#import "NJOutputController.h"
 #import "NJEvents.h"
 
 @implementation NJMappingsController {
     return nil;
 }
 
+- (NJMapping *)objectAtIndexedSubscript:(NSUInteger)idx {
+    return idx < _mappings.count ? _mappings[idx] : nil;
+}
+
+- (void)mappingsChanged {
+    [self save];
+    [tableView reloadData];
+    popoverActivate.title = _currentMapping.name;
+    [NSNotificationCenter.defaultCenter
+        postNotificationName:NJEventMappingListChanged
+        object:_mappings];
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
+                                  objects:(__unsafe_unretained id [])buffer
+                                    count:(NSUInteger)len {
+    return [_mappings countByEnumeratingWithState:state
+                                          objects:buffer
+                                            count:len];
+}
+
+
 - (void)activateMappingForProcess:(NSString *)processName {
     NJMapping *oldMapping = manualMapping;
     NJMapping *newMapping = self[processName];
 - (void)activateMapping:(NJMapping *)mapping {
     if (!mapping)
         mapping = manualMapping;
+    if (mapping == _currentMapping)
+        return;
     NSLog(@"Switching to mapping %@.", mapping.name);
     manualMapping = mapping;
     _currentMapping = mapping;
     [removeButton setEnabled:_mappings[0] != mapping];
-    [targetController loadCurrent];
+    [outputController loadCurrent];
+    popoverActivate.title = _currentMapping.name;
+    NSUInteger selected = [_mappings indexOfObject:mapping];
+    [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:selected] byExtendingSelection:NO];
+    [NSUserDefaults.standardUserDefaults setInteger:selected forKey:@"selected"];
     [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 mappingsChanged];
     [self activateMapping:newMapping];
+    [tableView editColumn:0 row:_mappings.count - 1 withEvent:nil select:YES];
 }
 
 - (IBAction)removePressed:(id)sender {
         return;
     
     [_mappings removeObjectAtIndex:tableView.selectedRow];
-    [tableView reloadData];
-    [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged];
+    [self mappingsChanged];
     [self activateMapping:_mappings[0]];
-    [self save];
 }
 
 -(void)tableViewSelectionDidChange:(NSNotification *)notify {
-    if (tableView.selectedRow >= 0)
-        [self activateMapping:_mappings[tableView.selectedRow]];
+    [self activateMapping:self[tableView.selectedRow]];
 }
 
 - (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index {
-    return [_mappings[index] name];
+    return self[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];
+- (void)tableView:(NSTableView *)view
+   setObjectValue:(NSString *)obj
+   forTableColumn:(NSTableColumn *)col
+              row:(NSInteger)index {
+    self[index].name = obj;
+    [self mappingsChanged];
 }
 
 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
 }
 
 - (BOOL)tableView:(NSTableView *)view shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)index {
-    return index > 0;
+    return YES;
 }
 
 - (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) };
+    [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"];
 }
 
-- (void)loadAllFrom:(NSDictionary*)envelope {
-    NSArray *storedMappings = envelope[@"mappings"];
+- (void)load {
+    NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"];
+    NSArray *mappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"];
+    [self loadAllFrom:mappings andActivate:selected];
+}
+
+- (void)loadAllFrom:(NSArray *)storedMappings andActivate:(NSUInteger)selected {
     NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count];
 
-    // have to do two passes in case mapping1 refers to mapping2 via a TargetMapping
+    // have to do two passes in case mapping1 refers to mapping2 via a NJOutputMapping
     for (NSDictionary *storedMapping in storedMappings) {
         NJMapping *mapping = [[NJMapping alloc] initWithName:storedMapping[@"name"]];
         [newMappings addObject:mapping];
         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;
+            NJOutput *output = [NJOutput outputDeserialize:entries[key]
+                                              withMappings:newMappings];
+            if (output)
+                mapping.entries[key] = output;
         }
     }
     
     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]];
+        if (selected >= newMappings.count)
+            selected = 0;
+        [self mappingsChanged];
+        [self activateMapping:_mappings[selected]];
     }
 }
 
     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;
+            NJOutput *output = [NJOutput outputDeserialize:value
+                                              withMappings:_mappings];
+            if (output)
+                mapping.entries[key] = output;
         }
     }
     return mapping;
                               mapping = mergeInto;
                           } else {
                               [_mappings addObject:mapping];
-                              [tableView reloadData];
                           }
                           
-                          [self save];
-                          [(ApplicationController *)NSApplication.sharedApplication.delegate mappingsChanged];
+                          [self mappingsChanged];
                           [self activateMapping:mapping];
-                          [targetController loadCurrent];
+                          [outputController loadCurrent];
                           
                           if (conflict && !mergeInto) {
                               [tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:_mappings.count - 1] byExtendingSelection:NO];
                       if (result != NSFileHandlingPanelOKButton)
                           return;
                       [panel close];
+                      [NSProcessInfo.processInfo disableSuddenTermination];
                       NSError *error;
                       NSDictionary *serialization = [mapping serialize];
                       NSData *json = [NSJSONSerialization dataWithJSONObject:serialization
                       if (!error)
                           [json writeToURL:panel.URL options:NSDataWritingAtomic error:&error];
                       
+                      [NSProcessInfo.processInfo enableSuddenTermination];
                       if (error) {
                           [window presentError:error
                                 modalForWindow:window
                   }];
 }
 
+- (IBAction)mappingPressed:(id)sender {
+    [popover showRelativeToRect:popoverActivate.bounds ofView:popoverActivate preferredEdge:NSMinXEdge];
+}
+
+- (void)popoverWillShow:(NSNotification *)notification {
+    popoverActivate.state = NSOnState;
+}
+
+- (void)popoverWillClose:(NSNotification *)notification {
+    popoverActivate.state = NSOffState;
+}
+
 @end