Split NJMappingController view handling off into NJMappingViewController. This is...
[enjoyable.git] / Classes / NJMappingsViewController.m
1 //
2 // NJMappingsViewController.m
3 // Enjoyable
4 //
5 // Created by Joe Wreschnig on 3/17/13.
6 //
7 //
8
9 #import "NJMappingsViewController.h"
10
11 #import "NJMapping.h"
12
13 #define PB_ROW @"com.yukkurigames.Enjoyable.MappingRow"
14
15
16 @implementation NJMappingsViewController
17
18 - (void)awakeFromNib {
19 [self.mappingList registerForDraggedTypes:@[PB_ROW, NSURLPboardType]];
20 [self.mappingList setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
21 }
22
23 - (IBAction)addClicked:(id)sender {
24 NJMapping *newMapping = [[NJMapping alloc] init];
25 [self.delegate mappingsViewController:self addMapping:newMapping];
26 }
27
28 - (IBAction)removeClicked:(id)sender {
29 [self.delegate mappingsViewController:self
30 removeMappingAtIndex:self.mappingList.selectedRow];
31 }
32
33 - (IBAction)moveUpClicked:(id)sender {
34 NSInteger fromIdx = self.mappingList.selectedRow;
35 NSInteger toIdx = fromIdx - 1;
36 [self.delegate mappingsViewController:self
37 moveMappingFromIndex:fromIdx
38 toIndex:toIdx];
39 [self.mappingList beginUpdates];
40 [self.mappingList moveRowAtIndex:fromIdx toIndex:toIdx];
41 [self.mappingList endUpdates];
42 [self.mappingList scrollRowToVisible:toIdx];
43 [self.mappingList selectRowIndexes:[[NSIndexSet alloc] initWithIndex:toIdx]
44 byExtendingSelection:NO];
45 }
46
47 - (IBAction)moveDownClicked:(id)sender {
48 NSInteger fromIdx = self.mappingList.selectedRow;
49 NSInteger toIdx = fromIdx + 1;
50 [self.delegate mappingsViewController:self
51 moveMappingFromIndex:fromIdx
52 toIndex:toIdx];
53 [self.mappingList beginUpdates];
54 [self.mappingList moveRowAtIndex:fromIdx toIndex:toIdx];
55 [self.mappingList endUpdates];
56 [self.mappingList scrollRowToVisible:toIdx];
57 [self.mappingList selectRowIndexes:[[NSIndexSet alloc] initWithIndex:toIdx]
58 byExtendingSelection:NO];
59 }
60
61 - (IBAction)mappingTriggerClicked:(id)sender {
62 [self.mappingListPopover showRelativeToRect:self.mappingListTrigger.bounds
63 ofView:self.mappingListTrigger
64 preferredEdge:NSMinXEdge];
65 self.mappingListTrigger.state = NSOnState;
66 }
67
68 - (void)popoverWillShow:(NSNotification *)notification {
69 self.mappingListTrigger.state = NSOnState;
70 }
71
72 - (void)popoverWillClose:(NSNotification *)notification {
73 self.mappingListTrigger.state = NSOffState;
74 }
75
76 - (void)addedMappingAtIndex:(NSInteger)index startEditing:(BOOL)startEditing {
77 [self.mappingList abortEditing];
78 [self.mappingList beginUpdates];
79 [self.mappingList insertRowsAtIndexes:[[NSIndexSet alloc] initWithIndex:index]
80 withAnimation:startEditing ? 0 : NSTableViewAnimationSlideLeft];
81 [self.mappingList endUpdates];
82 if (startEditing) {
83 [self.mappingListTrigger performClick:self];
84 [self.mappingList editColumn:0 row:index withEvent:nil select:YES];
85 [self.mappingList scrollRowToVisible:index];
86 }
87 }
88
89 - (void)removedMappingAtIndex:(NSInteger)index {
90 [self.mappingList abortEditing];
91 [self.mappingList beginUpdates];
92 [self.mappingList removeRowsAtIndexes:[[NSIndexSet alloc] initWithIndex:index]
93 withAnimation:NSTableViewAnimationEffectFade];
94 [self.mappingList endUpdates];
95 }
96
97 - (void)changedActiveMappingToIndex:(NSInteger)index {
98 NJMapping *mapping = [self.delegate mappingsViewController:self
99 mappingForIndex:index];
100 self.removeMapping.enabled = [self.delegate mappingsViewController:self
101 canRemoveMappingAtIndex:index];
102 self.moveUp.enabled = [self.delegate mappingsViewController:self
103 canMoveMappingFromIndex:index toIndex:index - 1];
104 self.moveDown.enabled = [self.delegate mappingsViewController:self
105 canMoveMappingFromIndex:index toIndex:index + 1];
106 self.mappingListTrigger.title = mapping.name;
107 [self.mappingList selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
108 [self.mappingList scrollRowToVisible:index];
109 [NSUserDefaults.standardUserDefaults setInteger:index forKey:@"selected"];
110
111 }
112
113 - (void)tableViewSelectionDidChange:(NSNotification *)note {
114 [self.mappingList abortEditing];
115 NSTableView *tableView = note.object;
116 [self.delegate mappingsViewController:self
117 choseMappingAtIndex:tableView.selectedRow];
118 }
119
120 - (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)index {
121 return [self.delegate mappingsViewController:self
122 mappingForIndex:index].name;
123 }
124
125 - (void)tableView:(NSTableView *)view
126 setObjectValue:(NSString *)obj
127 forTableColumn:(NSTableColumn *)col
128 row:(NSInteger)index {
129 NJMapping *mapping = [self.delegate mappingsViewController:self
130 mappingForIndex:index];
131 mapping.name = obj;
132 [self.delegate mappingsViewController:self editedMappingAtIndex:index];
133 }
134
135 - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
136 return [self.delegate numberOfMappings:self];
137 }
138
139 - (BOOL)tableView:(NSTableView *)tableView
140 acceptDrop:(id <NSDraggingInfo>)info
141 row:(NSInteger)row
142 dropOperation:(NSTableViewDropOperation)dropOperation {
143 NSPasteboard *pboard = [info draggingPasteboard];
144 if ([pboard.types containsObject:PB_ROW]) {
145 NSString *value = [pboard stringForType:PB_ROW];
146 NSInteger srcRow = [value intValue];
147 row -= srcRow < row;
148 [self.mappingList beginUpdates];
149 [self.mappingList moveRowAtIndex:srcRow toIndex:row];
150 [self.mappingList endUpdates];
151 [self.delegate mappingsViewController:self
152 moveMappingFromIndex:srcRow
153 toIndex:row];
154 return YES;
155 } else if ([pboard.types containsObject:NSURLPboardType]) {
156 NSURL *url = [NSURL URLFromPasteboard:pboard];
157 NSError *error;
158 if (![self.delegate mappingsViewController:self
159 importMappingFromURL:url
160 atIndex:row
161 error:&error]) {
162 [tableView presentError:error];
163 return NO;
164 } else {
165 return YES;
166 }
167 } else {
168 return NO;
169 }
170 }
171
172 - (NSDragOperation)tableView:(NSTableView *)tableView
173 validateDrop:(id <NSDraggingInfo>)info
174 proposedRow:(NSInteger)row
175 proposedDropOperation:(NSTableViewDropOperation)dropOperation {
176 NSPasteboard *pboard = [info draggingPasteboard];
177 if ([pboard.types containsObject:PB_ROW]) {
178 [tableView setDropRow:MAX(1, row) dropOperation:NSTableViewDropAbove];
179 return NSDragOperationMove;
180 } else if ([pboard.types containsObject:NSURLPboardType]) {
181 NSURL *url = [NSURL URLFromPasteboard:pboard];
182 if ([url.pathExtension isEqualToString:@"enjoyable"]) {
183 [tableView setDropRow:MAX(1, row) dropOperation:NSTableViewDropAbove];
184 return NSDragOperationCopy;
185 } else {
186 return NSDragOperationNone;
187 }
188 } else {
189 return NSDragOperationNone;
190 }
191 }
192
193 - (NSArray *)tableView:(NSTableView *)tableView
194 namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
195 forDraggedRowsWithIndexes:(NSIndexSet *)indexSet {
196 NJMapping *toSave = [self.delegate mappingsViewController:self
197 mappingForIndex:indexSet.firstIndex];
198 NSString *filename = [[toSave.name stringByFixingPathComponent]
199 stringByAppendingPathExtension:@"enjoyable"];
200 NSURL *dst = [dropDestination URLByAppendingPathComponent:filename];
201 dst = [NSFileManager.defaultManager generateUniqueURLWithBase:dst];
202 NSError *error;
203 if (![toSave writeToURL:dst error:&error]) {
204 [tableView presentError:error];
205 return @[];
206 } else {
207 return @[dst.lastPathComponent];
208 }
209 }
210
211 - (BOOL)tableView:(NSTableView *)tableView
212 writeRowsWithIndexes:(NSIndexSet *)rowIndexes
213 toPasteboard:(NSPasteboard *)pboard {
214 if (rowIndexes.count == 1 && rowIndexes.firstIndex != 0) {
215 [pboard declareTypes:@[PB_ROW, NSFilesPromisePboardType] owner:nil];
216 [pboard setString:@(rowIndexes.firstIndex).stringValue forType:PB_ROW];
217 [pboard setPropertyList:@[@"enjoyable"] forType:NSFilesPromisePboardType];
218 return YES;
219 } else if (rowIndexes.count == 1 && rowIndexes.firstIndex == 0) {
220 [pboard declareTypes:@[NSFilesPromisePboardType] owner:nil];
221 [pboard setPropertyList:@[@"enjoyable"] forType:NSFilesPromisePboardType];
222 return YES;
223 } else {
224 return NO;
225 }
226 }
227
228 - (void)reloadData {
229 [self.mappingList reloadData];
230 }
231
232 @end
233