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