760b41bac53546659cd28f346ef07b318e94cde0
[enjoyable.git] / Classes / NJMappingsController.m
1 //
2 // NJMappingsController.m
3 // Enjoy
4 //
5 // Created by Sam McCall on 4/05/09.
6 //
7
8 #import "NJMappingsController.h"
9
10 #import "NJMapping.h"
11 #import "NJOutput.h"
12 #import "NJEvents.h"
13
14 @implementation NJMappingsController {
15 NSMutableArray *_mappings;
16 NJMapping *_manualMapping;
17 }
18
19 - (id)init {
20 if ((self = [super init])) {
21 _mappings = [[NSMutableArray alloc] init];
22 _currentMapping = [[NJMapping alloc] initWithName:
23 NSLocalizedString(@"(default)", @"default name for first the mapping")];
24 _manualMapping = _currentMapping;
25 [_mappings addObject:_currentMapping];
26 }
27 return self;
28 }
29
30 - (NJMapping *)objectForKeyedSubscript:(NSString *)name {
31 for (NJMapping *mapping in _mappings)
32 if ([name isEqualToString:mapping.name])
33 return mapping;
34 return nil;
35 }
36
37 - (NJMapping *)objectAtIndexedSubscript:(NSUInteger)idx {
38 return idx < _mappings.count ? _mappings[idx] : nil;
39 }
40
41 - (void)mappingsSet {
42 [self postLoadProcess];
43 [NSNotificationCenter.defaultCenter
44 postNotificationName:NJEventMappingListChanged
45 object:self
46 userInfo:@{ NJMappingListKey: _mappings,
47 NJMappingKey: _currentMapping }];
48 }
49
50 - (void)mappingsChanged {
51 [self save];
52 [self mappingsSet];
53 }
54
55 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
56 objects:(__unsafe_unretained id [])buffer
57 count:(NSUInteger)len {
58 return [_mappings countByEnumeratingWithState:state
59 objects:buffer
60 count:len];
61 }
62
63 - (void)activateMappingForProcess:(NSRunningApplication *)app {
64 NJMapping *oldMapping = _manualMapping;
65 NSArray *names = app.possibleMappingNames;
66 BOOL found = NO;
67 for (NSString *name in names) {
68 NJMapping *mapping = self[name];
69 if (mapping) {
70 [self activateMapping:mapping];
71 found = YES;
72 break;
73 }
74 }
75
76 if (!found) {
77 [self activateMapping:oldMapping];
78 if ([oldMapping.name.lowercaseString isEqualToString:@"@application"]
79 || [oldMapping.name.lowercaseString isEqualToString:
80 NSLocalizedString(@"@Application", nil).lowercaseString]) {
81 oldMapping.name = app.bestMappingName;
82 [self mappingsChanged];
83 }
84 }
85 _manualMapping = oldMapping;
86 }
87
88 - (void)activateMapping:(NJMapping *)mapping {
89 if (!mapping)
90 mapping = _manualMapping;
91 if (mapping == _currentMapping)
92 return;
93 NSLog(@"Switching to mapping %@.", mapping.name);
94 _manualMapping = mapping;
95 _currentMapping = mapping;
96 NSUInteger idx = [self indexOfMapping:_currentMapping];
97 [NSNotificationCenter.defaultCenter
98 postNotificationName:NJEventMappingChanged
99 object:self
100 userInfo:@{ NJMappingKey : _currentMapping,
101 NJMappingIndexKey: @(idx) }];
102 }
103
104 - (void)save {
105 NSLog(@"Saving mappings to defaults.");
106 NSMutableArray *ary = [[NSMutableArray alloc] initWithCapacity:_mappings.count];
107 for (NJMapping *mapping in _mappings)
108 [ary addObject:[mapping serialize]];
109 [NSUserDefaults.standardUserDefaults setObject:ary forKey:@"mappings"];
110 }
111
112 - (void)postLoadProcess {
113 for (NJMapping *mapping in self)
114 [mapping postLoadProcess:self];
115 }
116
117 - (void)load {
118 NSUInteger selected = [NSUserDefaults.standardUserDefaults integerForKey:@"selected"];
119 NSArray *storedMappings = [NSUserDefaults.standardUserDefaults arrayForKey:@"mappings"];
120 NSMutableArray* newMappings = [[NSMutableArray alloc] initWithCapacity:storedMappings.count];
121
122 for (NSDictionary *serialization in storedMappings)
123 [newMappings addObject:
124 [[NJMapping alloc] initWithSerialization:serialization]];
125
126 if (newMappings.count) {
127 _mappings = newMappings;
128 if (selected >= newMappings.count)
129 selected = 0;
130 [self activateMapping:_mappings[selected]];
131 [self mappingsSet];
132 }
133 }
134
135 - (NSInteger)indexOfMapping:(NJMapping *)mapping {
136 return [_mappings indexOfObjectIdenticalTo:mapping];
137 }
138
139 - (void)mergeMapping:(NJMapping *)mapping intoMapping:(NJMapping *)existing {
140 [existing mergeEntriesFrom:mapping];
141 [self mappingsChanged];
142 if (existing == _currentMapping) {
143 // FIXME: Hack to trigger updates in the rest of the UI.
144 _currentMapping = nil;
145 NJMapping *manual = _manualMapping;
146 [self activateMapping:existing];
147 _manualMapping = manual;
148 }
149 }
150
151 - (void)renameMapping:(NJMapping *)mapping to:(NSString *)name {
152 mapping.name = name;
153 [self mappingsChanged];
154 if (mapping == _currentMapping) {
155 // FIXME: Hack to trigger updates in the rest of the UI.
156 _currentMapping = nil;
157 NJMapping *manual = _manualMapping;
158 [self activateMapping:mapping];
159 _manualMapping = manual;
160 }
161 }
162
163 - (void)addMapping:(NJMapping *)mapping {
164 [self insertMapping:mapping atIndex:_mappings.count];
165 }
166
167 - (void)insertMapping:(NJMapping *)mapping atIndex:(NSInteger)idx {
168 [_mappings insertObject:mapping atIndex:idx];
169 [self mappingsChanged];
170 }
171
172 - (void)removeMappingAtIndex:(NSInteger)idx {
173 NSInteger currentIdx = [self indexOfMapping:_currentMapping];
174 [_mappings removeObjectAtIndex:idx];
175 [self activateMapping:self[MIN(currentIdx, _mappings.count - 1)]];
176 [self mappingsChanged];
177 }
178
179 - (void)moveMoveMappingFromIndex:(NSInteger)fromIdx toIndex:(NSInteger)toIdx {
180 [_mappings moveObjectAtIndex:fromIdx toIndex:toIdx];
181 [self mappingsChanged];
182 }
183
184 - (NSUInteger)count {
185 return _mappings.count;
186 }
187
188 @end