2 // NJOutputController.m
5 // Created by Sam McCall on 5/05/09.
8 #import "NJOutputController.h"
13 #import "NJInputController.h"
14 #import "NJKeyInputField.h"
15 #import "NJOutputMapping.h"
16 #import "NJOutputController.h"
17 #import "NJOutputKeyPress.h"
18 #import "NJOutputMouseButton.h"
19 #import "NJOutputMouseMove.h"
20 #import "NJOutputMouseScroll.h"
22 @implementation NJOutputController {
27 if ((self = [super init])) {
28 [NSNotificationCenter.defaultCenter
30 selector:@selector(mappingListDidChange:)
31 name:NJEventMappingListChanged
33 [NSNotificationCenter.defaultCenter
35 selector:@selector(mappingDidChange:)
36 name:NJEventMappingChanged
43 [NSNotificationCenter.defaultCenter removeObserver:self];
46 - (void)cleanUpInterface {
47 NSInteger row = radioButtons.selectedRow;
50 keyInput.keyCode = NJKeyInputFieldEmpty;
51 [keyInput resignIfFirstResponder];
55 [mappingPopup selectItemAtIndex:-1];
56 [mappingPopup resignIfFirstResponder];
57 unknownMapping.hidden = YES;
61 mouseDirSelect.selectedSegment = -1;
62 mouseSpeedSlider.floatValue = mouseSpeedSlider.minValue;
63 [mouseDirSelect resignIfFirstResponder];
65 if (mouseDirSelect.selectedSegment == -1)
66 mouseDirSelect.selectedSegment = 0;
67 if (!mouseSpeedSlider.floatValue)
68 mouseSpeedSlider.floatValue = 10;
72 mouseBtnSelect.selectedSegment = -1;
73 [mouseBtnSelect resignIfFirstResponder];
74 } else if (mouseBtnSelect.selectedSegment == -1)
75 mouseBtnSelect.selectedSegment = 0;
78 scrollDirSelect.selectedSegment = -1;
79 scrollSpeedSlider.floatValue = scrollSpeedSlider.minValue;
80 smoothCheck.state = NSOffState;
81 [scrollDirSelect resignIfFirstResponder];
82 [scrollSpeedSlider resignIfFirstResponder];
83 [smoothCheck resignIfFirstResponder];
85 if (scrollDirSelect.selectedSegment == -1)
86 scrollDirSelect.selectedSegment = 0;
91 - (IBAction)radioChanged:(NSView *)sender {
92 [sender.window makeFirstResponder:sender];
93 if (radioButtons.selectedRow == 1)
94 [keyInput.window makeFirstResponder:keyInput];
98 - (void)keyInputField:(NJKeyInputField *)keyInput didChangeKey:(CGKeyCode)keyCode {
99 [radioButtons selectCellAtRow:1 column:0];
100 [radioButtons.window makeFirstResponder:radioButtons];
104 - (void)keyInputFieldDidClear:(NJKeyInputField *)keyInput {
105 [radioButtons selectCellAtRow:0 column:0];
109 - (void)mappingChosen:(id)sender {
110 [radioButtons selectCellAtRow:2 column:0];
111 [mappingPopup.window makeFirstResponder:mappingPopup];
112 unknownMapping.hidden = YES;
116 - (void)mdirChanged:(NSView *)sender {
117 [radioButtons selectCellAtRow:3 column:0];
118 [sender.window makeFirstResponder:sender];
122 - (void)mouseSpeedChanged:(NSSlider *)sender {
123 [radioButtons selectCellAtRow:3 column:0];
124 [sender.window makeFirstResponder:sender];
128 - (void)mbtnChanged:(NSView *)sender {
129 [radioButtons selectCellAtRow:4 column:0];
130 [sender.window makeFirstResponder:sender];
134 - (void)sdirChanged:(NSView *)sender {
135 [radioButtons selectCellAtRow:5 column:0];
136 [sender.window makeFirstResponder:sender];
140 - (void)scrollSpeedChanged:(NSSlider *)sender {
141 [radioButtons selectCellAtRow:5 column:0];
142 [sender.window makeFirstResponder:sender];
146 - (IBAction)scrollTypeChanged:(NSButton *)sender {
147 [radioButtons selectCellAtRow:5 column:0];
148 [sender.window makeFirstResponder:sender];
149 if (sender.state == NSOnState) {
150 scrollSpeedSlider.floatValue =
151 scrollSpeedSlider.minValue + (scrollSpeedSlider.maxValue - scrollSpeedSlider.minValue) / 2;
152 scrollSpeedSlider.enabled = YES;
154 scrollSpeedSlider.floatValue = scrollSpeedSlider.minValue;
155 scrollSpeedSlider.enabled = NO;
160 - (NJOutput *)currentOutput {
161 return inputController.currentMapping[_input];
164 - (NJOutput *)makeOutput {
165 switch (radioButtons.selectedRow) {
169 if (keyInput.hasKeyCode) {
170 NJOutputKeyPress *k = [[NJOutputKeyPress alloc] init];
171 k.keyCode = keyInput.keyCode;
178 NJOutputMapping *c = [[NJOutputMapping alloc] init];
179 c.mapping = inputController.mappings[mappingPopup.indexOfSelectedItem];
183 NJOutputMouseMove *mm = [[NJOutputMouseMove alloc] init];
184 mm.axis = mouseDirSelect.selectedSegment;
185 mm.speed = mouseSpeedSlider.floatValue;
189 NJOutputMouseButton *mb = [[NJOutputMouseButton alloc] init];
190 mb.button = [mouseBtnSelect.cell tagForSegment:mouseBtnSelect.selectedSegment];
194 NJOutputMouseScroll *ms = [[NJOutputMouseScroll alloc] init];
195 ms.direction = [scrollDirSelect.cell tagForSegment:scrollDirSelect.selectedSegment];
196 ms.speed = scrollSpeedSlider.floatValue;
197 ms.smooth = smoothCheck.state == NSOnState;
206 [self cleanUpInterface];
207 inputController.currentMapping[_input] = [self makeOutput];
208 [inputController save];
212 return radioButtons.isEnabled;
215 - (void)setEnabled:(BOOL)enabled {
216 radioButtons.enabled = enabled;
217 keyInput.enabled = enabled;
218 mappingPopup.enabled = enabled;
219 mouseDirSelect.enabled = enabled;
220 mouseSpeedSlider.enabled = enabled;
221 mouseBtnSelect.enabled = enabled;
222 scrollDirSelect.enabled = enabled;
223 smoothCheck.enabled = enabled;
224 scrollSpeedSlider.enabled = enabled && smoothCheck.state;
226 unknownMapping.hidden = YES;
229 - (void)loadOutput:(NJOutput *)output forInput:(NJInput *)input {
232 title.stringValue = @"";
235 NSString *inpFullName = input.name;
236 for (NJInputPathElement *cur = input.parent; cur; cur = cur.parent) {
237 inpFullName = [[NSString alloc] initWithFormat:@"%@ ▸ %@", cur.name, inpFullName];
239 title.stringValue = inpFullName;
242 if ([output isKindOfClass:NJOutputKeyPress.class]) {
243 [radioButtons selectCellAtRow:1 column:0];
244 keyInput.keyCode = [(NJOutputKeyPress*)output keyCode];
245 } else if ([output isKindOfClass:NJOutputMapping.class]) {
246 [radioButtons selectCellAtRow:2 column:0];
247 NSMenuItem *item = [mappingPopup itemWithIdenticalRepresentedObject:[(NJOutputMapping *)output mapping]];
248 [mappingPopup selectItem:item];
249 unknownMapping.hidden = !!item;
250 unknownMapping.title = [(NJOutputMapping *)output mappingName];
252 else if ([output isKindOfClass:NJOutputMouseMove.class]) {
253 [radioButtons selectCellAtRow:3 column:0];
254 mouseDirSelect.selectedSegment = [(NJOutputMouseMove *)output axis];
255 mouseSpeedSlider.floatValue = [(NJOutputMouseMove *)output speed];
257 else if ([output isKindOfClass:NJOutputMouseButton.class]) {
258 [radioButtons selectCellAtRow:4 column:0];
259 [mouseBtnSelect selectSegmentWithTag:[(NJOutputMouseButton *)output button]];
261 else if ([output isKindOfClass:NJOutputMouseScroll.class]) {
262 [radioButtons selectCellAtRow:5 column:0];
263 int direction = [(NJOutputMouseScroll *)output direction];
264 float speed = [(NJOutputMouseScroll *)output speed];
265 BOOL smooth = [(NJOutputMouseScroll *)output smooth];
266 [scrollDirSelect selectSegmentWithTag:direction];
267 scrollSpeedSlider.floatValue = speed;
268 smoothCheck.state = smooth ? NSOnState : NSOffState;
269 scrollSpeedSlider.enabled = smooth;
271 [radioButtons selectCellAtRow:self.enabled ? 0 : -1 column:0];
273 [self cleanUpInterface];
276 - (void)loadInput:(NJInput *)input {
278 [self loadOutput:self.currentOutput forInput:input];
282 if (radioButtons.selectedRow <= 1)
283 [keyInput.window makeFirstResponder:keyInput];
285 [keyInput resignIfFirstResponder];
288 - (void)mappingListDidChange:(NSNotification *)note {
289 NSArray *mappings = note.userInfo[NJMappingListKey];
290 NJMapping *current = mappingPopup.selectedItem.representedObject;
291 [mappingPopup.menu removeAllItems];
292 for (NJMapping *mapping in mappings) {
293 NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:mapping.name
294 action:@selector(mappingChosen:)
297 item.representedObject = mapping;
298 [mappingPopup.menu addItem:item];
300 [mappingPopup selectItemWithIdenticalRepresentedObject:current];
303 - (void)mappingDidChange:(NSNotification *)note {
304 [self loadInput:_input];