Fix several cases where the UI did not properly reflect model changes.
[enjoyable.git] / Classes / NJDeviceViewController.m
1 //
2 // NJDeviceViewController.m
3 // Enjoyable
4 //
5 // Created by Joe Wreschnig on 3/16/13.
6 //
7 //
8
9 #import "NJDeviceViewController.h"
10
11 #import "NJInputPathElement.h"
12
13 @implementation NJDeviceViewController {
14 NSMutableArray *_expanded;
15 }
16
17 - (id)init {
18 if ((self = [super init])) {
19 NSArray *expanded = [NSUserDefaults.standardUserDefaults objectForKey:@"expanded rows"];
20 if (![expanded isKindOfClass:NSArray.class])
21 expanded = @[];
22 _expanded = [[NSMutableArray alloc] initWithCapacity:MAX(16, _expanded.count)];
23 [_expanded addObjectsFromArray:expanded];
24 }
25 return self;
26 }
27
28 - (void)expandRecursive:(NJInputPathElement *)pathElement {
29 if (pathElement) {
30 [self expandRecursive:pathElement.parent];
31 [self.inputsTree expandItem:pathElement];
32 }
33 }
34
35 - (void)expandRecursiveByUID:(NSString *)uid {
36 [self expandRecursive:[self.delegate deviceViewController:self elementForUID:uid]];
37 }
38
39 - (void)beginUpdates {
40 [self.inputsTree beginUpdates];
41 }
42
43 - (void)endUpdates {
44 [self.inputsTree endUpdates];
45 }
46
47 - (void)reexpandAll {
48 for (NSString *uid in [_expanded copy])
49 [self expandRecursiveByUID:uid];
50 if (self.inputsTree.selectedRow == -1) {
51 NSString *selectedUid = [NSUserDefaults.standardUserDefaults objectForKey:@"selected input"];
52 id item = [self.delegate deviceViewController:self elementForUID:selectedUid];
53 [self.inputsTree selectItem:item];
54 }
55 }
56
57 - (void)addedDevice:(NJDevice *)device atIndex:(NSUInteger)idx {
58 [self.inputsTree insertItemsAtIndexes:[[NSIndexSet alloc] initWithIndex:idx]
59 inParent:nil
60 withAnimation:NSTableViewAnimationEffectFade];
61 [self reexpandAll];
62 self.noDevicesNotice.hidden = YES;
63 }
64
65 - (void)removedDevice:(NJDevice *)device atIndex:(NSUInteger)idx {
66 BOOL anyDevices = !![self.delegate numberOfDevicesInDeviceList:self];
67 [self.inputsTree removeItemsAtIndexes:[[NSIndexSet alloc] initWithIndex:idx]
68 inParent:nil
69 withAnimation:NSTableViewAnimationEffectFade];
70 self.noDevicesNotice.hidden = anyDevices || !self.hidStoppedNotice.isHidden;
71 }
72
73 - (void)hidStarted {
74 self.noDevicesNotice.hidden = !![self.delegate numberOfDevicesInDeviceList:self];
75 self.hidStoppedNotice.hidden = YES;
76 }
77
78 - (void)hidStopped {
79 self.noDevicesNotice.hidden = YES;
80 self.hidStoppedNotice.hidden = NO;
81 [self.inputsTree reloadData];
82 }
83
84 - (void)expandAndSelectItem:(NJInputPathElement *)item {
85 [self expandRecursive:item];
86 NSInteger row = [self.inputsTree rowForItem:item];
87 if (row >= 0) {
88 [self.inputsTree selectRowIndexes:[[NSIndexSet alloc] initWithIndex:row]
89 byExtendingSelection:NO];
90 [self.inputsTree scrollRowToVisible:row];
91 }
92 }
93
94 - (NSInteger)outlineView:(NSOutlineView *)outlineView
95 numberOfChildrenOfItem:(NJInputPathElement *)item {
96 if (item)
97 return item.children.count;
98 else
99 return [self.delegate numberOfDevicesInDeviceList:self];
100
101 }
102
103 - (BOOL)outlineView:(NSOutlineView *)outlineView
104 isItemExpandable:(NJInputPathElement *)item {
105 return item ? item.children.count > 0: YES;
106 }
107
108 - (id)outlineView:(NSOutlineView *)outlineView
109 child:(NSInteger)index
110 ofItem:(NJInputPathElement *)item {
111 if (item)
112 return item.children[index];
113 else
114 return [self.delegate deviceViewController:self deviceForIndex:index];
115 }
116
117 - (id)outlineView:(NSOutlineView *)outlineView
118 objectValueForTableColumn:(NSTableColumn *)tableColumn
119 byItem:(NJInputPathElement *)item {
120 return item ? item.name : @"root";
121 }
122
123 - (void)outlineViewSelectionDidChange:(NSNotification *)notification {
124 NSOutlineView *outlineView = notification.object;
125 NJInputPathElement *item = outlineView.selectedItem;
126 if (item) {
127 [NSUserDefaults.standardUserDefaults setObject:item.uid
128 forKey:@"selected input"];
129 if (!item.children)
130 [self.delegate deviceViewController:self
131 didSelectHandler:item];
132 else if (!item.parent)
133 [self.delegate deviceViewController:self
134 didSelectDevice:item];
135 else
136 [self.delegate deviceViewController:self
137 didSelectBranch:item];
138 } else {
139 [self.delegate deviceViewControllerDidSelectNothing:self];
140 }
141 }
142
143 - (void)outlineViewItemDidExpand:(NSNotification *)notification {
144 NSString *uid = [notification.userInfo[@"NSObject"] uid];
145 if (![_expanded containsObject:uid]) {
146 [_expanded addObject:uid];
147 [NSUserDefaults.standardUserDefaults setObject:_expanded forKey:@"expanded rows"];
148 }
149 }
150
151 - (void)outlineViewItemDidCollapse:(NSNotification *)notification {
152 [_expanded removeObject:[notification.userInfo[@"NSObject"] uid]];
153 [NSUserDefaults.standardUserDefaults setObject:_expanded forKey:@"expanded rows"];
154 }
155
156 - (BOOL)outlineView:(NSOutlineView *)outlineView
157 isGroupItem:(NJInputPathElement *)item {
158 return !item.parent;
159 }
160
161 - (BOOL)outlineView:(NSOutlineView *)outlineView
162 shouldSelectItem:(NJInputPathElement *)item {
163 return ![self outlineView:outlineView isGroupItem:item];
164 }
165
166 - (NJInputPathElement *)selectedHandler {
167 NJInputPathElement *element = self.inputsTree.selectedItem;
168 return element.children ? nil : element;
169 }
170
171
172
173 @end