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