f3eca24b79c50a6857e45e0f60214bf8a5b10196
[enjoyable.git] / 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 #import "NJOutputSwitchMouseMode.h"
23
24 @implementation NJOutputController
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 } else if (!mappingPopup.selectedItem)
53 [mappingPopup selectItemAtIndex:0];
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 = 4;
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 [scrollDirSelect resignIfFirstResponder];
76 } else {
77 if (scrollDirSelect.selectedSegment == -1)
78 scrollDirSelect.selectedSegment = 0;
79 if (scrollDirSelect.selectedSegment < 2
80 && !scrollSpeedSlider.floatValue)
81 scrollSpeedSlider.floatValue = 15.f;
82 else if (scrollDirSelect.selectedSegment >= 2
83 && scrollSpeedSlider.floatValue)
84 scrollSpeedSlider.floatValue = scrollSpeedSlider.minValue;
85 }
86
87 }
88
89 - (IBAction)radioChanged:(NSView *)sender {
90 [sender.window makeFirstResponder:sender];
91 if (radioButtons.selectedRow == 1)
92 [keyInput.window makeFirstResponder:keyInput];
93 [self commit];
94 }
95
96 - (void)keyInputField:(NJKeyInputField *)keyInput didChangeKey:(CGKeyCode)keyCode {
97 [radioButtons selectCellAtRow:1 column:0];
98 [radioButtons.window makeFirstResponder:radioButtons];
99 [self commit];
100 }
101
102 - (void)keyInputFieldDidClear:(NJKeyInputField *)keyInput {
103 [radioButtons selectCellAtRow:0 column:0];
104 [self commit];
105 }
106
107 - (void)mappingChosen:(id)sender {
108 [radioButtons selectCellAtRow:2 column:0];
109 [mappingPopup.window makeFirstResponder:mappingPopup];
110 [self commit];
111 }
112
113 - (void)mdirChanged:(NSView *)sender {
114 [radioButtons selectCellAtRow:3 column:0];
115 [sender.window makeFirstResponder:sender];
116 [self commit];
117 }
118
119 - (void)mouseSpeedChanged:(NSSlider *)sender {
120 [radioButtons selectCellAtRow:3 column:0];
121 [sender.window makeFirstResponder:sender];
122 [self commit];
123 }
124
125 - (void)mbtnChanged:(NSView *)sender {
126 [radioButtons selectCellAtRow:4 column:0];
127 [sender.window makeFirstResponder:sender];
128 [self commit];
129 }
130
131 - (void)sdirChanged:(NSView *)sender {
132 [radioButtons selectCellAtRow:5 column:0];
133 [sender.window makeFirstResponder:sender];
134 [self commit];
135 }
136
137 - (void)scrollSpeedChanged:(NSSlider *)sender {
138 [radioButtons selectCellAtRow:5 column:0];
139 [sender.window makeFirstResponder:sender];
140 if (!sender.floatValue && scrollDirSelect.selectedSegment < 2)
141 scrollDirSelect.selectedSegment += 2;
142 else if (sender.floatValue && scrollDirSelect.selectedSegment >= 2)
143 scrollDirSelect.selectedSegment -= 2;
144 [self commit];
145 }
146
147 - (NJOutput *)currentOutput {
148 return mappingsController.currentMapping[inputController.selectedInput];
149 }
150
151 - (NJOutput *)makeOutput {
152 switch (radioButtons.selectedRow) {
153 case 0:
154 return nil;
155 case 1:
156 if (keyInput.hasKeyCode) {
157 NJOutputKeyPress *k = [[NJOutputKeyPress alloc] init];
158 k.vk = keyInput.keyCode;
159 return k;
160 } else {
161 return nil;
162 }
163 break;
164 case 2: {
165 NJOutputMapping *c = [[NJOutputMapping alloc] init];
166 c.mapping = mappingsController[mappingPopup.indexOfSelectedItem];
167 return c;
168 }
169 case 3: {
170 NJOutputMouseMove *mm = [[NJOutputMouseMove alloc] init];
171 mm.axis = mouseDirSelect.selectedSegment;
172 mm.speed = mouseSpeedSlider.floatValue;
173 return mm;
174 }
175 case 4: {
176 NJOutputMouseButton *mb = [[NJOutputMouseButton alloc] init];
177 mb.button = mouseBtnSelect.selectedSegment == 0 ? kCGMouseButtonLeft : kCGMouseButtonRight;
178 return mb;
179 }
180 case 5: {
181 NJOutputMouseScroll *ms = [[NJOutputMouseScroll alloc] init];
182 ms.direction = (scrollDirSelect.selectedSegment & 1) ? 1 : -1;
183 ms.speed = scrollDirSelect.selectedSegment < 2
184 ? scrollSpeedSlider.floatValue
185 : 0.f;
186 return ms;
187 }
188 case 6: {
189 NJOutputSwitchMouseMode *tms = [[NJOutputSwitchMouseMode alloc] init];
190 return tms;
191 }
192 default:
193 return nil;
194 }
195 }
196
197 - (void)commit {
198 [self cleanUpInterface];
199 mappingsController.currentMapping[inputController.selectedInput] = [self makeOutput];
200 [mappingsController save];
201 }
202
203 - (BOOL)enabled {
204 return [radioButtons isEnabled];
205 }
206
207 - (void)setEnabled:(BOOL)enabled {
208 [radioButtons setEnabled:enabled];
209 [keyInput setEnabled:enabled];
210 [mappingPopup setEnabled:enabled];
211 [mouseDirSelect setEnabled:enabled];
212 [mouseSpeedSlider setEnabled:enabled];
213 [mouseBtnSelect setEnabled:enabled];
214 [scrollDirSelect setEnabled:enabled];
215 }
216
217 - (void)loadOutput:(NJOutput *)output forInput:(NJInput *)input {
218 if (!input) {
219 self.enabled = NO;
220 title.stringValue = @"";
221 } else {
222 self.enabled = YES;
223 NSString *inpFullName = input.name;
224 for (id <NJInputPathElement> cur = input.base; cur; cur = cur.base) {
225 inpFullName = [[NSString alloc] initWithFormat:@"%@ > %@", cur.name, inpFullName];
226 }
227 title.stringValue = inpFullName;
228 }
229
230 if ([output isKindOfClass:NJOutputKeyPress.class]) {
231 [radioButtons selectCellAtRow:1 column:0];
232 keyInput.keyCode = [(NJOutputKeyPress*)output vk];
233 } else if ([output isKindOfClass:NJOutputMapping.class]) {
234 [radioButtons selectCellAtRow:2 column:0];
235 NSMenuItem *item = [mappingPopup itemWithRepresentedObject:[(NJOutputMapping *)output mapping]];
236 [mappingPopup selectItem:item];
237 if (!item)
238 [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
239 }
240 else if ([output isKindOfClass:NJOutputMouseMove.class]) {
241 [radioButtons selectCellAtRow:3 column:0];
242 mouseDirSelect.selectedSegment = [(NJOutputMouseMove *)output axis];
243 mouseSpeedSlider.floatValue = [(NJOutputMouseMove *)output speed];
244 }
245 else if ([output isKindOfClass:NJOutputMouseButton.class]) {
246 [radioButtons selectCellAtRow:4 column:0];
247 mouseBtnSelect.selectedSegment = [(NJOutputMouseButton *)output button] == kCGMouseButtonLeft ? 0 : 1;
248 }
249 else if ([output isKindOfClass:NJOutputMouseScroll.class]) {
250 [radioButtons selectCellAtRow:5 column:0];
251 int direction = [(NJOutputMouseScroll *)output direction];
252 float speed = [(NJOutputMouseScroll *)output speed];
253 scrollDirSelect.selectedSegment = (direction > 0) + !speed * 2;
254 scrollSpeedSlider.floatValue = speed;
255 }
256 else if ([output isKindOfClass:NJOutputSwitchMouseMode.class]) {
257 [radioButtons selectCellAtRow:6 column:0];
258 } else {
259 [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
260 }
261 [self cleanUpInterface];
262 }
263
264 - (void)loadCurrent {
265 [self loadOutput:self.currentOutput forInput:inputController.selectedInput];
266 }
267
268 - (void)focusKey {
269 if (radioButtons.selectedRow <= 1)
270 [keyInput.window makeFirstResponder:keyInput];
271 else
272 [keyInput resignIfFirstResponder];
273 }
274
275 - (void)mappingListDidChange:(NSNotification *)note {
276 NSArray *mappings = note.object;
277 NJMapping *current = mappingPopup.selectedItem.representedObject;
278 [mappingPopup.menu removeAllItems];
279 for (NJMapping *mapping in mappings) {
280 NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name
281 action:@selector(mappingChosen:)
282 keyEquivalent:@""];
283 item.target = self;
284 item.representedObject = mapping;
285 [mappingPopup.menu addItem:item];
286 }
287 [mappingPopup selectItemWithRepresentedObject:current];
288 }
289
290 @end