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