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