Save after deleting a config. Reset target to no-op when deleting its config, rather...
[enjoyable.git] / TargetController.m
index 9f85fd9..7a4fd05 100644 (file)
 //  Created by Sam McCall on 5/05/09.
 //
 
+#import "TargetController.h"
+
+#import "ConfigsController.h"
+#import "Config.h"
+#import "JSAction.h"
+#import "JoystickController.h"
+#import "KeyInputTextView.h"
+#import "TargetConfig.h"
+#import "TargetController.h"
+#import "TargetKeyboard.h"
+#import "TargetMouseBtn.h"
+#import "TargetMouseMove.h"
+#import "TargetMouseScroll.h"
+#import "TargetToggleMouseScope.h"
+
 @implementation TargetController
 
--(void) keyChanged {
-       [radioButtons setState: 1 atRow: 1 column: 0 ];
-       [self commit];
-}
--(IBAction)radioChanged:(id)sender {
-       [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender];
-       [self commit];
-}
--(IBAction)mdirChanged:(id)sender {
-    [radioButtons setState: 1 atRow: 3 column: 0];
-       [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender];
-       [self commit];
-}
--(IBAction)mbtnChanged:(id)sender {
-    [radioButtons setState: 1 atRow: 4 column: 0];
-       [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender];
-       [self commit];
-}
--(IBAction)sdirChanged:(id)sender {
-    [radioButtons setState: 1 atRow: 5 column: 0];
-       [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: sender];
-       [self commit];
-}
-
-
--(Target*) state {
-       switch([radioButtons selectedRow]) {
-               case 0: // none
-                       return NULL;
-               case 1: // key
-                       if([keyInput hasKey]) {
-                               TargetKeyboard* k = [[TargetKeyboard alloc] init];
-                               [k setVk: [keyInput vk]];
-                               [k setDescr: [keyInput descr]];
-                               return k;
-                       }
-                       break;
-               case 2:
-               {
-                       TargetConfig* c = [[TargetConfig alloc] init];
-                       [c setConfig: [configsController configs][[configPopup indexOfSelectedItem]]];
-                       return c;
-               }
+- (void)cleanUpInterface {
+    NSInteger row = radioButtons.selectedRow;
+    
+    if (row != 1) {
+        keyInput.vk = -1;
+        [keyInput resignIfFirstResponder];
+    }
+    
+    if (row != 2) {
+        [configPopup selectItemAtIndex:-1];
+        [configPopup resignIfFirstResponder];
+    } else if (!configPopup.selectedItem)
+        [configPopup selectItemAtIndex:0];
+    
+    if (row != 3) {
+        mouseDirSelect.selectedSegment = -1;
+        [mouseDirSelect resignIfFirstResponder];
+    } else if (mouseDirSelect.selectedSegment == -1)
+        mouseDirSelect.selectedSegment = 0;
+    
+    if (row != 4) {
+        mouseBtnSelect.selectedSegment = -1;
+        [mouseBtnSelect resignIfFirstResponder];
+    } else if (mouseBtnSelect.selectedSegment == -1)
+        mouseBtnSelect.selectedSegment = 0;
+    
+    if (row != 5) {
+        scrollDirSelect.selectedSegment = -1;
+        [scrollDirSelect resignIfFirstResponder];
+    } else if (scrollDirSelect.selectedSegment == -1)
+        scrollDirSelect.selectedSegment = 0;    
+}
+
+- (IBAction)radioChanged:(NSView *)sender {
+    [sender.window makeFirstResponder:sender];
+    if (radioButtons.selectedRow == 1)
+        [keyInput.window makeFirstResponder:keyInput];
+    [self commit];
+}
+
+- (void)keyChanged {
+    [radioButtons selectCellAtRow:1 column:0];
+    [radioButtons.window makeFirstResponder:radioButtons];
+    [self commit];
+}
+
+- (void)configChosen:(id)sender {
+    [radioButtons selectCellAtRow:2 column:0];
+    [configPopup.window makeFirstResponder:configPopup];
+    [self commit];
+}
+
+- (void)mdirChanged:(NSView *)sender {
+    [radioButtons selectCellAtRow:3 column:0];
+    [sender.window makeFirstResponder:sender];
+    [self commit];
+}
+
+- (void)mbtnChanged:(NSView *)sender {
+    [radioButtons selectCellAtRow:4 column:0];
+    [sender.window makeFirstResponder:sender];
+    [self commit];
+}
+
+- (void)sdirChanged:(NSView *)sender {
+    [radioButtons selectCellAtRow:5 column:0];
+    [sender.window makeFirstResponder:sender];
+    [self commit];
+}
+
+- (Target *)currentTarget {
+    return configsController.currentConfig[joystickController.selectedAction];
+}
+
+- (Target *)makeTarget {
+    switch (radioButtons.selectedRow) {
+        case 0:
+            return nil;
+        case 1:
+            if (keyInput.hasKey) {
+                TargetKeyboard *k = [[TargetKeyboard alloc] init];
+                k.vk = keyInput.vk;
+                return k;
+            } else {
+                return nil;
+            }
+            break;
+        case 2: {
+            TargetConfig *c = [[TargetConfig alloc] init];
+            c.config = configsController.configs[configPopup.indexOfSelectedItem];
+            return c;
+        }
         case 3: {
-            // mouse X/Y
             TargetMouseMove *mm = [[TargetMouseMove alloc] init];
-            [mm setDir: [mouseDirSelect selectedSegment]];
+            mm.axis = mouseDirSelect.selectedSegment;
             return mm;
         }
         case 4: {
-            // mouse button
             TargetMouseBtn *mb = [[TargetMouseBtn alloc] init];
-            if ([mouseBtnSelect selectedSegment] == 0) {
-                [mb setWhich: kCGMouseButtonLeft];
-            }
-            else {
-                [mb setWhich: kCGMouseButtonRight];
-            }
+            mb.button = mouseBtnSelect.selectedSegment == 0 ? kCGMouseButtonLeft : kCGMouseButtonRight;
             return mb;
         }
         case 5: {
-            // scroll
             TargetMouseScroll *ms = [[TargetMouseScroll alloc] init];
-            if ([scrollDirSelect selectedSegment] == 0) {
-                [ms setHowMuch: -1];
-            }
-            else {
-                [ms setHowMuch: 1];
-            }
+            ms.amount = scrollDirSelect.selectedSegment ? 1 : -1;
             return ms;
         }
         case 6: {
-            // toggle mouse scope
             TargetToggleMouseScope *tms = [[TargetToggleMouseScope alloc] init];
             return tms;
         }
-       }
-       return NULL;
-}
-
--(void)configChosen:(id)sender {
-       [radioButtons setState: 1 atRow: 2 column: 0];
-       [self commit];
-}
-
--(void) commit {
-       id action = [joystickController selectedAction];
-       if(action) {
-               Target* target = [self state];
-               [[configsController currentConfig] setTarget: target forAction: action];
-       }
-}
-
--(void) reset {
-       [keyInput clear];
-       [radioButtons setState: 1 atRow: 0 column: 0];
-    [mouseDirSelect setSelectedSegment: 0];
-    [mouseBtnSelect setSelectedSegment: 0];
-    [scrollDirSelect setSelectedSegment: 0];
-       [self refreshConfigsPreservingSelection: NO];
-}
-
--(void) setEnabled: (BOOL) enabled {
-       [radioButtons setEnabled: enabled];
-       [keyInput setEnabled: enabled];
-       [configPopup setEnabled: enabled];
-    [mouseDirSelect setEnabled: enabled];
-    [mouseBtnSelect setEnabled: enabled];
-    [scrollDirSelect setEnabled: enabled];
-}
--(BOOL) enabled {
-       return [radioButtons isEnabled];
-}
-
--(void) load {
-       id jsaction = [joystickController selectedAction];
-       currentJsaction = jsaction;
-       if(!jsaction) {
-               [self setEnabled: NO];
-               [title setStringValue: @""];
-               return;
-       } else {
-               [self setEnabled: YES];
-       }
-       Target* target = [[configsController currentConfig] getTargetForAction: jsaction];
-       
-       id act = jsaction;
-       NSString* actFullName = [act name];
-       while([act base]) {
-               act = [act base];
-               actFullName = [[NSString alloc] initWithFormat: @"%@ > %@", [act name], actFullName];
-       }
-       [title setStringValue: [[NSString alloc] initWithFormat: @"%@ > %@", [[configsController currentConfig] name], actFullName]];
-       
-       if(!target) {
-               // already reset
-       } else if([target isKindOfClass: [TargetKeyboard class]]) {
-               [radioButtons setState:1 atRow: 1 column: 0];
-               [keyInput setVk: [(TargetKeyboard*)target vk]];
-       } else if([target isKindOfClass: [TargetConfig class]]) {
-               [radioButtons setState:1 atRow: 2 column: 0];
-               [configPopup selectItemAtIndex: [[configsController configs] indexOfObject: [(TargetConfig*)target config]]];
+        default:
+            return nil;
     }
-    else if ([target isKindOfClass: [TargetMouseMove class]]) {
-        [radioButtons setState:1 atRow: 3 column: 0];
-        [mouseDirSelect setSelectedSegment: [(TargetMouseMove *)target dir]];
-       }
-    else if ([target isKindOfClass: [TargetMouseBtn class]]) {
-        [radioButtons setState: 1 atRow: 4 column: 0];
-        if ([(TargetMouseBtn *)target which] == kCGMouseButtonLeft)
-            [mouseBtnSelect setSelectedSegment: 0];
-        else
-            [mouseBtnSelect setSelectedSegment: 1];
+}
+
+- (void)commit {
+    [self cleanUpInterface];
+    configsController.currentConfig[joystickController.selectedAction] = [self makeTarget];
+    [configsController save];
+}
+
+- (BOOL)enabled {
+    return [radioButtons isEnabled];
+}
+
+- (void)setEnabled:(BOOL)enabled {
+    [radioButtons setEnabled:enabled];
+    [keyInput setEnabled:enabled];
+    [configPopup setEnabled:enabled];
+    [mouseDirSelect setEnabled:enabled];
+    [mouseBtnSelect setEnabled:enabled];
+    [scrollDirSelect setEnabled:enabled];
+}
+
+- (void)loadTarget:(Target *)target forAction:(JSAction *)action {
+    if (!action) {
+        self.enabled = NO;
+        title.stringValue = @"";
+    } else {
+        self.enabled = YES;
+        NSString *actFullName = action.name;
+        for (JSAction *cur = action.base; cur; cur = cur.base) {
+            actFullName = [[NSString alloc] initWithFormat:@"%@ > %@", cur.name, actFullName];
+        }
+        title.stringValue = [[NSString alloc] initWithFormat:@"%@ > %@", configsController.currentConfig.name, actFullName];
+    }
+
+    if ([target isKindOfClass:[TargetKeyboard class]]) {
+        [radioButtons selectCellAtRow:1 column:0];
+        keyInput.vk = [(TargetKeyboard*)target vk];
+    } else if ([target isKindOfClass:[TargetConfig class]]) {
+        [radioButtons selectCellAtRow:2 column:0];
+        NSUInteger idx = [configsController.configs
+                          indexOfObject:[(TargetConfig *)target config]];
+        if (idx == NSNotFound) {
+            [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
+            [configPopup selectItemAtIndex:-1];
+        } else
+            [configPopup selectItemAtIndex:idx];
+    }
+    else if ([target isKindOfClass:[TargetMouseMove class]]) {
+        [radioButtons selectCellAtRow:3 column:0];
+        [mouseDirSelect setSelectedSegment:[(TargetMouseMove *)target axis]];
     }
-    else if ([target isKindOfClass: [TargetMouseScroll class]]) {
-        [radioButtons setState: 1 atRow: 5 column: 0];
-        if ([(TargetMouseScroll *)target howMuch] < 0)
-            [scrollDirSelect setSelectedSegment: 0];
-        else
-            [scrollDirSelect setSelectedSegment: 1];
+    else if ([target isKindOfClass:[TargetMouseBtn class]]) {
+        [radioButtons selectCellAtRow:4 column:0];
+        mouseBtnSelect.selectedSegment = [(TargetMouseBtn *)target button] == kCGMouseButtonLeft ? 0 : 1;
     }
-    else if ([target isKindOfClass: [TargetToggleMouseScope class]]) {
-        [radioButtons setState: 1 atRow: 6 column: 0];
+    else if ([target isKindOfClass:[TargetMouseScroll class]]) {
+        [radioButtons selectCellAtRow:5 column:0];
+        scrollDirSelect.selectedSegment = [(TargetMouseScroll *)target amount] > 0;
+    }
+    else if ([target isKindOfClass:[TargetToggleMouseScope class]]) {
+        [radioButtons selectCellAtRow:6 column:0];
     } else {
-               [NSException raise:@"Unknown target subclass" format:@"Unknown target subclass"];
-       }
+        [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
+    }
+    [self cleanUpInterface];
 }
 
--(void) focusKey {
-       [[[NSApplication sharedApplication] mainWindow] makeFirstResponder: keyInput];
+- (void)loadCurrent {
+    [self loadTarget:[self currentTarget] forAction:joystickController.selectedAction];
 }
 
--(void) refreshConfigsPreservingSelection: (BOOL) preserve  {
-       int initialIndex = [configPopup indexOfSelectedItem];
-       
-       NSArray* configs = [configsController configs];
-       [configPopup removeAllItems];
-       for(int i=0; i<[configs count]; i++) {
-               [configPopup addItemWithTitle: [configs[i]name]];
-       }
-       if(preserve)
-               [configPopup selectItemAtIndex:initialIndex];
-               
+- (void)focusKey {
+    if (radioButtons.selectedRow <= 1)
+        [keyInput.window makeFirstResponder:keyInput];
+    else
+        [keyInput resignIfFirstResponder];
+}
+
+- (void)refreshConfigs {
+    // TODO: This doesn't work when removing configs.
+    NSInteger initialIndex = configPopup.indexOfSelectedItem;
+    [configPopup.menu removeAllItems];
+    for (Config *config in configsController.configs) {
+        NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:config.name
+                                                      action:@selector(configChosen:)
+                                               keyEquivalent:@""];
+        item.target = self;
+        [configPopup.menu addItem:item];
+    }
+    [configPopup selectItemAtIndex:initialIndex];
 }
 
 @end