Replace hacky target stringification with structured serialization.
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Thu, 28 Feb 2013 13:44:41 +0000 (14:44 +0100)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Thu, 28 Feb 2013 13:44:41 +0000 (14:44 +0100)
18 files changed:
ConfigsController.m
KeyInputTextView.h
KeyInputTextView.m
Target.h
Target.m
TargetConfig.h
TargetConfig.m
TargetController.m
TargetKeyboard.h
TargetKeyboard.m
TargetMouseBtn.h
TargetMouseBtn.m
TargetMouseMove.h
TargetMouseMove.m
TargetMouseScroll.h
TargetMouseScroll.m
TargetToggleMouseScope.h
TargetToggleMouseScope.m

index 7db30bf..67033d3 100644 (file)
        return [configs[index] name];
 }
 
-- (void)tableView:(NSTableView *)view setObjectValue:obj forTableColumn:(NSTableColumn *)col row:(int)index {
-       /* ugly hack so stringification doesn't fail */
-       NSString* newName = [(NSString*)obj stringByReplacingOccurrencesOfString: @"~" withString: @""];
-       [(Config *)configs[index] setName:newName];
+- (void)tableView:(NSTableView *)view setObjectValue:(NSString *)obj forTableColumn:(NSTableColumn *)col row:(int)index {
+       [(Config *)configs[index] setName:obj];
        [targetController refreshConfigsPreservingSelection:YES];
        [tableView reloadData];
        [(ApplicationController *)[[NSApplication sharedApplication] delegate] configsChanged];
                cfgInfo[@"name"] = [config name];
                NSMutableDictionary* cfgEntries = [[NSMutableDictionary alloc] init];
                for(id key in [config entries]) {
-                       cfgEntries[key] = [[config entries][key]stringify];
+                       cfgEntries[key] = [[config entries][key] serialize];
                }
                cfgInfo[@"entries"] = cfgEntries;
                [ary addObject: cfgInfo];
        for(int i=0; i<[ary count]; i++) {
                NSDictionary* dict = ary[i][@"entries"];
                for(id key in dict) {
-                       [newConfigs[i] entries][key] = [Target unstringify: dict[key] withConfigList: newConfigs];
+                       [newConfigs[i] entries][key] = [Target targetDeserialize:dict[key] withConfigs:newConfigs];
                }
        }
        
index 0551509..a3cd4ff 100644 (file)
@@ -18,6 +18,8 @@
 @property (readonly) BOOL hasKey;
 @property (assign) BOOL enabled;
 
++ (NSString *)stringForKeyCode:(int)keycode;
+
 - (void)clear;
 
 @end
index cde2547..7bda696 100644 (file)
@@ -33,7 +33,7 @@
     return self.vk >= 0;
 }
 
-- (NSString *)stringForKeyCode:(int)keycode {
++ (NSString *)stringForKeyCode:(int)keycode {
     switch(keycode) {
         case   -1: return @"";
         case 0x7a: return @"F1";
 
 - (void)setVk:(int)key {
     vk = key;
-    descr = [self stringForKeyCode:key];
+    descr = [KeyInputTextView stringForKeyCode:key];
     [self setStringValue:descr];
     if (self.hasKey)
         [targetController keyChanged];
index e1d1ff7..93b181f 100644 (file)
--- a/Target.h
+++ b/Target.h
 - (void)trigger;
 - (void)untrigger;
 - (BOOL)update:(JoystickController *)jc;
-- (NSString*) stringify;
-+ (Target *)unstringify:(NSString*)str withConfigList:(NSArray*)configs;
+
+- (NSDictionary *)serialize;
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs;
++ (NSString *)serializationCode;
 
 @end
index 6b208e8..35af184 100644 (file)
--- a/Target.m
+++ b/Target.m
 
 @synthesize magnitude;
 
-// TODO: Should just be NSCoding? Or like a dictionary?
-+(Target*) unstringify: (NSString*) str withConfigList: (NSArray*) configs {
-    NSArray* components = [str componentsSeparatedByString:@"~"];
-    NSParameterAssert([components count]);
-    NSString* typeTag = components[0];
-    if([typeTag isEqualToString:@"key"])
-        return [TargetKeyboard unstringifyImpl:components];
-    if([typeTag isEqualToString:@"cfg"])
-        return [TargetConfig unstringifyImpl:components withConfigList:configs];
-    if([typeTag isEqualToString:@"mmove"])
-        return [TargetMouseMove unstringifyImpl:components];
-    if([typeTag isEqualToString:@"mbtn"])
-        return [TargetMouseBtn unstringifyImpl:components];
-    if([typeTag isEqualToString:@"mscroll"])
-        return [TargetMouseScroll unstringifyImpl:components];
-    if([typeTag isEqualToString:@"mtoggle"])
-        return [TargetToggleMouseScope unstringifyImpl:components];
-    
-    NSParameterAssert(NO);
-    return NULL;
++ (NSString *)serializationCode {
+    [self doesNotRecognizeSelector:_cmd];
+    return nil;
 }
 
-- (NSString *)stringify {
+- (NSDictionary *)serialize {
     [self doesNotRecognizeSelector:_cmd];
-    return NULL;
+    return nil;    
+}
+
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs {
+    // Don't crash loading old configs (but don't load them either).
+    if (![serialization isKindOfClass:[NSDictionary class]])
+        return nil;
+    NSString *type = serialization[@"type"];
+    for (Class cls in @[[TargetKeyboard class],
+                        [TargetConfig class],
+                        [TargetMouseMove class],
+                        [TargetMouseBtn class],
+                        [TargetMouseScroll class],
+                        [TargetToggleMouseScope class]
+         ]) {
+        if ([type isEqualToString:[cls serializationCode]])
+            return [cls targetDeserialize:serialization withConfigs:configs];
+    }
+    
+    return nil;
 }
 
 - (void)trigger {
index 0df0835..3f453ff 100644 (file)
@@ -13,6 +13,5 @@
 @interface TargetConfig : Target
 
 @property (weak) Config *config;
-+ (TargetConfig *)unstringifyImpl:(NSArray *)comps withConfigList:(NSArray *)configs;
 
 @end
index 763bbac..1fef7a9 100644 (file)
 
 @implementation TargetConfig
 
-- (NSString *)stringify {
-    return [[NSString alloc] initWithFormat: @"cfg~%@", self.config.name];
++ (NSString *)serializationCode {
+    return @"cfg";
 }
 
-+ (TargetConfig *)unstringifyImpl:(NSArray *)comps withConfigList:(NSArray *)configs {
-    NSString *name = comps[1];
+- (NSDictionary *)serialize {
+    return self.config
+        ? @{ @"type": @"cfg", @"name": self.config.name }
+        : @{};
+}
+
++ (TargetConfig *)targetDeserialize:(NSDictionary *)serialization
+                        withConfigs:(NSArray *)configs {
+    NSString *name = serialization[@"name"];
     TargetConfig *target = [[TargetConfig alloc] init];
     for (Config *config in configs) {
         if ([config.name isEqualToString:name]) {
@@ -26,7 +33,6 @@
             return target;
         }
     }
-    NSLog(@"Warning: couldn't find matching config to restore from: %@", name);
     return nil;
 }
 
index 3fc0f28..8afaaf2 100644 (file)
@@ -55,7 +55,6 @@
                        if(keyInput.hasKey) {
                                TargetKeyboard* k = [[TargetKeyboard alloc] init];
                                [k setVk: [keyInput vk]];
-                               [k setDescr: [keyInput descr]];
                                return k;
                        }
                        break;
index 6ff088b..6599332 100644 (file)
@@ -8,14 +8,9 @@
 
 #import "Target.h"
 
-@interface TargetKeyboard : Target {
-       CGKeyCode vk;
-       NSString* descr;
-}
+@interface TargetKeyboard : Target
 
-@property (readwrite) CGKeyCode vk;
-@property (readwrite, copy) NSString* descr;
-
-+(TargetKeyboard*) unstringifyImpl: (NSArray*) comps;
+@property (assign) CGKeyCode vk;
+@property (readonly) NSString* descr;
 
 @end
index e7bd8e7..d19c65f 100644 (file)
@@ -7,19 +7,24 @@
 
 #import "TargetKeyboard.h"
 
+#import "KeyInputTextView.h"
+
 @implementation TargetKeyboard
 
-@synthesize vk, descr;
+@synthesize vk;
+
++ (NSString *)serializationCode {
+    return @"key";
+}
 
--(NSString*) stringify {
-       return [[NSString alloc] initWithFormat: @"key~%d~%@", vk, descr];
+- (NSDictionary *)serialize {
+    return @{ @"type": @"key", @"key": @(self.vk) };
 }
 
-+(TargetKeyboard*) unstringifyImpl: (NSArray*) comps {
-       NSParameterAssert([comps count] == 3);
-       TargetKeyboard* target = [[TargetKeyboard alloc] init];
-       [target setVk: [comps[1] integerValue]];
-       [target setDescr: comps[2]];
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs {
+       TargetKeyboard *target = [[TargetKeyboard alloc] init];
+    target.vk = [serialization[@"key"] intValue];
        return target;
 }
 
@@ -35,4 +40,8 @@
        CFRelease(keyUp);
 }
 
+- (NSString *)descr {
+    return [KeyInputTextView stringForKeyCode:self.vk];
+}
+
 @end
index 29153d8..a0b8516 100644 (file)
@@ -8,12 +8,8 @@
 
 #import "Target.h"
 
-@interface TargetMouseBtn : Target {
-    CGMouseButton which;
-}
+@interface TargetMouseBtn : Target
 
-@property(readwrite) CGMouseButton which;
-
-+(TargetMouseBtn*) unstringifyImpl: (NSArray*) comps;
+@property (assign) CGMouseButton which;
 
 @end
index e8d77e4..28fe536 100644 (file)
 
 @synthesize which;
 
--(NSString*) stringify {
-       return [[NSString alloc] initWithFormat: @"mbtn~%u", which];
++ (NSString *)serializationCode {
+    return @"mbtn";
 }
 
-+(TargetMouseBtn*) unstringifyImpl: (NSArray*) comps {
-       NSParameterAssert([comps count] == 2);
-       TargetMouseBtn* target = [[TargetMouseBtn alloc] init];
-       [target setWhich: [comps[1] integerValue]];
+- (NSDictionary *)serialize {
+    return @{ @"type": @"mbtn", @"which": @(self.which) };
+}
+
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs {
+       TargetMouseBtn *target = [[TargetMouseBtn alloc] init];
+    target.which = [serialization[@"which"] intValue];
        return target;
 }
 
index f486a96..24efa40 100644 (file)
@@ -8,12 +8,8 @@
 
 #import "Target.h"
 
-@interface TargetMouseMove : Target {
-    int dir;
-}
+@interface TargetMouseMove : Target
 
-@property(readwrite) int dir;
-
-+(TargetMouseMove*) unstringifyImpl: (NSArray*) comps;
+@property (assign) int dir;
 
 @end
index 5f83dbf..8eeae88 100644 (file)
 
 @synthesize dir;
 
--(NSString*) stringify {
-       return [[NSString alloc] initWithFormat: @"mmove~%d", dir];
++ (NSString *)serializationCode {
+    return @"mmove";
 }
 
-+(TargetMouseMove*) unstringifyImpl: (NSArray*) comps {
-       NSParameterAssert([comps count] == 2);
-       TargetMouseMove* target = [[TargetMouseMove alloc] init];
-       [target setDir: [comps[1] integerValue]];
+- (NSDictionary *)serialize {
+    return @{ @"type": @"mmove", @"dir": @(self.dir) };
+}
+
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs {
+       TargetMouseMove *target = [[TargetMouseMove alloc] init];
+    target.dir = [serialization[@"dir"] intValue];
        return target;
 }
 
index a53a02e..cdfe010 100644 (file)
@@ -8,12 +8,8 @@
 
 #import "Target.h"
 
-@interface TargetMouseScroll : Target {
-    int howMuch;
-}
+@interface TargetMouseScroll : Target
 
-@property(readwrite) int howMuch;
-
-+(TargetMouseScroll*) unstringifyImpl: (NSArray*) comps;
+@property (assign) int howMuch;
 
 @end
index 79bc542..3c417c1 100644 (file)
 
 @synthesize howMuch;
 
--(NSString*) stringify {
-       return [[NSString alloc] initWithFormat: @"mscroll~%d", howMuch];
++ (NSString *)serializationCode {
+    return @"mscroll";
 }
 
-+(TargetMouseScroll*) unstringifyImpl: (NSArray*) comps {
-       NSParameterAssert([comps count] == 2);
-       TargetMouseScroll* target = [[TargetMouseScroll alloc] init];
-       [target setHowMuch: [comps[1] integerValue]];
-       return target;
+- (NSDictionary *)serialize {
+    return @{ @"type": @"mscroll", @"howMuch": @(self.howMuch) };
 }
 
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs {
+       TargetMouseScroll *target = [[TargetMouseScroll alloc] init];
+    target.howMuch = [serialization[@"howMuch"] intValue];
+       return target;
+}
 -(void) trigger {
     CGEventRef scroll = CGEventCreateScrollWheelEvent(NULL,
                                                       kCGScrollEventUnitLine,
                                                       1,
-                                                      [self howMuch]);
+                                                      self.howMuch);
     CGEventPost(kCGHIDEventTap, scroll);
     CFRelease(scroll);
 }
index f167b5e..45c79ba 100644 (file)
@@ -10,6 +10,4 @@
 
 @interface TargetToggleMouseScope : Target
 
-+(TargetToggleMouseScope*) unstringifyImpl: (NSArray*) comps;
-
 @end
index d6833fc..4f1d157 100644 (file)
 
 @implementation TargetToggleMouseScope
 
--(NSString*) stringify {
-       return [[NSString alloc] initWithFormat: @"mtoggle"];
++ (NSString *)serializationCode {
+    return @"mtoggle";
 }
 
-+(TargetToggleMouseScope*) unstringifyImpl: (NSArray*) comps {
-       NSParameterAssert([comps count] == 1);
-       TargetToggleMouseScope* target = [[TargetToggleMouseScope alloc] init];
-       return target;
+- (NSDictionary *)serialize {
+    return @{ @"type": @"mtoggle" };
 }
 
++ (Target *)targetDeserialize:(NSDictionary *)serialization
+                  withConfigs:(NSArray *)configs {
+       TargetToggleMouseScope *target = [[TargetToggleMouseScope alloc] init];
+       return target;
+}
 - (void)trigger {
     // FIXME: It's hacky to get at the controller this way, but it's
     // also hacky to pass it. Shouldn't need to do either.