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