Show a special message when the HID was closed during deactivation.
[enjoyable.git] / Classes / NJDeviceController.m
index 2849838..2a1546c 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:)
     }
 }
 
+- (id)elementForUID:(NSString *)uid {
+    for (NJDevice *dev in _devices) {
+        id item = [dev elementForUID:uid];
+        if (item)
+            return item;
+    }
+    return nil;
+}
+
+- (void)expandRecursiveByUID:(NSString *)uid {
+    [self expandRecursive:[self elementForUID:uid]];
+}
+
 - (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 +162,8 @@ static int findAvailableIndex(NSArray *list, NJDevice *dev) {
     dev.index = findAvailableIndex(_devices, dev);
     [_devices addObject:dev];
     [outlineView reloadData];
+    [self reexpandAll];
+    hidSleepingPrompt.hidden = YES;
     connectDevicePrompt.hidden = !!_devices.count;
 }
 
@@ -166,6 +191,7 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD
         [_devices removeObject:match];
         [outlineView reloadData];
         connectDevicePrompt.hidden = !!_devices.count;
+        hidSleepingPrompt.hidden = YES;
     }
     if (_devices.count == 1)
         [outlineView expandItem:_devices[0]];
@@ -202,13 +228,13 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD
     IOHIDManagerSetDeviceMatchingMultiple(_hidManager, (__bridge CFArrayRef)criteria);
     IOReturn ret = IOHIDManagerOpen(_hidManager, kIOHIDOptionsTypeNone);
     if (ret != kIOReturnSuccess) {
-        [[NSAlert alertWithMessageText:@"Input devices are unavailable"
+        [[NSAlert alertWithMessageText:NSLocalizedString(@"input devices unavailable",
+                                                         @"error title when devices can't be read")
                          defaultButton:nil
                        alternateButton:nil
                            otherButton:nil
-             informativeTextWithFormat:@"Error 0x%08x occured trying to access your devices. "
-                                       @"Input may not be correctly detected or mapped.",
-                                       ret]
+             informativeTextWithFormat:NSLocalizedString(@"input error 0x%08x occurred",
+                                                         @"message containing IOReturn failure code when devices can't be read"), ret]
             beginSheetModalForWindow:outlineView.window
             modalDelegate:nil
             didEndSelector:nil
@@ -217,6 +243,8 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD
     } else {
         IOHIDManagerRegisterDeviceMatchingCallback(_hidManager, add_callback, (__bridge void *)self);
         IOHIDManagerRegisterDeviceRemovalCallback(_hidManager, remove_callback, (__bridge void *)self);
+        hidSleepingPrompt.hidden = YES;
+        connectDevicePrompt.hidden = !!_devices.count;
     }
 }
 
@@ -230,7 +258,8 @@ static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDD
     }
     [_devices removeAllObjects];
     [outlineView reloadData];
-    connectDevicePrompt.hidden = !!_devices.count;
+    hidSleepingPrompt.hidden = NO;
+    connectDevicePrompt.hidden = YES;
 }
 
 - (NJInput *)selectedInput {
@@ -261,6 +290,10 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
 }
 
 - (void)outlineViewSelectionDidChange:(NSNotification *)notification {
+    id <NJInputPathElement> item = [outlineView itemAtRow:outlineView.selectedRow];
+    if (item)
+        [NSUserDefaults.standardUserDefaults setObject:item.uid
+                                                forKey:@"selected input"];
     [outputController loadCurrent];
 }
 
@@ -274,6 +307,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 +343,18 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
     }
 }
 
+- (void)reexpandAll {
+    for (NSString *uid in [_expanded copy])
+        [self expandRecursiveByUID:uid];
+    if (outlineView.selectedRow == -1) {
+        NSString *selectedUid = [NSUserDefaults.standardUserDefaults objectForKey:@"selected input"];
+        id item = [self elementForUID:selectedUid];
+        NSInteger row = [outlineView rowForItem:item];
+        if (row >= 0)
+            [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
+    }
+}
+
 - (void)closeHidIfDisabled:(NSNotification *)application {
     if (!self.translatingEvents)
         [self closeHid];