aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2010-11-25 09:00:02 +0000
committerBibiko <bibiko@eva.mpg.de>2010-11-25 09:00:02 +0000
commit6a4fab961e1efd1f8eb55aa2806f17cde027f36c (patch)
tree9e3c5776b20deaba488b031ab29a29954cfc4e7d /Source
parentf51f2b3d87a59a94d5bc16850debfec5128b50ed (diff)
downloadsequelpro-6a4fab961e1efd1f8eb55aa2806f17cde027f36c.tar.gz
sequelpro-6a4fab961e1efd1f8eb55aa2806f17cde027f36c.tar.bz2
sequelpro-6a4fab961e1efd1f8eb55aa2806f17cde027f36c.zip
• further work on Bundle Editor's outline view
Diffstat (limited to 'Source')
-rw-r--r--Source/SPBundleEditorController.h2
-rw-r--r--Source/SPBundleEditorController.m401
-rw-r--r--Source/SPOutlineView.m58
3 files changed, 313 insertions, 148 deletions
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:&currentPath];
+
+ // 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];
}