1567fee7507534ddced90980e439a0afba122ebf
[enjoyable.git] / Classes / NJOutputController.m
1 //
2 // NJOutputController.m
3 // Enjoy
4 //
5 // Created by Sam McCall on 5/05/09.
6 //
7
8 #import "NJOutputController.h"
9
10 #import "NJMappingsController.h"
11 #import "NJMapping.h"
12 #import "NJInput.h"
13 #import "NJEvents.h"
14 #import "NJDeviceController.h"
15 #import "NJKeyInputField.h"
16 #import "NJOutputMapping.h"
17 #import "NJOutputController.h"
18 #import "NJOutputKeyPress.h"
19 #import "NJOutputMouseButton.h"
20 #import "NJOutputMouseMove.h"
21 #import "NJOutputMouseScroll.h"
22
23 @implementation NJOutputController {
24 NJInput *_input;
25 }
26
27 - (id)init {
28 if ((self = [super init])) {
29 [NSNotificationCenter.defaultCenter
30 addObserver:self
31 selector:@selector(mappingListDidChange:)
32 name:NJEventMappingListChanged
33 object:nil];
34 [NSNotificationCenter.defaultCenter
35 addObserver:self
36 selector:@selector(mappingDidChange:)
37 name:NJEventMappingChanged
38 object:nil];
39 }
40 return self;
41 }
42
43 - (void)dealloc {
44 [NSNotificationCenter.defaultCenter removeObserver:self];
45 }
46
47 - (void)cleanUpInterface {
48 NSInteger row = radioButtons.selectedRow;
49
50 if (row != 1) {
51 keyInput.keyCode = NJKeyInputFieldEmpty;
52 [keyInput resignIfFirstResponder];
53 }
54
55 if (row != 2) {
56 [mappingPopup selectItemAtIndex:-1];
57 [mappingPopup resignIfFirstResponder];
58 unknownMapping.hidden = YES;
59 }
60
61 if (row != 3) {
62 mouseDirSelect.selectedSegment = -1;
63 mouseSpeedSlider.floatValue = mouseSpeedSlider.minValue;
64 [mouseDirSelect resignIfFirstResponder];
65 } else {
66 if (mouseDirSelect.selectedSegment == -1)
67 mouseDirSelect.selectedSegment = 0;
68 if (!mouseSpeedSlider.floatValue)
69 mouseSpeedSlider.floatValue = 10;
70 }
71
72 if (row != 4) {
73 mouseBtnSelect.selectedSegment = -1;
74 [mouseBtnSelect resignIfFirstResponder];
75 } else if (mouseBtnSelect.selectedSegment == -1)
76 mouseBtnSelect.selectedSegment = 0;
77
78 if (row != 5) {
79 scrollDirSelect.selectedSegment = -1;
80 scrollSpeedSlider.floatValue = scrollSpeedSlider.minValue;
81 smoothCheck.state = NSOffState;
82 [scrollDirSelect resignIfFirstResponder];
83 [scrollSpeedSlider resignIfFirstResponder];
84 [smoothCheck resignIfFirstResponder];
85 } else {
86 if (scrollDirSelect.selectedSegment == -1)
87 scrollDirSelect.selectedSegment = 0;
88 }
89
90 }
91
92 - (IBAction)radioChanged:(NSView *)sender {
93 [sender.window makeFirstResponder:sender];
94 if (radioButtons.selectedRow == 1)
95 [keyInput.window makeFirstResponder:keyInput];
96 [self commit];
97 }
98
99 - (void)keyInputField:(NJKeyInputField *)keyInput didChangeKey:(CGKeyCode)keyCode {
100 [radioButtons selectCellAtRow:1 column:0];
101 [radioButtons.window makeFirstResponder:radioButtons];
102 [self commit];
103 }
104
105 - (void)keyInputFieldDidClear:(NJKeyInputField *)keyInput {
106 [radioButtons selectCellAtRow:0 column:0];
107 [self commit];
108 }
109
110 - (void)mappingChosen:(id)sender {
111 [radioButtons selectCellAtRow:2 column:0];
112 [mappingPopup.window makeFirstResponder:mappingPopup];
113 unknownMapping.hidden = YES;
114 [self commit];
115 }
116
117 - (void)mdirChanged:(NSView *)sender {
118 [radioButtons selectCellAtRow:3 column:0];
119 [sender.window makeFirstResponder:sender];
120 [self commit];
121 }
122
123 - (void)mouseSpeedChanged:(NSSlider *)sender {
124 [radioButtons selectCellAtRow:3 column:0];
125 [sender.window makeFirstResponder:sender];
126 [self commit];
127 }
128
129 - (void)mbtnChanged:(NSView *)sender {
130 [radioButtons selectCellAtRow:4 column:0];
131 [sender.window makeFirstResponder:sender];
132 [self commit];
133 }
134
135 - (void)sdirChanged:(NSView *)sender {
136 [radioButtons selectCellAtRow:5 column:0];
137 [sender.window makeFirstResponder:sender];
138 [self commit];
139 }
140
141 - (void)scrollSpeedChanged:(NSSlider *)sender {
142 [radioButtons selectCellAtRow:5 column:0];
143 [sender.window makeFirstResponder:sender];
144 [self commit];
145 }
146
147 - (IBAction)scrollTypeChanged:(NSButton *)sender {
148 [radioButtons selectCellAtRow:5 column:0];
149 [sender.window makeFirstResponder:sender];
150 if (sender.state == NSOnState) {
151 scrollSpeedSlider.floatValue =
152 scrollSpeedSlider.minValue + (scrollSpeedSlider.maxValue - scrollSpeedSlider.minValue) / 2;
153 scrollSpeedSlider.enabled = YES;
154 } else {
155 scrollSpeedSlider.floatValue = scrollSpeedSlider.minValue;
156 scrollSpeedSlider.enabled = NO;
157 }
158 [self commit];
159 }
160
161 - (NJOutput *)currentOutput {
162 return mappingsController.currentMapping[_input];
163 }
164
165 - (NJOutput *)makeOutput {
166 switch (radioButtons.selectedRow) {
167 case 0:
168 return nil;
169 case 1:
170 if (keyInput.hasKeyCode) {
171 NJOutputKeyPress *k = [[NJOutputKeyPress alloc] init];
172 k.keyCode = keyInput.keyCode;
173 return k;
174 } else {
175 return nil;
176 }
177 break;
178 case 2: {
179 NJOutputMapping *c = [[NJOutputMapping alloc] init];
180 c.mapping = mappingsController[mappingPopup.indexOfSelectedItem];
181 return c;
182 }
183 case 3: {
184 NJOutputMouseMove *mm = [[NJOutputMouseMove alloc] init];
185 mm.axis = mouseDirSelect.selectedSegment;
186 mm.speed = mouseSpeedSlider.floatValue;
187 return mm;
188 }
189 case 4: {
190 NJOutputMouseButton *mb = [[NJOutputMouseButton alloc] init];
191 mb.button = [mouseBtnSelect.cell tagForSegment:mouseBtnSelect.selectedSegment];
192 return mb;
193 }
194 case 5: {
195 NJOutputMouseScroll *ms = [[NJOutputMouseScroll alloc] init];
196 ms.direction = [scrollDirSelect.cell tagForSegment:scrollDirSelect.selectedSegment];
197 ms.speed = scrollSpeedSlider.floatValue;
198 ms.smooth = smoothCheck.state == NSOnState;
199 return ms;
200 }
201 default:
202 return nil;
203 }
204 }
205
206 - (void)commit {
207 [self cleanUpInterface];
208 mappingsController.currentMapping[_input] = [self makeOutput];
209 [mappingsController save];
210 }
211
212 - (BOOL)enabled {
213 return radioButtons.isEnabled;
214 }
215
216 - (void)setEnabled:(BOOL)enabled {
217 radioButtons.enabled = enabled;
218 keyInput.enabled = enabled;
219 mappingPopup.enabled = enabled;
220 mouseDirSelect.enabled = enabled;
221 mouseSpeedSlider.enabled = enabled;
222 mouseBtnSelect.enabled = enabled;
223 scrollDirSelect.enabled = enabled;
224 smoothCheck.enabled = enabled;
225 scrollSpeedSlider.enabled = enabled && smoothCheck.state;
226 if (!enabled)
227 unknownMapping.hidden = YES;
228 }
229
230 - (void)loadOutput:(NJOutput *)output forInput:(NJInput *)input {
231 if (!input) {
232 self.enabled = NO;
233 title.stringValue = @"";
234 } else {
235 self.enabled = YES;
236 NSString *inpFullName = input.name;
237 for (NJInputPathElement *cur = input.parent; cur; cur = cur.parent) {
238 inpFullName = [[NSString alloc] initWithFormat:@"%@ ▸ %@", cur.name, inpFullName];
239 }
240 title.stringValue = inpFullName;
241 }
242
243 if ([output isKindOfClass:NJOutputKeyPress.class]) {
244 [radioButtons selectCellAtRow:1 column:0];
245 keyInput.keyCode = [(NJOutputKeyPress*)output keyCode];
246 } else if ([output isKindOfClass:NJOutputMapping.class]) {
247 [radioButtons selectCellAtRow:2 column:0];
248 NSMenuItem *item = [mappingPopup itemWithIdenticalRepresentedObject:[(NJOutputMapping *)output mapping]];
249 [mappingPopup selectItem:item];
250 unknownMapping.hidden = !!item;
251 unknownMapping.title = [(NJOutputMapping *)output mappingName];
252 }
253 else if ([output isKindOfClass:NJOutputMouseMove.class]) {
254 [radioButtons selectCellAtRow:3 column:0];
255 mouseDirSelect.selectedSegment = [(NJOutputMouseMove *)output axis];
256 mouseSpeedSlider.floatValue = [(NJOutputMouseMove *)output speed];
257 }
258 else if ([output isKindOfClass:NJOutputMouseButton.class]) {
259 [radioButtons selectCellAtRow:4 column:0];
260 [mouseBtnSelect selectSegmentWithTag:[(NJOutputMouseButton *)output button]];
261 }
262 else if ([output isKindOfClass:NJOutputMouseScroll.class]) {
263 [radioButtons selectCellAtRow:5 column:0];
264 int direction = [(NJOutputMouseScroll *)output direction];
265 float speed = [(NJOutputMouseScroll *)output speed];
266 BOOL smooth = [(NJOutputMouseScroll *)output smooth];
267 [scrollDirSelect selectSegmentWithTag:direction];
268 scrollSpeedSlider.floatValue = speed;
269 smoothCheck.state = smooth ? NSOnState : NSOffState;
270 scrollSpeedSlider.enabled = smooth;
271 } else {
272 [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
273 }
274 [self cleanUpInterface];
275 }
276
277 - (void)loadInput:(NJInput *)input {
278 _input = input;
279 [self loadOutput:self.currentOutput forInput:input];
280 }
281
282 - (void)focusKey {
283 if (radioButtons.selectedRow <= 1)
284 [keyInput.window makeFirstResponder:keyInput];
285 else
286 [keyInput resignIfFirstResponder];
287 }
288
289 - (void)mappingListDidChange:(NSNotification *)note {
290 NSArray *mappings = note.userInfo[NJMappingListKey];
291 NJMapping *current = mappingPopup.selectedItem.representedObject;
292 [mappingPopup.menu removeAllItems];
293 for (NJMapping *mapping in mappings) {
294 NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name
295 action:@selector(mappingChosen:)
296 keyEquivalent:@""];
297 item.target = self;
298 item.representedObject = mapping;
299 [mappingPopup.menu addItem:item];
300 }
301 [mappingPopup selectItemWithIdenticalRepresentedObject:current];
302 }
303
304 - (void)mappingDidChange:(NSNotification *)note {
305 [self loadInput:_input];
306 }
307
308 @end