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