Remember expanded rows between activations / device insertion.
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Tue, 12 Mar 2013 16:32:07 +0000 (17:32 +0100)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Tue, 12 Mar 2013 16:32:07 +0000 (17:32 +0100)
Classes/NJDevice.m
Classes/NJDeviceController.m
Classes/NJInput.m
Classes/NJInputPathElement.h
Info.plist

index 69775d8..e2a0efa 100644 (file)
@@ -106,4 +106,28 @@ static NSArray *InputsForElement(IOHIDDeviceRef device, id base) {
     return [self findInputByCookie:cookie];
 }
 
+- (BOOL)isEqual:(id)object {
+    return [object isKindOfClass:NJDevice.class]
+        && [[object uid] isEqualToString:self.uid];
+}
+
+- (NSUInteger)hash {
+    return self.uid.hash;
+}
+
+- (id <NJInputPathElement>)elementForUID:(NSString *)uid {
+    if ([uid isEqualToString:self.uid])
+        return self;
+    else if (![uid hasPrefix:self.uid])
+        return nil;
+    else {
+        for (id <NJInputPathElement> elem in self.children) {
+            id <NJInputPathElement> ret = [elem elementForUID:uid];
+            if (ret)
+                return ret;
+        }
+    }
+    return nil;
+}
+
 @end
index 2ce3fa9..a1e5868 100644 (file)
     NSTimer *_continuousOutputsTick;
     NSMutableArray *_continousOutputs;
     NSMutableArray *_devices;
+    NSMutableArray *_expanded;
 }
 
+#define EXPANDED_MEMORY_MAX_SIZE 100
+
 - (id)init {
     if ((self = [super init])) {
         _devices = [[NSMutableArray alloc] initWithCapacity:16];
         _continousOutputs = [[NSMutableArray alloc] initWithCapacity:32];
+        
+        NSArray *expanded = [NSUserDefaults.standardUserDefaults objectForKey:@"expanded rows"];
+        if (![expanded isKindOfClass:NSArray.class])
+            expanded = @[];
+        _expanded = [[NSMutableArray alloc] initWithCapacity:MAX(16, _expanded.count)];
+        [_expanded addObjectsFromArray:expanded];
+
         [NSNotificationCenter.defaultCenter
              addObserver:self
              selector:@selector(applicationDidFinishLaunching:)
     }
 }
 
+- (void)expandRecursiveByUID:(NSString *)uid {
+    for (NJDevice *dev in _devices) {
+        id item = [dev elementForUID:uid];
+        if (item)
+            [self expandRecursive:item];
+    }
+}
+
 - (void)addRunningOutput:(NJOutput *)output {
     // Axis events will trigger every small movement, don't keep
     // re-adding them or they trigger multiple times each time.
@@ -139,6 +157,7 @@ static int findAvailableIndex(NSArray *list, NJDevice *dev) {
     dev.index = findAvailableIndex(_devices, dev);
     [_devices addObject:dev];
     [outlineView reloadData];
+    [self reexpandAll];
     connectDevicePrompt.hidden = !!_devices.count;
 }
 
@@ -274,6 +293,24 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
     return ![self outlineView:outlineView_ isGroupItem:item];
 }
 
+- (void)outlineViewItemDidExpand:(NSNotification *)notification {
+    id <NJInputPathElement> item = notification.userInfo[@"NSObject"];
+    NSString *uid = item.uid;
+    if (![_expanded containsObject:uid])
+        [_expanded addObject:uid];
+    while (_expanded.count > EXPANDED_MEMORY_MAX_SIZE)
+        [_expanded removeObjectAtIndex:0];
+    [NSUserDefaults.standardUserDefaults setObject:_expanded
+                                            forKey:@"expanded rows"];
+}
+
+- (void)outlineViewItemDidCollapse:(NSNotification *)notification {
+    id <NJInputPathElement> item = notification.userInfo[@"NSObject"];
+    [_expanded removeObject:item.uid];
+    [NSUserDefaults.standardUserDefaults setObject:_expanded
+                                            forKey:@"expanded rows"];
+}
+
 - (void)setTranslatingEvents:(BOOL)translatingEvents {
     if (translatingEvents != _translatingEvents) {
         _translatingEvents = translatingEvents;
@@ -292,6 +329,11 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
     }
 }
 
+- (void)reexpandAll {
+    for (NSString *uid in [_expanded copy])
+        [self expandRecursiveByUID:uid];
+}
+
 - (void)closeHidIfDisabled:(NSNotification *)application {
     if (!self.translatingEvents)
         [self closeHid];
index a279322..15b4687 100644 (file)
     [self doesNotRecognizeSelector:_cmd];
 }
 
+- (BOOL)isEqual:(id)object {
+    return [object isKindOfClass:NJInput.class]
+        && [[object uid] isEqualToString:self.uid];
+}
+
+- (NSUInteger)hash {
+    return self.uid.hash;
+}
+
+- (id <NJInputPathElement>)elementForUID:(NSString *)uid {
+    if ([uid isEqualToString:self.uid])
+        return self;
+    else {
+        for (id <NJInputPathElement> elem in self.children) {
+            id <NJInputPathElement> ret = [elem elementForUID:uid];
+            if (ret)
+                return ret;
+        }
+    }
+    return nil;
+}
+
 @end
index 8750038..f3f27c2 100644 (file)
@@ -2,9 +2,13 @@
 
 @protocol NJInputPathElement <NSObject>
 
+// TODO: It's time this became a real base class rather than a protocol.
+
 - (NSArray *)children;
 - (id <NJInputPathElement>) base;
 - (NSString *)name;
 - (NSString *)uid;
 
+- (id <NJInputPathElement>)elementForUID:(NSString *)uid;
+
 @end
index c4a9347..9017347 100644 (file)
@@ -46,7 +46,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>187</string>
+       <string>210</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.utilities</string>
        <key>NSHumanReadableCopyright</key>