ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/MacOSX/Launcher/VMListController.mm
(Generate patch)

Comparing SheepShaver/src/MacOSX/Launcher/VMListController.mm (file contents):
Revision 1.1 by asvitkine, 2009-08-02T18:34:57Z vs.
Revision 1.11 by asvitkine, 2010-12-28T02:57:46Z

# Line 21 | Line 21
21   #import "VMListController.h"
22   #import "VMSettingsController.h"
23  
24 + /*
25 +
26 + TODO:
27 +
28 + Drag VM from Finder to import
29 + When choosing things like rom file and keycode files - have a checkbox to copy
30 + selected file into the bundle.
31 + Copy path!
32 +
33 + */
34 +
35 + @interface NSObject (TableViewContextMenu)
36 + - (NSMenu *) tableView: (NSTableView *) tableView menuForEvent: (NSEvent *) event;
37 + @end
38 +
39 + @implementation NSTableView (ContextMenu)
40 + - (NSMenu *) menuForEvent: (NSEvent *) event
41 + {
42 +        if ([[self delegate] respondsToSelector:@selector(tableView:menuForEvent:)])
43 +                return [[self delegate] tableView:self menuForEvent:event];
44 +        return nil;
45 + }
46 + @end
47 +
48 + #define VM_DRAG_TYPE @"sheepvm"
49 +
50   @implementation VMListController
51  
52   + (id) sharedInstance
# Line 40 | Line 66
66          vmArray = [[NSMutableArray alloc] initWithCapacity:[vms count]];
67          [vmArray addObjectsFromArray:vms];
68  
69 +        tasks = [[NSMutableDictionary alloc] init];
70 +
71 +        [[NSNotificationCenter defaultCenter] addObserver:self
72 +                selector:@selector(onTaskTerminated:)
73 +                name:NSTaskDidTerminateNotification
74 +                object:nil];
75 +
76          return self;
77   }
78  
79   - (void) awakeFromNib
80   {
81 <  [vmList setDataSource: self];
82 <        //[vmList setDelegate: self];
83 <  [vmList reloadData];
81 >        [[[vmList tableColumns] objectAtIndex:0] setEditable:YES];
82 >        [vmList setDataSource: self];
83 >        [vmList setDelegate: self];
84 >        [vmList reloadData];
85 >        [vmList registerForDraggedTypes:[NSArray arrayWithObjects:VM_DRAG_TYPE, nil]];
86 > }
87 >
88 > - (void) _showNotFoundAlert
89 > {
90 >        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
91 >        [alert setMessageText:@"The virtual machine cannot be found."];
92 >        [alert setAlertStyle:NSWarningAlertStyle];
93 >        [alert beginSheetModalForWindow:[self window]
94 >                    modalDelegate:self
95 >                   didEndSelector:nil
96 >                      contextInfo:nil];
97 > }
98 >
99 > - (void) reloadDataAndSave
100 > {
101 >        [vmList reloadData];
102 >        [[NSUserDefaults standardUserDefaults] setObject:vmArray forKey:@"vm_list"];
103 > }
104 >
105 > - (void) keyDown: (NSEvent *) event
106 > {
107 >        if ([event type] == NSKeyDown && [[event characters] length] > 0) {
108 >                unichar key = [[event characters] characterAtIndex:0];
109 >                if (key == NSDeleteFunctionKey || key == NSDeleteCharacter) {
110 >                        [self deleteVirtualMachine:self];
111 >                }
112 >        }
113   }
114  
115   - (int) numberOfRowsInTableView: (NSTableView *) table
116   {
117 <  return [vmArray count];
117 >        return [vmArray count];
118   }
119  
120   - (id) tableView: (NSTableView *) table objectValueForTableColumn: (NSTableColumn *) c row: (int) r
121   {
122 <  return [vmArray objectAtIndex: r]; // [[vmArray objectAtIndex: r] lastPathComponent];
122 >        return [[[vmArray objectAtIndex: r] lastPathComponent] stringByDeletingPathExtension];
123 > }
124 >
125 > - (void) tableView: (NSTableView *) table setObjectValue: (id) value forTableColumn: (NSTableColumn *) c row: (int) r
126 > {
127 >        NSString *currentPath = [vmArray objectAtIndex: r];
128 >        NSString *newPath = [[NSString stringWithFormat:@"%@/%@.sheepvm",
129 >                [currentPath stringByDeletingLastPathComponent], value] retain];
130 >        if (![currentPath isEqual:newPath]) {
131 >                if ([[NSFileManager defaultManager] fileExistsAtPath:currentPath]) {
132 >                        NSFileManager *manager = [NSFileManager defaultManager];
133 >                        if ([manager movePath: currentPath toPath: newPath handler:nil]) {
134 >                                [vmArray replaceObjectAtIndex: r withObject: newPath];
135 >                                [currentPath release];
136 >                        }
137 >                } else {
138 >                        [self _showNotFoundAlert];
139 >                }
140 >        }
141 > }
142 >
143 > - (void) tableViewSelectionDidChange: (NSNotification *) notification
144 > {
145 >        if ([vmList selectedRow] >= 0) {
146 >                [settingsButton setEnabled:YES];
147 >                [launchButton setEnabled:YES];
148 >        } else {
149 >                [settingsButton setEnabled:NO];
150 >                [launchButton setEnabled:NO];
151 >        }
152   }
153  
154 < //- (NSString *) tableView: (NSTableView *) table toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
155 < //             tableColumn: (NSTableColumn *) c row: (int) r mouseLocation: (NSPoint) loc
156 < //{
157 < //      return [vmArray objectAtIndex: r];
158 < //}
154 > - (BOOL) tableView: (NSTableView *) table writeRowsWithIndexes: (NSIndexSet *) rows toPasteboard: (NSPasteboard *) pboard
155 > {
156 >        vmBeingDragged = [vmArray objectAtIndex:[rows firstIndex]];
157 >        [pboard declareTypes:[NSArray arrayWithObject:VM_DRAG_TYPE] owner:self];
158 >        [pboard setString:VM_DRAG_TYPE forType:VM_DRAG_TYPE];
159 >        return YES;
160 > }
161 >
162 > - (NSDragOperation) tableView: (NSTableView *) table validateDrop: (id <NSDraggingInfo>) info proposedRow: (int) row proposedDropOperation: (NSTableViewDropOperation) op
163 > {
164 >        if (op == NSTableViewDropAbove && row != -1) {
165 >                return NSDragOperationPrivate;
166 >        } else {
167 >                return NSDragOperationNone;
168 >        }
169 > }
170 >
171 > - (BOOL) tableView: (NSTableView *) table acceptDrop: (id <NSDraggingInfo>) info row: (int) row dropOperation: (NSTableViewDropOperation) op
172 > {      
173 >        if ([[[info draggingPasteboard] availableTypeFromArray:[NSArray arrayWithObject:VM_DRAG_TYPE]] isEqualToString:VM_DRAG_TYPE]) {
174 >                [vmList deselectAll:nil];
175 >                int index = [vmArray indexOfObject:vmBeingDragged];
176 >                if (index != row) {
177 >                        [vmArray insertObject:vmBeingDragged atIndex:row];
178 >                        if (row <= index) {
179 >                                index += 1;
180 >                        } else {
181 >                                row -= 1;
182 >                        }
183 >                        [vmArray removeObjectAtIndex: index];
184 >                }
185 >                [self reloadDataAndSave];
186 >                [vmList selectRow:row byExtendingSelection:NO];
187 >                return YES;
188 >        }
189 >
190 >        return NO;
191 > }
192 >
193 > - (NSMenu *) tableView: (NSTableView *) table menuForEvent: (NSEvent *) event
194 > {
195 >        NSMenu *menu = nil;
196 >        int row = [table rowAtPoint:[table convertPoint:[event locationInWindow] fromView:nil]];
197 >        if (row >= 0) {
198 >                [table selectRow:row byExtendingSelection:NO];
199 >                menu = [[[NSMenu alloc] initWithTitle: @"Contextual Menu"] autorelease];
200 >                [menu addItemWithTitle: @"Launch Virtual Machine"
201 >                                action: @selector(launchVirtualMachine:) keyEquivalent: @""];
202 >                [menu addItemWithTitle: @"Edit VM Settings..."
203 >                                action: @selector(editVirtualMachineSettings:) keyEquivalent: @""];
204 >                [menu addItemWithTitle: @"Reveal VM in Finder"
205 >                                action: @selector(revealVirtualMachineInFinder:) keyEquivalent: @""];
206 >                [menu addItemWithTitle: @"Remove VM from List"
207 >                                action: @selector(deleteVirtualMachine:) keyEquivalent: @""];
208 >        }
209 >        return menu;
210 > }
211 >
212 > - (NSString *) tableView: (NSTableView *) table toolTipForCell: (NSCell *) cell rect: (NSRectPointer) rect
213 >             tableColumn: (NSTableColumn *) c row: (int) r mouseLocation: (NSPoint) loc
214 > {
215 >        return [vmArray objectAtIndex: r];
216 > }
217  
218   - (IBAction) newVirtualMachine: (id) sender
219   {
220 +        [vmList abortEditing];
221          NSSavePanel *save = [NSSavePanel savePanel];
222          [save setMessage: @"New SheepShaver Virtual Machine:"];
223          [save setRequiredFileType: @"sheepvm"];
# Line 84 | Line 234
234   - (IBAction) _newVirtualMachineDone: (NSSavePanel *) save returnCode: (int) returnCode contextInfo: (void *) contextInfo
235   {
236          if (returnCode == NSOKButton) {
237 <                // make dir.
238 <                // create prefs file in there
239 <                // edit said prefs file
240 <                // advanced: show sub-panel in save dialog that says "Create Disk:"
237 >                NSFileManager *manager = [NSFileManager defaultManager];
238 >                [manager createDirectoryAtPath:[save filename] attributes:nil];
239 >                [manager createFileAtPath:[[save filename] stringByAppendingPathComponent:@"prefs"] contents:nil attributes:nil];
240 >                [vmArray addObject:[save filename]];
241 >                [vmList reloadData];
242 >                [vmList selectRow:([vmArray count] - 1) byExtendingSelection:NO];
243 >                [[VMSettingsController sharedInstance] editSettingsForNewVM:[save filename] sender:self];
244 >                if ([[VMSettingsController sharedInstance] cancelWasClicked]) {
245 >                        [manager removeFileAtPath:[save filename] handler:nil];
246 >                        [vmArray removeObjectAtIndex:([vmArray count] - 1)];
247 >                }
248 >                [self reloadDataAndSave];
249          }
250   }
251  
252   - (IBAction) importVirtualMachine: (id) sender
253   {
254 +        [vmList abortEditing];
255          NSOpenPanel *open = [NSOpenPanel openPanel];
256          [open setMessage:@"Import SheepShaver Virtual Machine:"];
257          [open setResolvesAliases:YES];
# Line 113 | Line 272
272   {
273          if (returnCode == NSOKButton) {
274                  [vmArray addObject:[open filename]];
275 <                [vmList reloadData];
117 <                [[NSUserDefaults standardUserDefaults] setObject:vmArray forKey:@"vm_list"];
275 >                [self reloadDataAndSave];
276          }
277   }
278  
279 < - (IBAction) editVirtualMachineSettings:(id)sender
279 > - (IBAction) editVirtualMachineSettings: (id) sender
280   {
281 +        [vmList abortEditing];
282          int selectedRow = [vmList selectedRow];
283 <  if (selectedRow >= 0) {
284 <                [[VMSettingsController sharedInstance] editSettingsFor:[vmArray objectAtIndex:selectedRow] sender:sender];
285 <  }
283 >        if (selectedRow >= 0) {
284 >                NSString *path = [vmArray objectAtIndex:selectedRow];
285 >                if ([tasks objectForKey:path]) {
286 >                        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
287 >                        [alert setMessageText:@"Cannot edit virtual machine settings while it's running."];
288 >                        [alert setAlertStyle:NSWarningAlertStyle];
289 >                        [alert beginSheetModalForWindow:[self window]
290 >                                    modalDelegate:self
291 >                                   didEndSelector:nil
292 >                                      contextInfo:nil];
293 >                } else if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
294 >                        [[VMSettingsController sharedInstance] editSettingsFor:path sender:sender];
295 >                } else {
296 >                        [self _showNotFoundAlert];
297 >                }
298 >        }
299   }
300  
301 < - (IBAction) runVirtualMachine:(id)sender
301 > - (IBAction) launchVirtualMachine: (id) sender
302   {
303 +        [vmList abortEditing];
304 +        int selectedRow = [vmList selectedRow];
305 +        if (selectedRow >= 0) {
306 +                NSString *path = [vmArray objectAtIndex:selectedRow];
307 +                if ([tasks objectForKey:path]) {
308 +                        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
309 +                        [alert setMessageText:@"The selected virtual machine is already running."];
310 +                        [alert setAlertStyle:NSWarningAlertStyle];
311 +                        [alert beginSheetModalForWindow:[self window]
312 +                                    modalDelegate:self
313 +                                   didEndSelector:nil
314 +                                      contextInfo:nil];
315 +                } else if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
316 +                        NSTask *sheep = [[NSTask alloc] init];
317 +                        [sheep setLaunchPath:[[NSBundle mainBundle] pathForAuxiliaryExecutable:@"SheepShaver"]];
318 +                        [sheep setArguments:[NSArray arrayWithObject:path]];
319 +                        [sheep launch];
320 +                        [tasks setObject:sheep forKey:path];
321 +                } else {
322 +                        [self _showNotFoundAlert];
323 +                }
324 +        }
325 + }
326 +
327 + - (void) onTaskTerminated: (NSNotification *) notification
328 + {
329 +        NSArray *paths = [tasks allKeys];
330 +        NSEnumerator *enumerator = [paths objectEnumerator];
331 +        NSString *path;
332 +        while ((path = [enumerator nextObject])) {
333 +                NSTask *task = [tasks objectForKey:path];
334 +                if (![task isRunning]) {
335 +                        [tasks removeObjectForKey:path];
336 +                        [task release];
337 +                }
338 +        }
339 + }
340 +
341 + - (IBAction) deleteVirtualMachine: (id) sender
342 + {
343 +        [vmList abortEditing];
344 +        int selectedRow = [vmList selectedRow];
345 +        if (selectedRow >= 0) {
346 +                NSAlert *alert = [[[NSAlert alloc] init] autorelease];
347 +                [alert setMessageText:@"Do you wish to remove the selected virtual machine from the list?"];
348 +                [alert addButtonWithTitle:@"Remove"];
349 +                [alert addButtonWithTitle:@"Cancel"];
350 +                [alert setAlertStyle:NSWarningAlertStyle];
351 +                [alert beginSheetModalForWindow:[self window]
352 +                                  modalDelegate:self
353 +                                 didEndSelector:@selector(_deleteVirtualMachineDone: returnCode: contextInfo:)
354 +                                    contextInfo:nil];
355 +        }
356 + }
357 +
358 + - (void) _deleteVirtualMachineDone: (NSAlert *) alert returnCode: (int) returnCode contextInfo: (void *) contextInfo
359 + {
360 +        if (returnCode == NSAlertFirstButtonReturn) {
361 +                [vmArray removeObjectAtIndex:[vmList selectedRow]];
362 +                [vmList deselectAll:self];
363 +                [self reloadDataAndSave];
364 +        }
365 + }
366 +
367 + - (IBAction) revealVirtualMachineInFinder: (id) sender
368 + {
369 +        [vmList abortEditing];
370 +        int selectedRow = [vmList selectedRow];
371 +        if (selectedRow >= 0) {
372 +                NSString *path = [vmArray objectAtIndex:selectedRow];
373 +                if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
374 +                        [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: @""];
375 +                } else {
376 +                        [self _showNotFoundAlert];
377 +                }
378 +        }
379   }
380  
381   @end

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines