diff options
-rw-r--r-- | Interfaces/English.lproj/BundleEditor.xib | 55 | ||||
-rw-r--r-- | Source/SPBundleEditorController.h | 2 | ||||
-rw-r--r-- | Source/SPBundleEditorController.m | 401 | ||||
-rw-r--r-- | Source/SPOutlineView.m | 58 |
4 files changed, 349 insertions, 167 deletions
diff --git a/Interfaces/English.lproj/BundleEditor.xib b/Interfaces/English.lproj/BundleEditor.xib index fe0dfdbc..2f5c74e7 100644 --- a/Interfaces/English.lproj/BundleEditor.xib +++ b/Interfaces/English.lproj/BundleEditor.xib @@ -23,7 +23,8 @@ </object> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> - <integer value="962"/> + <integer value="899"/> + <integer value="730"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -176,7 +177,7 @@ </object> </object> <double key="NSRowHeight">20</double> - <int key="NSTvFlags">1262485504</int> + <int key="NSTvFlags">1128267776</int> <reference key="NSDelegate"/> <reference key="NSDataSource"/> <string key="NSAutosaveName">SPBundleEditorOutlineView</string> @@ -187,7 +188,6 @@ <int key="NSTableViewSelectionHighlightStyle">1</int> <int key="NSTableViewDraggingDestinationStyle">1</int> <float key="NSOutlineViewIndentationPerLevelKey">14</float> - <bool key="NSOutlineViewAutosaveExpandedItemsKey">YES</bool> </object> </object> <string key="NSFrame">{{1, 1}, {146, 420}}</string> @@ -384,7 +384,6 @@ </object> </object> </object> - <int key="NSSelectedIndex">5</int> <bool key="NSPullDown">YES</bool> <int key="NSPreferredEdge">1</int> <bool key="NSUsesItemFromMenu">YES</bool> @@ -1069,7 +1068,7 @@ <bool key="NSAvoidsEmptySelection">YES</bool> <bool key="NSPreservesSelection">YES</bool> <bool key="NSSelectsInsertedObjects">YES</bool> - <string key="NSTreeContentChildrenKey">children</string> + <string key="NSTreeContentChildrenKey">_children_</string> </object> <object class="NSMenu" id="655873624"> <string key="NSTitle"/> @@ -1107,7 +1106,7 @@ </object> <object class="NSMenuItem" id="1055471998"> <reference key="NSMenu" ref="655873624"/> - <string key="NSTitle">Remove Selected Bundles</string> + <string key="NSTitle">Remove Selected Bundle</string> <string type="base64-UTF8" key="NSKeyEquiv">CA</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> @@ -1624,6 +1623,14 @@ </object> <int key="connectionID">991</int> </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">addButton</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="275669410"/> + </object> + <int key="connectionID">992</int> + </object> </object> <object class="IBMutableOrderedSet" key="objectRecords"> <object class="NSArray" key="orderedObjects"> @@ -2347,6 +2354,7 @@ <string>962.IBPluginDependency</string> <string>963.IBPluginDependency</string> <string>964.IBPluginDependency</string> + <string>965.CustomClassName</string> <string>965.IBPluginDependency</string> <string>967.IBPluginDependency</string> <string>970.IBPluginDependency</string> @@ -2355,9 +2363,9 @@ <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{226, 478}, {655, 444}}</string> + <string>{{182, 102}, {655, 444}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{226, 478}, {655, 444}}</string> + <string>{{182, 102}, {655, 444}}</string> <boolean value="NO"/> <boolean value="YES"/> <string>{655, 444}</string> @@ -2414,7 +2422,7 @@ <object class="IBToolTipAttribute" key="NS.object.0"> <string key="name">ToolTip</string> <reference key="object" ref="369890801"/> - <string key="toolTip">Remove selected Bundles (⌘⌫)</string> + <string key="toolTip">Remove selected Bundle (⌘⌫)</string> </object> </object> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2430,7 +2438,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.brandonwalkin.BWToolkit</string> - <string>{{239, 290}, {204, 98}}</string> + <string>{{276, 237}, {204, 98}}</string> <string>com.brandonwalkin.BWToolkit</string> <string>com.brandonwalkin.BWToolkit</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2538,7 +2546,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> - <string>{{151, 519}, {268, 73}}</string> + <string>{{151, 519}, {261, 73}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2566,6 +2574,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>SPOutlineView</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -2588,7 +2597,7 @@ </object> </object> <nil key="sourceID"/> - <int key="maxID">991</int> + <int key="maxID">992</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -2834,8 +2843,8 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>addButton</string> <string>categoryTextField</string> - <string>commandBundleArrayController</string> <string>commandBundleTreeController</string> <string>commandTextView</string> <string>commandsOutlineView</string> @@ -2854,8 +2863,8 @@ </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSButton</string> <string>NSTextField</string> - <string>NSArrayController</string> <string>NSTreeController</string> <string>id</string> <string>id</string> @@ -2877,8 +2886,8 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>addButton</string> <string>categoryTextField</string> - <string>commandBundleArrayController</string> <string>commandBundleTreeController</string> <string>commandTextView</string> <string>commandsOutlineView</string> @@ -2898,12 +2907,12 @@ <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBToOneOutletInfo"> - <string key="name">categoryTextField</string> - <string key="candidateClassName">NSTextField</string> + <string key="name">addButton</string> + <string key="candidateClassName">NSButton</string> </object> <object class="IBToOneOutletInfo"> - <string key="name">commandBundleArrayController</string> - <string key="candidateClassName">NSArrayController</string> + <string key="name">categoryTextField</string> + <string key="candidateClassName">NSTextField</string> </object> <object class="IBToOneOutletInfo"> <string key="name">commandBundleTreeController</string> @@ -2972,6 +2981,14 @@ <string key="minorKey">../../Source/SPBundleEditorController.h</string> </object> </object> + <object class="IBPartialClassDescription"> + <string key="className">SPOutlineView</string> + <string key="superclassName">NSOutlineView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBDocumentRelativeSource</string> + <string key="minorKey">../../Source/SPOutlineView.h</string> + </object> + </object> </object> <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> <bool key="EncodedWithXMLCoder">YES</bool> diff --git a/Source/SPBundleEditorController.h b/Source/SPBundleEditorController.h index b5001e0c..4a2468e0 100644 --- a/Source/SPBundleEditorController.h +++ b/Source/SPBundleEditorController.h @@ -43,12 +43,14 @@ IBOutlet NSPopUpButton* outputPopupButton; IBOutlet NSPopUpButton* scopePopupButton; IBOutlet NSButton *removeButton; + IBOutlet NSButton *addButton; IBOutlet NSMenuItem *duplicateMenuItem; IBOutlet NSMenuItem *revealInFinderMenuItem; IBOutlet SRRecorderControl *keyEquivalentField; IBOutlet NSTreeController *commandBundleTreeController; NSMutableArray *commandBundleArray; + NSMutableArray *touchedBundleArray; NSMutableDictionary *commandBundleTree; NSString *bundlePath; diff --git a/Source/SPBundleEditorController.m b/Source/SPBundleEditorController.m index b137de13..17a4e337 100644 --- a/Source/SPBundleEditorController.m +++ b/Source/SPBundleEditorController.m @@ -25,6 +25,8 @@ #import "SPBundleEditorController.h" #import "SPArrayAdditions.h" +#define kBundleNameKey @"bundleName" +#define kChildrenKey @"_children_" @interface SPBundleEditorController (PrivateAPI) @@ -44,6 +46,7 @@ if ((self = [super initWithWindowNibName:@"BundleEditor"])) { commandBundleArray = nil; + touchedBundleArray = nil; draggedFilePath = nil; oldBundleName = nil; isTableCellEditing = NO; @@ -75,6 +78,7 @@ [inputFallbackInputFieldScopeArray release]; if(commandBundleArray) [commandBundleArray release], commandBundleArray = nil; + if(touchedBundleArray) [touchedBundleArray release], touchedBundleArray = nil; if(commandBundleTree) [commandBundleTree release], commandBundleTree = nil; if(bundlePath) [bundlePath release], bundlePath = nil; @@ -86,13 +90,14 @@ { commandBundleArray = [[NSMutableArray alloc] initWithCapacity:1]; + touchedBundleArray = [[NSMutableArray alloc] initWithCapacity:1]; commandBundleTree = [[NSMutableDictionary alloc] initWithCapacity:1]; - [commandBundleTree setObject:[NSMutableArray array] forKey:@"children"]; - [commandBundleTree setObject:@"Bundles" forKey:@"bundleName"]; - [[commandBundleTree objectForKey:@"children"] addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSMutableArray array], @"children", NSLocalizedString(@"Input Field", @"input field scope menu label"), @"bundleName", nil]]; - [[commandBundleTree objectForKey:@"children"] addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSMutableArray array], @"children", NSLocalizedString(@"Data Table", @"data table scope menu label"), @"bundleName", nil]]; - [[commandBundleTree objectForKey:@"children"] addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSMutableArray array], @"children", NSLocalizedString(@"General", @"general scope menu label"), @"bundleName", nil]]; + [commandBundleTree setObject:[NSMutableArray array] forKey:kChildrenKey]; + [commandBundleTree setObject:@"BUNDLES" forKey:kBundleNameKey]; + [[commandBundleTree objectForKey:kChildrenKey] addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSMutableArray array], kChildrenKey, NSLocalizedString(@"Input Field", @"input field scope menu label"), kBundleNameKey, nil]]; + [[commandBundleTree objectForKey:kChildrenKey] addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSMutableArray array], kChildrenKey, NSLocalizedString(@"Data Table", @"data table scope menu label"), kBundleNameKey, nil]]; + [[commandBundleTree objectForKey:kChildrenKey] addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSMutableArray array], kChildrenKey, NSLocalizedString(@"General", @"general scope menu label"), kBundleNameKey, nil]]; // Init all needed menus inputGeneralScopePopUpMenu = [[NSMenu alloc] initWithTitle:@""]; @@ -331,13 +336,16 @@ // Store pending changes in Query [[self window] makeFirstResponder:nameTextField]; + NSIndexPath *currentIndexPath = nil; + currentIndexPath = [commandBundleTreeController selectionIndexPath]; + // Duplicate a selected Bundle if sender == self if (sender == self) { NSDictionary *currentDict = [[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject]; bundle = [NSMutableDictionary dictionaryWithDictionary:currentDict]; - NSString *bundleFileName = [bundle objectForKey:@"bundleName"]; - NSString *newFileName = [NSString stringWithFormat:@"%@_Copy", [bundle objectForKey:@"bundleName"]]; + NSString *bundleFileName = [bundle objectForKey:kBundleNameKey]; + NSString *newFileName = [NSString stringWithFormat:@"%@_Copy", [bundle objectForKey:kBundleNameKey]]; NSString *possibleExisitingBundleFilePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, bundleFileName, SPUserBundleFileExtension]; NSString *newBundleFilePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, newFileName, SPUserBundleFileExtension]; @@ -373,31 +381,81 @@ return; } - [bundle setObject:newFileName forKey:@"bundleName"]; + [bundle setObject:newFileName forKey:kBundleNameKey]; } // Add a new Bundle else { - bundle = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"New Bundle", @"New Name", @"", SPBundleScopeGeneral, nil] - forKeys:[NSArray arrayWithObjects:@"bundleName", SPBundleFileNameKey, SPBundleFileCommandKey, SPBundleFileScopeKey, nil]]; - } - if ([commandsOutlineView numberOfSelectedRows] > 0) { - insertIndex = [[commandsOutlineView selectedRowIndexes] lastIndex]+1; - [commandBundleArray insertObject:bundle atIndex:insertIndex]; - } - else { - [commandBundleArray addObject:bundle]; - insertIndex = [commandBundleArray count] - 1; + + NSString *category = nil; + NSString *scope = nil; + BOOL lastIndexWasAlreadyFixed = NO; + id currentObject = [[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject]; + + // If selected item is one of the main scopes go one item deeper + if([currentIndexPath length] == 2) { + NSUInteger *newPath[3]; + [currentIndexPath getIndexes:&newPath]; + newPath[2] = 0; + currentIndexPath = [NSIndexPath indexPathWithIndexes:newPath length:3]; + lastIndexWasAlreadyFixed = YES; + } + // If selected item is a category go one item deeper + else if([currentIndexPath length] == 3 && [currentObject objectForKey:kChildrenKey]) { + NSUInteger *newPath[4]; + [currentIndexPath getIndexes:&newPath]; + newPath[3] = 0; + currentIndexPath = [NSIndexPath indexPathWithIndexes:newPath length:4]; + lastIndexWasAlreadyFixed = YES; + category = [currentObject objectForKey:kBundleNameKey]; + } + + NSUInteger *currentPath[[currentIndexPath length]]; + [currentIndexPath getIndexes:¤tPath]; + + // Last index plus 1 to insert bundle under the current selection + if(!lastIndexWasAlreadyFixed) { + currentPath[[currentIndexPath length]-1] = (NSUInteger)currentPath[[currentIndexPath length]-1] + 1; + currentIndexPath = [NSIndexPath indexPathWithIndexes:currentPath length:[currentIndexPath length]]; + } + + // Set current scope + switch((NSUInteger)currentPath[1]) { + case 0: + scope = SPBundleScopeInputField; + break; + case 1: + scope = SPBundleScopeDataTable; + break; + case 2: + scope = SPBundleScopeGeneral; + break; + default: + scope = SPBundleScopeGeneral; + } + + // Get current category + if([currentIndexPath length] > 2 && category == nil) { + category = [[[[[commandsOutlineView parentForItem:[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]]] representedObject] objectForKey:kChildrenKey] objectAtIndex:0] objectForKey:SPBundleFileCategoryKey]; + } + if(category == nil) category = @""; + + bundle = [NSMutableDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"New Bundle", @"New Name", @"", scope, category, nil] + forKeys:[NSArray arrayWithObjects:kBundleNameKey, SPBundleFileNameKey, SPBundleFileCommandKey, SPBundleFileScopeKey, SPBundleFileCategoryKey, nil]]; } + if(![touchedBundleArray containsObject:[bundle objectForKey:kBundleNameKey]]) + [touchedBundleArray addObject:[bundle objectForKey:kBundleNameKey]]; + + [commandBundleTreeController insertObject:bundle atArrangedObjectIndexPath:currentIndexPath]; + [commandBundleTreeController rearrangeObjects]; [commandsOutlineView reloadData]; - [commandsOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:insertIndex] byExtendingSelection:NO]; - [commandsOutlineView scrollRowToVisible:[commandsOutlineView selectedRow]]; - [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] > 0)]; + [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] == 1 && ![[[commandBundleTreeController selectedObjects] objectAtIndex:0] objectForKey:kChildrenKey])]; + [addButton setEnabled:([[commandBundleTreeController selectionIndexPath] length] > 1)]; [self _updateInputPopupButton]; @@ -407,11 +465,11 @@ - (IBAction)removeCommandBundle:(id)sender { - NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Remove selected Bundles?", @"remove selected bundles message") + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Remove selected Bundle?", @"remove selected bundle message") defaultButton:NSLocalizedString(@"Remove", @"remove button") alternateButton:NSLocalizedString(@"Cancel", @"cancel button") otherButton:nil - informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to move all selected Bundles to the Trash and remove them respectively?", @"move to trash and remove resp all selected bundles informative message")]; + informativeTextWithFormat:NSLocalizedString(@"Are you sure you want to move the selected Bundle to the Trash and remove them respectively?", @"move to trash and remove resp the selected bundle informative message")]; [alert setAlertStyle:NSCriticalAlertStyle]; @@ -432,7 +490,7 @@ if([commandsOutlineView numberOfSelectedRows] != 1) return; [[NSWorkspace sharedWorkspace] selectFile:[NSString stringWithFormat:@"%@/%@.%@/%@", - bundlePath, [[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:@"bundleName"], SPUserBundleFileExtension, SPBundleFileName] inFileViewerRootedAtPath:nil]; + bundlePath, [[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:kBundleNameKey], SPUserBundleFileExtension, SPBundleFileName] inFileViewerRootedAtPath:nil]; } @@ -447,7 +505,7 @@ [panel setCanSelectHiddenExtension:YES]; [panel setCanCreateDirectories:YES]; - [panel beginSheetForDirectory:nil file:[[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:@"bundleName"] modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"saveBundle"]; + [panel beginSheetForDirectory:nil file:[[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:kBundleNameKey] modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:@"saveBundle"]; } - (IBAction)showHelp:(id)sender @@ -476,9 +534,9 @@ // Re-init commandBundleArray [commandBundleArray removeAllObjects]; - [[[commandBundleTree objectForKey:@"children"] objectAtIndex:0] setObject:[NSMutableArray array] forKey:@"children"]; - [[[commandBundleTree objectForKey:@"children"] objectAtIndex:1] setObject:[NSMutableArray array] forKey:@"children"]; - [[[commandBundleTree objectForKey:@"children"] objectAtIndex:2] setObject:[NSMutableArray array] forKey:@"children"]; + [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:0] setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:1] setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:2] setObject:[NSMutableArray array] forKey:kChildrenKey]; [commandsOutlineView reloadData]; // Load all installed bundle items @@ -508,73 +566,73 @@ { NSMutableDictionary *bundleCommand = [NSMutableDictionary dictionary]; [bundleCommand addEntriesFromDictionary:cmdData]; - [bundleCommand setObject:[bundle stringByDeletingPathExtension] forKey:@"bundleName"]; + [bundleCommand setObject:[bundle stringByDeletingPathExtension] forKey:kBundleNameKey]; [commandBundleArray addObject:bundleCommand]; if([[cmdData objectForKey:SPBundleFileScopeKey] isEqualToString:SPBundleScopeInputField]) { if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) { BOOL catExists = NO; - id children = [[[commandBundleTree objectForKey:@"children"] objectAtIndex:0] objectForKey:@"children"]; + id children = [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:0] objectForKey:kChildrenKey]; for(id child in children) { - if([child isKindOfClass:[NSDictionary class]] && [child objectForKey:@"children"] && [[child objectForKey:@"bundleName"] isEqualToString:[cmdData objectForKey:SPBundleFileCategoryKey]]) { - [[child objectForKey:@"children"] addObject:bundleCommand]; + if([child isKindOfClass:[NSDictionary class]] && [child objectForKey:kChildrenKey] && [[child objectForKey:kBundleNameKey] isEqualToString:[cmdData objectForKey:SPBundleFileCategoryKey]]) { + [[child objectForKey:kChildrenKey] addObject:bundleCommand]; catExists = YES; break; } } if(!catExists) { NSMutableDictionary *aDict = [NSMutableDictionary dictionary]; - [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:@"bundleName"]; - [aDict setObject:[NSMutableArray array] forKey:@"children"]; - [[aDict objectForKey:@"children"] addObject:bundleCommand]; - [[[[commandBundleTree objectForKey:@"children"] objectAtIndex:0] objectForKey:@"children"] addObject:aDict]; + [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:kBundleNameKey]; + [aDict setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[aDict objectForKey:kChildrenKey] addObject:bundleCommand]; + [[[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:0] objectForKey:kChildrenKey] addObject:aDict]; } } else { - [[[[commandBundleTree objectForKey:@"children"] objectAtIndex:0] objectForKey:@"children"] addObject:bundleCommand]; + [[[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:0] objectForKey:kChildrenKey] addObject:bundleCommand]; } } else if([[cmdData objectForKey:SPBundleFileScopeKey] isEqualToString:SPBundleScopeDataTable]) { if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) { BOOL catExists = NO; - id children = [[[commandBundleTree objectForKey:@"children"] objectAtIndex:1] objectForKey:@"children"]; + id children = [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:1] objectForKey:kChildrenKey]; for(id child in children) { - if([child isKindOfClass:[NSDictionary class]] && [child objectForKey:@"children"] && [[child objectForKey:@"bundleName"] isEqualToString:[cmdData objectForKey:SPBundleFileCategoryKey]]) { - [[child objectForKey:@"children"] addObject:bundleCommand]; + if([child isKindOfClass:[NSDictionary class]] && [child objectForKey:kChildrenKey] && [[child objectForKey:kBundleNameKey] isEqualToString:[cmdData objectForKey:SPBundleFileCategoryKey]]) { + [[child objectForKey:kChildrenKey] addObject:bundleCommand]; catExists = YES; break; } } if(!catExists) { NSMutableDictionary *aDict = [NSMutableDictionary dictionary]; - [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:@"bundleName"]; - [aDict setObject:[NSMutableArray array] forKey:@"children"]; - [[aDict objectForKey:@"children"] addObject:bundleCommand]; - [[[[commandBundleTree objectForKey:@"children"] objectAtIndex:1] objectForKey:@"children"] addObject:aDict]; + [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:kBundleNameKey]; + [aDict setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[aDict objectForKey:kChildrenKey] addObject:bundleCommand]; + [[[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:1] objectForKey:kChildrenKey] addObject:aDict]; } } else { - [[[[commandBundleTree objectForKey:@"children"] objectAtIndex:1] objectForKey:@"children"] addObject:bundleCommand]; + [[[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:1] objectForKey:kChildrenKey] addObject:bundleCommand]; } } else if([[cmdData objectForKey:SPBundleFileScopeKey] isEqualToString:SPBundleScopeGeneral]) { if([cmdData objectForKey:SPBundleFileCategoryKey] && [[cmdData objectForKey:SPBundleFileCategoryKey] length]) { BOOL catExists = NO; - id children = [[[commandBundleTree objectForKey:@"children"] objectAtIndex:2] objectForKey:@"children"]; + id children = [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:2] objectForKey:kChildrenKey]; for(id child in children) { - if([child isKindOfClass:[NSDictionary class]] && [child objectForKey:@"children"] && [[child objectForKey:@"bundleName"] isEqualToString:[cmdData objectForKey:SPBundleFileCategoryKey]]) { - [[child objectForKey:@"children"] addObject:bundleCommand]; + if([child isKindOfClass:[NSDictionary class]] && [child objectForKey:kChildrenKey] && [[child objectForKey:kBundleNameKey] isEqualToString:[cmdData objectForKey:SPBundleFileCategoryKey]]) { + [[child objectForKey:kChildrenKey] addObject:bundleCommand]; catExists = YES; break; } } if(!catExists) { NSMutableDictionary *aDict = [NSMutableDictionary dictionary]; - [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:@"bundleName"]; - [aDict setObject:[NSMutableArray array] forKey:@"children"]; - [[aDict objectForKey:@"children"] addObject:bundleCommand]; - [[[[commandBundleTree objectForKey:@"children"] objectAtIndex:2] objectForKey:@"children"] addObject:aDict]; + [aDict setObject:[cmdData objectForKey:SPBundleFileCategoryKey] forKey:kBundleNameKey]; + [aDict setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[aDict objectForKey:kChildrenKey] addObject:bundleCommand]; + [[[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:2] objectForKey:kChildrenKey] addObject:aDict]; } } else { - [[[[commandBundleTree objectForKey:@"children"] objectAtIndex:2] objectForKey:@"children"] addObject:bundleCommand]; + [[[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:2] objectForKey:kChildrenKey] addObject:bundleCommand]; } } } @@ -584,7 +642,8 @@ } } - [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] > 0)]; + [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] == 1 && ![[[commandBundleTreeController selectedObjects] objectAtIndex:0] objectForKey:kChildrenKey])]; + [addButton setEnabled:([[commandBundleTreeController selectionIndexPath] length] > 1)]; [commandBundleTreeController setContent:commandBundleTree]; [commandBundleTreeController rearrangeObjects]; @@ -599,24 +658,43 @@ // Commit all pending edits if([commandBundleTreeController commitEditing]) { + // Get all Bundles out of commandBundleTree which were touched + NSMutableArray *allBundles = [NSMutableArray array]; + for(NSInteger k = 0; k < [[commandBundleTree objectForKey:kChildrenKey] count]; k++) { + for(id item in [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:k] objectForKey:kChildrenKey]) { + if([item objectForKey:kChildrenKey]) { + for(id b in [item objectForKey:kChildrenKey]) { + if([touchedBundleArray containsObject:[b objectForKey:kBundleNameKey]]) { + [allBundles addObject:b]; + } + } + } + else { + if([touchedBundleArray containsObject:[item objectForKey:kBundleNameKey]]) { + [allBundles addObject:item]; + } + } + } + } + // Make the bundleNames unique since they represent folder names NSMutableDictionary *allNames = [NSMutableDictionary dictionary]; NSInteger idx = 0; - for(id item in commandBundleArray) { - if([allNames objectForKey:[item objectForKey:@"bundleName"]]) { - NSString *newName = [NSString stringWithFormat:@"%@_%ld", [item objectForKey:@"bundleName"], (NSUInteger)(random() % 35000)]; - [[commandBundleArray objectAtIndex:idx] setObject:newName forKey:@"bundleName"]; + for(id item in allBundles) { + if([allNames objectForKey:[item objectForKey:kBundleNameKey]]) { + NSString *newName = [NSString stringWithFormat:@"%@_%ld", [item objectForKey:kBundleNameKey], (NSUInteger)(random() % 35000)]; + [[allBundles objectAtIndex:idx] setObject:newName forKey:kBundleNameKey]; } else { - [allNames setObject:@"" forKey:[item objectForKey:@"bundleName"]]; + [allNames setObject:@"" forKey:[item objectForKey:kBundleNameKey]]; } idx++; } BOOL closeMe = YES; - for(id item in commandBundleArray) { + for(id item in allBundles) { if(![self saveBundle:item atPath:nil]) { closeMe = NO; - NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while saving “%@”.", @"error while saving “%@”"), [item objectForKey:@"bundleName"]] + NSAlert *alert = [NSAlert alertWithMessageText:[NSString stringWithFormat:NSLocalizedString(@"Error while saving “%@”.", @"error while saving “%@”"), [item objectForKey:kBundleNameKey]] defaultButton:NSLocalizedString(@"OK", @"OK button") alternateButton:nil otherButton:nil @@ -644,12 +722,12 @@ // If passed aPath is nil construct the path from bundle's bundleName. // aPath is mainly used for dragging a bundle from table view. if(aPath == nil) { - if(![bundle objectForKey:@"bundleName"] || ![[bundle objectForKey:@"bundleName"] length]) { + if(![bundle objectForKey:kBundleNameKey] || ![[bundle objectForKey:kBundleNameKey] length]) { return NO; } if(!bundlePath) bundlePath = [[[NSFileManager defaultManager] applicationSupportDirectoryForSubDirectory:SPBundleSupportFolder createIfNotExists:YES error:nil] retain]; - aPath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, [bundle objectForKey:@"bundleName"], SPUserBundleFileExtension]; + aPath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, [bundle objectForKey:kBundleNameKey], SPUserBundleFileExtension]; } // Create spBundle folder if it doesn't exist @@ -670,7 +748,7 @@ // Remove unnecessary keys [saveDict removeObjectsForKeys:[NSArray arrayWithObjects: - @"bundleName", + kBundleNameKey, nil]]; // Remove a given old command.plist file @@ -698,11 +776,12 @@ NSArray *selObjects = [commandBundleTreeController selectedObjects]; NSArray *selIndexPaths = [commandBundleTreeController selectionIndexPaths]; + BOOL deletionSuccessfully = YES; for(id obj in selObjects) { // Move already installed Bundles to Trash - NSString *bundleName = [obj objectForKey:@"bundleName"]; + NSString *bundleName = [obj objectForKey:kBundleNameKey]; NSString *thePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, bundleName, SPUserBundleFileExtension]; if([[NSFileManager defaultManager] fileExistsAtPath:thePath isDirectory:nil]) { NSError *error = nil; @@ -721,24 +800,33 @@ [alert setAlertStyle:NSCriticalAlertStyle]; [alert runModal]; + deletionSuccessfully = NO; break; } + [commandsOutlineView reloadData]; } } - [self reloadBundles:self]; + if(deletionSuccessfully) { + [commandBundleTreeController removeObjectsAtArrangedObjectIndexPaths:selIndexPaths]; + [commandBundleTreeController rearrangeObjects]; + } else { + [self reloadBundles:self]; + } // Set focus to table view to avoid an unstable state [[self window] makeFirstResponder:commandsOutlineView]; - [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] > 0)]; + [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] == 1 && ![[[commandBundleTreeController selectedObjects] objectAtIndex:0] objectForKey:kChildrenKey])]; + [addButton setEnabled:([[commandBundleTreeController selectionIndexPath] length] > 1)]; + } } else if([contextInfo isEqualToString:@"saveBundle"]) { if (returnCode == NSOKButton) { - id aBundle = [commandBundleArray objectAtIndex:[commandsOutlineView selectedRow]]; + id aBundle = [[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject]; - NSString *bundleFileName = [aBundle objectForKey:@"bundleName"]; + NSString *bundleFileName = [aBundle objectForKey:kBundleNameKey]; NSString *possibleExisitingBundleFilePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, bundleFileName, SPUserBundleFileExtension]; NSString *savePath = [sheet filename]; @@ -788,9 +876,10 @@ { // Clear commandBundleArray if window will close to save memory [commandBundleArray removeAllObjects]; - [[[commandBundleTree objectForKey:@"children"] objectAtIndex:0] setObject:[NSMutableArray array] forKey:@"children"]; - [[[commandBundleTree objectForKey:@"children"] objectAtIndex:1] setObject:[NSMutableArray array] forKey:@"children"]; - [[[commandBundleTree objectForKey:@"children"] objectAtIndex:2] setObject:[NSMutableArray array] forKey:@"children"]; + [touchedBundleArray removeAllObjects]; + [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:0] setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:1] setObject:[NSMutableArray array] forKey:kChildrenKey]; + [[[commandBundleTree objectForKey:kChildrenKey] objectAtIndex:2] setObject:[NSMutableArray array] forKey:kChildrenKey]; [commandsOutlineView reloadData]; // Remove temporary drag file if any @@ -810,7 +899,7 @@ - (void)shortcutRecorder:(SRRecorderControl *)aRecorder keyComboDidChange:(KeyCombo)newKeyCombo { - if([commandsOutlineView selectedRow] < 0 || [commandsOutlineView selectedRow] > [commandBundleArray count]) return; + if([commandsOutlineView selectedRow] < 0) return; // Transform KeyCombo struct to KeyBinding.dict format for NSMenuItems NSMutableString *keyEq = [NSMutableString string]; @@ -839,7 +928,7 @@ - (BOOL)outlineView:(id)outlineView isItemExpandable:(id)item { - if([item isKindOfClass:[NSDictionary class]] && [item objectForKey:@"children"]) + if([item isKindOfClass:[NSDictionary class]] && [item objectForKey:kChildrenKey]) return YES; return NO; @@ -852,8 +941,8 @@ item = commandBundleTree; if([item isKindOfClass:[NSDictionary class]]) - if([item objectForKey:@"children"]) - return [[item objectForKey:@"children"] count]; + if([item objectForKey:kChildrenKey]) + return [[item objectForKey:kChildrenKey] count]; else return [item count]; @@ -867,14 +956,20 @@ { if(item && [item respondsToSelector:@selector(objectForKey:)]) - return [item objectForKey:@"bundleName"]; + return [item objectForKey:kBundleNameKey]; return @""; } - (BOOL)outlineView:outlineView isGroupItem:(id)item { - return (![item isLeaf]); + return ([[item representedObject] isKindOfClass:[NSDictionary class]] && [[item representedObject] objectForKey:kChildrenKey]); +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldCollapseItem:(id)item +{ + if(![outlineView parentForItem:item]) return NO; + return YES; } - (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item @@ -889,77 +984,83 @@ - (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item { - return ([item isLeaf]); + if (![self outlineView:outlineView isGroupItem:item]) { + isTableCellEditing = YES; + return YES; + } + isTableCellEditing = NO; + return NO; } - (void)outlineViewSelectionDidChange:(NSNotification *)aNotification { + if([aNotification object] != commandsOutlineView) return; + if(oldBundleName) [oldBundleName release], oldBundleName = nil; + if(![[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:kChildrenKey]) + oldBundleName = [[[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:kBundleNameKey] retain]; + else + if(oldBundleName) [oldBundleName release], oldBundleName = nil; + + if(oldBundleName != nil && ![touchedBundleArray containsObject:oldBundleName]) + [touchedBundleArray addObject:oldBundleName]; [self _updateInputPopupButton]; } -// - (void)outlineView:(NSOutlineView *)outlineView didClickTableColumn:(NSTableColumn *)tableColumn -// { -// if(outlineView == outlineSchema2) { -// [schemaStatusSplitView setPosition:1000 ofDividerAtIndex:0]; -// [schema12SplitView setPosition:0 ofDividerAtIndex:0]; -// } -// } -// -// - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard -// { -// // Provide data for our custom type, and simple NSStrings. -// [pboard declareTypes:[NSArray arrayWithObjects:DragTableDataFromNavigatorPboardType, DragFromNavigatorPboardType, NSStringPboardType, nil] owner:self]; -// -// // Collect the actual schema paths without leading connection ID -// NSMutableArray *draggedItems = [NSMutableArray array]; -// for(id item in items) { -// id parentObject = [outlineView parentForItem:item] ? [outlineView parentForItem:item] : schemaData; -// if(!parentObject) return NO; -// id parentKeys = [parentObject allKeysForObject:item]; -// if(parentKeys && [parentKeys count] == 1) -// [draggedItems addObject:[[[parentKeys objectAtIndex:0] description] stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:@"^.*?%@", SPUniqueSchemaDelimiter] withString:@""]]; -// } -// -// // Drag the array with schema paths -// NSMutableData *arraydata = [[[NSMutableData alloc] init] autorelease]; -// NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:arraydata] autorelease]; -// [archiver encodeObject:draggedItems forKey:@"itemdata"]; -// [archiver finishEncoding]; -// [pboard setData:arraydata forType:DragFromNavigatorPboardType]; -// -// if([draggedItems count] == 1) { -// NSArray *pathComponents = [[draggedItems objectAtIndex:0] componentsSeparatedByString:SPUniqueSchemaDelimiter]; -// // Is a table? -// if([pathComponents count] == 2) { -// [pboard setString:[NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ SELECT * FROM %@", -// [[pathComponents lastObject] backtickQuotedString], -// [pathComponents componentsJoinedByPeriodAndBacktickQuoted] -// ] forType:DragTableDataFromNavigatorPboardType]; -// } -// } -// // For external destinations provide a comma separated string -// NSMutableString *dragString = [NSMutableString string]; -// for(id item in draggedItems) { -// if([dragString length]) [dragString appendString:@", "]; -// [dragString appendString:[[item componentsSeparatedByString:SPUniqueSchemaDelimiter] componentsJoinedByPeriodAndBacktickQuotedAndIgnoreFirst]]; -// } -// -// if(![dragString length]) return NO; -// -// [pboard setString:dragString forType:NSStringPboardType]; -// return YES; -// } +- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard +{ + if([commandsOutlineView numberOfSelectedRows] != 1 || [items count] != 1 || + ![[items objectAtIndex:0] isLeaf]) return NO; + // Remove old temporary drag file if any + if(draggedFilePath) { + [[NSFileManager defaultManager] removeItemAtPath:draggedFilePath error:nil]; + [draggedFilePath release]; + draggedFilePath = nil; + } -#pragma mark - -#pragma mark TableView data source and delegate + NSImage *dragImage; + NSPoint dragPosition; -/** - * Returns the number of query commandBundleArray. - */ + NSDictionary *bundleDict = [[items objectAtIndex:0] representedObject]; + NSString *bundleFileName = [bundleDict objectForKey:kBundleNameKey]; + NSString *possibleExisitingBundleFilePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, bundleFileName, SPUserBundleFileExtension]; + + draggedFilePath = [[NSString stringWithFormat:@"/tmp/%@.%@", bundleFileName, SPUserBundleFileExtension] retain]; + + BOOL isDir; + + // Copy possible existing bundle with content + if([[NSFileManager defaultManager] fileExistsAtPath:possibleExisitingBundleFilePath isDirectory:&isDir] && isDir) { + if(![[NSFileManager defaultManager] copyItemAtPath:possibleExisitingBundleFilePath toPath:draggedFilePath error:nil]) + return NO; + } + + // Write temporary bundle data to disk but do not save the dict to Bundles folder + if(![self saveBundle:bundleDict atPath:draggedFilePath]) return NO; + + // Write data to the pasteboard + NSArray *fileList = [NSArray arrayWithObjects:draggedFilePath, nil]; + // NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil]; + [pboard setPropertyList:fileList forType:NSFilenamesPboardType]; + + // Start the drag operation + dragImage = [[NSWorkspace sharedWorkspace] iconForFile:draggedFilePath]; + dragPosition = [[[self window] contentView] convertPoint:[[NSApp currentEvent] locationInWindow] fromView:nil]; + dragPosition.x -= 32; + dragPosition.y -= 32; + [[self window] dragImage:dragImage at:dragPosition offset:NSZeroSize + event:[NSApp currentEvent] pasteboard:pboard source:[self window] slideBack:YES]; + + return YES; +} + + +#pragma mark - +#pragma mark TableView delegate /* * Save spBundle name if inline edited (suppress empty names) and check for renaming and / in the name @@ -973,7 +1074,7 @@ BOOL isValid = YES; - if(newBundleName && [newBundleName length] && ![newBundleName rangeOfString:@"/"].length) { + if(oldBundleName && newBundleName && [newBundleName length] && ![newBundleName rangeOfString:@"/"].length) { NSString *oldName = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, oldBundleName, SPUserBundleFileExtension]; NSString *newName = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, newBundleName, SPUserBundleFileExtension]; @@ -996,14 +1097,20 @@ isValid = NO; } + // If not valid reset name to the old one if(!isValid) { - if(!oldBundleName) oldBundleName = @"New Name"; - [[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] setObject:oldBundleName forKey:@"bundleName"]; + [[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] setObject:oldBundleName forKey:kBundleNameKey]; } + [commandBundleTreeController rearrangeObjects]; [commandsOutlineView reloadData]; + if(oldBundleName) [oldBundleName release], oldBundleName = nil; + oldBundleName = [[[[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject] objectForKey:kBundleNameKey] retain]; + if(oldBundleName != nil && ![touchedBundleArray containsObject:oldBundleName]) + [touchedBundleArray addObject:oldBundleName]; + isTableCellEditing = NO; } @@ -1022,17 +1129,12 @@ if ( (action == @selector(duplicateCommandBundle:)) || (action == @selector(revealCommandBundleInFinder:)) || (action == @selector(saveBundle:)) + || (action == @selector(removeCommandBundle:)) ) { // Allow to record short-cuts used by the Bundle Editor if([[NSApp mainWindow] firstResponder] == keyEquivalentField) return NO; - return ([[commandBundleTreeController selectedObjects] count] == 1); - } - else if ( (action == @selector(removeCommandBundle:)) ) - { - // Allow to record short-cuts used by the Bundle Editor - if([[NSApp mainWindow] firstResponder] == keyEquivalentField) return NO; - return ([[commandBundleTreeController selectedObjects] count] > 0); + return ([[commandBundleTreeController selectedObjects] count] == 1 && ![[[commandBundleTreeController selectedObjects] objectAtIndex:0] objectForKey:kChildrenKey]); } return YES; @@ -1070,7 +1172,7 @@ NSPoint dragPosition; NSDictionary *bundleDict = [commandsOutlineView itemAtRow:[rows firstIndex]]; - NSString *bundleFileName = [bundleDict objectForKey:@"bundleName"]; + NSString *bundleFileName = [bundleDict objectForKey:kBundleNameKey]; NSString *possibleExisitingBundleFilePath = [NSString stringWithFormat:@"%@/%@.%@", bundlePath, bundleFileName, SPUserBundleFileExtension]; draggedFilePath = [[NSString stringWithFormat:@"/tmp/%@.%@", bundleFileName, SPUserBundleFileExtension] retain]; @@ -1202,7 +1304,7 @@ NSInteger anIndex; - if([commandsOutlineView selectedRow] < 0 || [commandsOutlineView selectedRow] > [commandBundleArray count]) return; + if([commandsOutlineView selectedRow] < 0) return; NSDictionary *currentDict = [[commandsOutlineView itemAtRow:[commandsOutlineView selectedRow]] representedObject]; @@ -1288,6 +1390,9 @@ [fallbackLabelField setHidden:YES]; } + [removeButton setEnabled:([[commandBundleTreeController selectedObjects] count] == 1 && ![[[commandBundleTreeController selectedObjects] objectAtIndex:0] objectForKey:kChildrenKey])]; + [addButton setEnabled:([[commandBundleTreeController selectionIndexPath] length] > 1)]; + } diff --git a/Source/SPOutlineView.m b/Source/SPOutlineView.m index f60807f3..1cf5055a 100644 --- a/Source/SPOutlineView.m +++ b/Source/SPOutlineView.m @@ -26,6 +26,55 @@ @implementation SPOutlineView +- (id)init +{ + if(self = [super init]){ + ; + } + return self; +} + +/** + * Right-click at row will select that row before ordering out the contextual menu + * if not more than one row is selected. + */ +- (NSMenu *)menuForEvent:(NSEvent *)event +{ + + // Check for SPBundleEditorController if right-click on expamdable item, then suppress context menu + if ([[[[self delegate] class] description] isEqualToString:@"SPBundleEditorController"]) { + + // If more than one row is selected only returns the default contextual menu + if ([self numberOfSelectedRows] > 1) return nil; + + // Right-click at a row will select that row before ordering out the context menu + NSInteger row = [self rowAtPoint:[self convertPoint:[event locationInWindow] fromView:nil]]; + + if (row >= 0 && row < [self numberOfRows]) { + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; + [[self window] makeFirstResponder:self]; + } + + if (![[self itemAtRow:[self selectedRow]] isLeaf]) + return nil; + return [self menu]; + } + + + // If more than one row is selected only returns the default contextual menu + if ([self numberOfSelectedRows] > 1) return [self menu]; + + // Right-click at a row will select that row before ordering out the context menu + NSInteger row = [self rowAtPoint:[self convertPoint:[event locationInWindow] fromView:nil]]; + + if (row >= 0 && row < [self numberOfRows]) { + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; + [[self window] makeFirstResponder:self]; + } + + return [self menu]; +} + - (BOOL)acceptsFirstResponder { return YES; @@ -33,7 +82,16 @@ - (void)keyDown:(NSEvent *)theEvent { + if ([self numberOfSelectedRows] == 1 && ([theEvent keyCode] == 36 || [theEvent keyCode] == 76)) { + if ([[[[self delegate] class] description] isEqualToString:@"SPBundleEditorController"]) { + if([[self delegate] respondsToSelector:@selector(outlineView:shouldEditTableColumn:item:)] && + [[self delegate] outlineView:self shouldEditTableColumn:[self tableColumnWithIdentifier:@"bundleName"] item:[self itemAtRow:[self selectedRow]]] + ) + [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; + else + return; + } [self editColumn:0 row:[self selectedRow] withEvent:nil select:YES]; } |