From 0253107558842a6ef1bacc28da2d012d95b826ad Mon Sep 17 00:00:00 2001 From: Sergii Stoian Date: Wed, 9 Jun 2004 15:15:56 +0000 Subject: [PATCH] See Documentatio/Changelog git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/projectcenter/branches/UNSTABLE_0_4@19489 72102866-910b-0410-8b05-ffd578937521 --- Documentation/ChangeLog | 28 +- Library/PCBuildPanel.h | 1 + Library/PCBuildPanel.m | 18 +- Library/PCEditor.m | 3 +- Library/PCFileManager.m | 15 +- Library/PCLaunchPanel.h | 1 + Library/PCLaunchPanel.m | 17 +- Library/PCLoadedFilesPanel.h | 1 + Library/PCLoadedFilesPanel.m | 45 +-- Library/PCProject.h | 16 +- Library/PCProject.m | 282 +++++++++-------- Library/PCProjectBrowser.h | 12 +- Library/PCProjectBrowser.m | 295 ++++++++++++------ Library/PCProjectEditor.m | 16 +- Library/PCProjectInspector.m | 4 +- Library/PCProjectLoadedFiles.m | 6 +- Library/PCProjectManager.h | 11 +- Library/PCProjectManager.m | 230 ++++++++------ Library/PCProjectWindow.m | 115 +++---- .../PCAppProject+Inspector.m | 2 +- Modules/ApplicationProject/PCAppProject.m | 17 +- Modules/BundleProject/PCBundleProject.m | 1 + .../RenaissanceProject/PCRenaissanceProject.m | 22 +- PCMenuController.h | 1 - PCMenuController.m | 39 ++- 25 files changed, 733 insertions(+), 465 deletions(-) diff --git a/Documentation/ChangeLog b/Documentation/ChangeLog index 4115dc3..8e7c7e8 100644 --- a/Documentation/ChangeLog +++ b/Documentation/ChangeLog @@ -1,3 +1,29 @@ +2004-06-09 Serg Stoyan + + * Library/PCProjectBrowser.[hm]: + (pathOfSelectedFile): renamed to pathToSelectedFile. + (nameOfSelectedCategory): implemented. Use it insetead PCProject's + -categoryForCategoryPath. + (pathToSelectedCategory): implemented. + (setPathForFile:category:): removed. + (reloadLastColumn): implemented. + + * Modules/ApplicationProject/PCAppProject.m: + (renameFile:toFile:): remove calling of PCProjectBrowser's + setPathForFile:category. + + * Modules/RenaissanceProject/ PCRenaissanceProject.m: + (renameFile:toFile:): ditto. + + * Library/PCLoadedFilesPanel.m: + * Library/PCBuildPanel.m: + * Library/PCLaunchPanel.m: + (activeProjectDidChange:): return if root project wasn't changed. + + * Library/PCProject.m: + (setProjectmanager:): don't set project components for subproject. + + 2004-06-02 Serg Stoyan * Library/PCProjectManager (openProjectAt:): get project name from @@ -10,7 +36,7 @@ * PCMenuController.m: disable "Tear-Off Editor Size" fields editing if Project Editor is not tear-off or Editor is not "ProjectCenter". Check only first arg of Editor value. - + 2004-06-01 Serg Stoyan * Finished on-the-fly applying "Tear-Off Panels" preferences. diff --git a/Library/PCBuildPanel.h b/Library/PCBuildPanel.h index 71498a5..0ca38c8 100644 --- a/Library/PCBuildPanel.h +++ b/Library/PCBuildPanel.h @@ -32,6 +32,7 @@ @interface PCBuildPanel : NSPanel { PCProjectManager *projectManager; + PCProject *currentProject; NSBox *contentBox; NSBox *emptyBox; } diff --git a/Library/PCBuildPanel.m b/Library/PCBuildPanel.m index a4a268c..c2d0854 100644 --- a/Library/PCBuildPanel.m +++ b/Library/PCBuildPanel.m @@ -121,22 +121,28 @@ - (void)activeProjectDidChange:(NSNotification *)aNotif { - PCProject *activeProject = [projectManager rootActiveProject]; + PCProject *rootProject = [projectManager rootActiveProject]; - [self setTitle: [NSString stringWithFormat: - @"%@ - Project Build", [activeProject projectName]]]; + if (rootProject == currentProject) + { + return; + } + + currentProject = rootProject; PCLogInfo(self, @"activeProjectDidChange to: %@", - [activeProject projectName]); + [rootProject projectName]); - if (!activeProject) + if (!rootProject) { [contentBox setContentView:emptyBox]; } else { + [self setTitle: [NSString stringWithFormat: + @"%@ - Project Build", [rootProject projectName]]]; [contentBox - setContentView:[[activeProject projectBuilder] componentView]]; + setContentView:[[rootProject projectBuilder] componentView]]; } } diff --git a/Library/PCEditor.m b/Library/PCEditor.m index e72f244..730838e 100644 --- a/Library/PCEditor.m +++ b/Library/PCEditor.m @@ -543,10 +543,11 @@ - (BOOL)becomeFirstResponder { + NSLog(@"PCEditor: becomeFirstResponder"); [[NSNotificationCenter defaultCenter] postNotificationName:PCEditorDidBecomeActiveNotification object:self]; - + return YES; } diff --git a/Library/PCFileManager.m b/Library/PCFileManager.m index 962ccfb..794d61a 100644 --- a/Library/PCFileManager.m +++ b/Library/PCFileManager.m @@ -27,6 +27,7 @@ #include "PCFileCreator.h" #include "PCProjectManager.h" #include "PCProject.h" +#include "PCProjectBrowser.h" #include "PCServer.h" #include "PCLogController.h" @@ -362,12 +363,18 @@ static PCFileManager *_mgr = nil; { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; NSString *lastOpenDir = [ud objectForKey:@"LastOpenDirectory"]; + PCProject *project = [projectManager rootActiveProject]; + NSString *selectedCategory = nil; int retval; - PCProject *project = [projectManager activeProject]; [self _createAddFilesPanel]; - - [fileTypePopup selectItemWithTitle:[project selectedRootCategory]]; + selectedCategory = [[project projectBrowser] nameOfSelectedCategory]; + if ([selectedCategory isEqualToString:@"Subprojects"]) + { + [addFilesPanel setCanChooseFiles:NO]; + [addFilesPanel setCanChooseDirectories:YES]; + } + [fileTypePopup selectItemWithTitle:selectedCategory]; [self filesForAddPopupClicked:self]; @@ -382,7 +389,7 @@ static PCFileManager *_mgr = nil; if (retval == NSOKButton) { [ud setObject:[addFilesPanel directory] forKey:@"LastOpenDirectory"]; - return [[[addFilesPanel filenames] mutableCopy] autorelease]; + return [[addFilesPanel filenames] mutableCopy]; } return nil; diff --git a/Library/PCLaunchPanel.h b/Library/PCLaunchPanel.h index e5b3b4d..b2dfefc 100644 --- a/Library/PCLaunchPanel.h +++ b/Library/PCLaunchPanel.h @@ -32,6 +32,7 @@ @interface PCLaunchPanel : NSPanel { PCProjectManager *projectManager; + PCProject *currentProject; NSBox *contentBox; NSBox *emptyBox; } diff --git a/Library/PCLaunchPanel.m b/Library/PCLaunchPanel.m index c9107e8..cbfb2ae 100644 --- a/Library/PCLaunchPanel.m +++ b/Library/PCLaunchPanel.m @@ -121,19 +121,26 @@ - (void)activeProjectDidChange:(NSNotification *)aNotif { - PCProject *activeProject = [projectManager rootActiveProject]; + PCProject *rootProject = [projectManager rootActiveProject]; - [self setTitle: [NSString stringWithFormat: - @"%@ - Launch", [activeProject projectName]]]; + if (rootProject == currentProject) + { + return; + } - if (!activeProject) + currentProject = rootProject; + + if (!rootProject) { [contentBox setContentView:emptyBox]; } else { + [self setTitle: [NSString stringWithFormat: + @"%@ - Launch", [rootProject projectName]]]; + [contentBox - setContentView:[[activeProject projectLauncher] componentView]]; + setContentView:[[rootProject projectLauncher] componentView]]; } } diff --git a/Library/PCLoadedFilesPanel.h b/Library/PCLoadedFilesPanel.h index 6d08c0a..e9d0f2d 100644 --- a/Library/PCLoadedFilesPanel.h +++ b/Library/PCLoadedFilesPanel.h @@ -32,6 +32,7 @@ @interface PCLoadedFilesPanel : NSPanel { PCProjectManager *projectManager; + PCProject *currentProject; NSBox *contentBox; NSBox *emptyBox; } diff --git a/Library/PCLoadedFilesPanel.m b/Library/PCLoadedFilesPanel.m index 6f3c85d..68ea7aa 100644 --- a/Library/PCLoadedFilesPanel.m +++ b/Library/PCLoadedFilesPanel.m @@ -35,22 +35,21 @@ { PCProjectLoadedFiles *projectLoadedFiles = nil; PCProject *activeProject = nil; - + projectManager = aManager; activeProject = [projectManager rootActiveProject]; + currentProject = activeProject; projectLoadedFiles = [activeProject projectLoadedFiles]; + PCLogStatus(self, @"[init]"); + self = [super initWithContentRect: NSMakeRect (0, 300, 220, 322) styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask) backing: NSBackingStoreRetained defer: YES]; - [self setFloatingPanel:YES]; -/* self = [super initWithContentRect: NSMakeRect (0, 300, 220, 322) - styleMask: NSUtilityWindowMask - backing: NSBackingStoreRetained - defer: YES];*/ +// [self setFloatingPanel:YES]; [self setMinSize: NSMakeSize(120, 23)]; [self setFrameAutosaveName: @"LoadedFiles"]; [self setReleasedWhenClosed: NO]; @@ -89,7 +88,7 @@ - (void)dealloc { - NSLog (@"PCLoadedFilesPanel: dealloc"); + NSLog(@"PCLoadedFilesPanel: dealloc"); [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -112,36 +111,38 @@ - (void)close { - PCLogInfo(self, @"close: %@", [contentBox contentView]); - [contentBox setContentView:emptyBox]; - - PCLogInfo(self, @"close: %@", [contentBox contentView]); [super close]; } -/*- (BOOL)canBecomeKeyWindow -{ - // Panels controls doesn't receive mouse click if return NO - return YES; -}*/ - - (void)activeProjectDidChange:(NSNotification *)aNotif { - PCProject *activeProject = [projectManager rootActiveProject]; + PCProject *rootProject = [projectManager rootActiveProject]; - [self setTitle: [NSString stringWithFormat: - @"%@ - Loaded Files", [activeProject projectName]]]; + PCLogInfo(self, @"rootProject %@ currentProject %@", + [rootProject projectName], [currentProject projectName]); - if (!activeProject) + if (rootProject == currentProject) + { + return; + } + + PCLogInfo(self, @"1--- rootProject %@ currentProject %@", + [rootProject projectName], [currentProject projectName]); + + currentProject = rootProject; + + if (!rootProject) { [contentBox setContentView:emptyBox]; } else { + [self setTitle: [NSString stringWithFormat: + @"%@ - Loaded Files", [rootProject projectName]]]; [contentBox - setContentView:[[activeProject projectLoadedFiles] componentView]]; + setContentView:[[rootProject projectLoadedFiles] componentView]]; } } diff --git a/Library/PCProject.h b/Library/PCProject.h index b4e6bc5..92c116c 100644 --- a/Library/PCProject.h +++ b/Library/PCProject.h @@ -92,7 +92,7 @@ extern NSString *PCProjectDictDidSaveNotification; - (BOOL)close:(id)sender; - (void)dealloc; -- (BOOL)saveProjectWindowsAndPanels; // Not finished +- (BOOL)saveProjectWindowsAndPanels; // ============================================================================ // ==== Accessory methods @@ -111,11 +111,6 @@ extern NSString *PCProjectDictDidSaveNotification; - (void)setProjectName:(NSString *)aName; - (BOOL)isProjectChanged; -- (NSString *)selectedRootCategory; -- (NSString *)selectedRootCategoryKey; - -- (Class)principalClass; - // =========================================================================== // ==== Can be overriden // =========================================================================== @@ -178,7 +173,6 @@ extern NSString *PCProjectDictDidSaveNotification; - (NSString *)categoryForKey:(NSString *)key; - (BOOL)save; -- (BOOL)saveAt:(NSString *)projPath; - (BOOL)writeSpecFile; @@ -204,8 +198,9 @@ extern NSString *PCProjectDictDidSaveNotification; - (PCProject *)subprojectWithName:(NSString *)name; - (void)addSubproject:(PCProject *)aSubproject; -- (void)newSubprojectNamed:(NSString *)aName; -- (void)removeSubproject:(PCProject *)aSubproject; +- (void)addSubprojectWithName:(NSString *)name; +- (BOOL)removeSubproject:(PCProject *)aSubproject; +- (BOOL)removeSubprojectWithName:(NSString *)subprojectName; @end @@ -216,7 +211,8 @@ extern NSString *PCProjectDictDidSaveNotification; - (NSString *)rootCategoryForCategoryPath:(NSString *)categoryPath; - (NSString *)categoryForCategoryPath:(NSString *)categoryPath; -- (NSString *)keyForCategoryPath:(NSString *)kp; +- (NSString *)keyForRootCategoryInCategoryPath:(NSString *)categoryPath; +- (NSString *)keyForCategoryPath:(NSString *)categoryPath; @end diff --git a/Library/PCProject.m b/Library/PCProject.m index a1b01a4..9b0293f 100644 --- a/Library/PCProject.m +++ b/Library/PCProject.m @@ -99,19 +99,27 @@ NSString { projectManager = aManager; - if (!projectBrowser) + if (isSubproject) + { + return; + } + + if (!projectBrowser && !isSubproject) { projectBrowser = [[PCProjectBrowser alloc] initWithProject:self]; } - if (!projectLoadedFiles) + + if (!projectLoadedFiles && !isSubproject) { projectLoadedFiles = [[PCProjectLoadedFiles alloc] initWithProject:self]; } - if (!projectEditor) + + if (!projectEditor && !isSubproject) { projectEditor = [[PCProjectEditor alloc] initWithProject:self]; } - if (!projectWindow) + + if (!projectWindow && !isSubproject) { projectWindow = [[PCProjectWindow alloc] initWithProject:self]; } @@ -265,6 +273,10 @@ NSString [windows removeObjectForKey:@"LoadedFiles"]; } + // Set to project dict for case if project changed + // Don't notify about projectDict changes + [projectDict setObject:windows forKey:@"PC_WINDOWS"]; + // Now save it directly to PC.project file [projectFileDict setObject:windows forKey:@"PC_WINDOWS"]; [projectFileDict writeToFile:projectFile atomically:YES]; @@ -314,6 +326,11 @@ NSString return projectManager; } +- (PCProjectWindow *)projectWindow +{ + return projectWindow; +} + - (PCProjectBrowser *)projectBrowser { return projectBrowser; @@ -354,23 +371,6 @@ NSString return projectEditor; } -- (NSString *)selectedRootCategory -{ - NSString *_path = [[self projectBrowser] pathOfSelectedFile]; - - return [self categoryForCategoryPath:_path]; -} - -- (NSString *)selectedRootCategoryKey -{ - NSString *_path = [[self projectBrowser] pathOfSelectedFile]; - NSString *key = [self keyForCategoryPath:_path]; - - PCLogInfo(self, @"selected category: %@. key: %@", _path, key); - - return key; -} - - (void)setProjectDictObject:(id)object forKey:(NSString *)key { id currentObject = [projectDict objectForKey:key]; @@ -400,21 +400,11 @@ NSString return projectName; } -- (PCProjectWindow *)projectWindow -{ - return projectWindow; -} - - (BOOL)isProjectChanged { return [projectWindow isDocumentEdited]; } -- (Class)principalClass -{ - return [self class]; -} - // ============================================================================ // ==== Can be overriden // ============================================================================ @@ -523,17 +513,14 @@ NSString return projectPath; } -//- (NSArray *)complementaryTypesForType:(NSString *)type - (NSString *)complementaryTypeForType:(NSString *)type { if ([type isEqualToString:@"m"] || [type isEqualToString:@"c"]) { -// return [NSArray arrayWithObjects:@"h",nil]; return [NSString stringWithString:@"h"]; } else if ([type isEqualToString:@"h"]) { -// return [NSArray arrayWithObjects:@"m",@"c",nil]; return [NSString stringWithString:@"m"]; } @@ -617,10 +604,11 @@ NSString complementaryTypeForType:[[files objectAtIndex:0] pathExtension]]; if (complementaryType) { - complementaryKey = - [self categoryKeyForFileType:complementaryType]; + complementaryKey = [self categoryKeyForFileType:complementaryType]; complementaryDir = [self dirForCategoryKey:complementaryKey]; } + + PCLogInfo(self, @"{%@} {addAndCopyFiles} %@", projectName, fileList); // Validate files while ((file = [fileEnum nextObject])) @@ -635,13 +623,16 @@ NSString compFile = [[file stringByDeletingPathExtension] stringByAppendingPathExtension:complementaryType]; - if ([[NSFileManager defaultManager] fileExistsAtPath:compFile]) + if ([[NSFileManager defaultManager] fileExistsAtPath:compFile] + && [self doesAcceptFile:compFile forKey:complementaryKey]) { [complementaryFiles addObject:compFile]; } } } + PCLogInfo(self, @"{addAndCopyFiles} %@", fileList); + // Copy files if (![key isEqualToString:PCLibraries]) // Don't copy libraries { @@ -690,11 +681,7 @@ NSString [projectFiles addObject:pFile]; } - [projectDict setObject:projectFiles forKey:type]; - - [[NSNotificationCenter defaultCenter] - postNotificationName:PCProjectDictDidChangeNotification - object:self]; + [self setProjectDictObject:projectFiles forKey:type]; } - (BOOL)removeFiles:(NSArray *)files forKey:(NSString *)key @@ -711,7 +698,7 @@ NSString { if ([key isEqualToString:PCSubprojects]) { - [self removeSubproject:[self subprojectWithName:file]]; + [self removeSubprojectWithName:file]; } [projectFiles removeObject:file]; @@ -720,33 +707,34 @@ NSString [projectEditor closeEditorForFile:filePath]; } - [projectDict setObject:projectFiles forKey:key]; - - [[NSNotificationCenter defaultCenter] - postNotificationName:PCProjectDictDidChangeNotification - object:self]; + [self setProjectDictObject:projectFiles forKey:key]; return YES; } - (BOOL)renameFile:(NSString *)fromFile toFile:(NSString *)toFile { - NSFileManager *fm = [NSFileManager defaultManager]; - NSString *selectedCategory = [self selectedRootCategory]; - NSString *selectedCategoryKey = [self selectedRootCategoryKey]; - NSString *fromPath = nil; - NSString *toPath = nil; + NSFileManager *fm = [NSFileManager defaultManager]; + NSString *selectedCategory = nil; + NSString *selectedCategoryKey = nil; + NSString *fromPath = nil; + NSString *toPath = nil; NSMutableDictionary *_pDict = nil; NSString *_file = nil; NSMutableArray *_array = nil; BOOL saveToFile = NO; + + selectedCategory = [projectBrowser nameOfSelectedCategory]; + selectedCategoryKey = [[projectManager rootActiveProject] + keyForCategory:selectedCategory]; fromPath = [[self dirForCategoryKey:selectedCategoryKey] stringByAppendingPathComponent:fromFile]; toPath = [[self dirForCategoryKey:selectedCategoryKey] stringByAppendingPathComponent:toFile]; - PCLogInfo(self, @"move %@ to %@", fromPath, toPath); + PCLogInfo(self, @"{%@} move %@ to %@ category: %@", + projectName, fromPath, toPath, selectedCategory); if ([fm movePath:fromPath toPath:toPath handler:nil] == YES) { @@ -778,8 +766,11 @@ NSString { [self save]; } - - [projectBrowser setPathForFile:toFile category:selectedCategory]; + + // Set browser path to new file name + [projectBrowser + setPath:[[projectBrowser pathToSelectedCategory] + stringByAppendingPathComponent:toFile]]; } return YES; @@ -842,10 +833,8 @@ NSString return rootEntries; } -// Category is the name we see in project browser, e.g. -// Classes. -// Key is the uppercase names which are located in PC.roject, e.g. -// CLASS_FILES +// Category - the name we see in project browser, e.g. "Classes" +// Key - the uppercase names located in PC.roject, e.g. "CLASS_FILES" - (NSString *)keyForCategory:(NSString *)category { int index = [rootCategories indexOfObject:category]; @@ -919,11 +908,6 @@ NSString return YES; } -- (BOOL)saveAt:(NSString *)projPath -{ - return NO; -} - - (BOOL)writeSpecFile { NSString *name = [projectDict objectForKey:PCProjectName]; @@ -987,12 +971,11 @@ NSString - (void)updateProjectDict { Class projClass = [self builderClass]; - NSString *_file; - NSString *key; - NSDictionary *origin; - NSArray *keys; - NSEnumerator *enumerator; - BOOL projectHasChanged = NO; + NSString *_file = nil; + NSString *key = nil; + NSDictionary *origin = nil; + NSArray *keys = nil; + NSEnumerator *enumerator = nil; _file = [[NSBundle bundleForClass:projClass] pathForResource:@"PC" ofType:@"project"]; @@ -1005,21 +988,12 @@ NSString { if ([projectDict objectForKey:key] == nil) { + // Doesn't call setProjectDictObject:forKey for opimizations [projectDict setObject:[origin objectForKey:key] forKey:key]; - projectHasChanged = YES; - -/* NSRunAlertPanel(@"New Project Key!", - @"The key '%@' has been added.", - @"OK",nil,nil,key);*/ } } - if (projectHasChanged == YES) - { - [[NSNotificationCenter defaultCenter] - postNotificationName:PCProjectDictDidChangeNotification - object:self]; - } + [self save]; } - (void)validateProjectDict @@ -1033,7 +1007,6 @@ NSString if (ret == NSAlertDefaultReturn) { [self updateProjectDict]; - [self save]; NSRunAlertPanel(@"Project updated!", @"The project file has been updated successfully!\nPlease make sure that all new project keys contain valid entries!", @@ -1098,7 +1071,9 @@ NSString // Subproject in project but not loaded if ([[projectDict objectForKey:PCSubprojects] containsObject:name]) { - // Search for subproject with name in subprojects array + PCLogInfo(self, @"{%@}Searching for loaded subproject: %@", + projectName, name); + // Search for subproject with name among loaded subprojects for (i = 0; i < count; i++) { sp = [loadedSubprojects objectAtIndex:i]; @@ -1110,27 +1085,37 @@ NSString sp = nil; } - // Subproject not found in array, load subproject + // Subproject not found in array, load it if (sp == nil) { spFile = [projectPath stringByAppendingPathComponent:name]; spFile = [spFile stringByAppendingPathExtension:@"subproj"]; spFile = [spFile stringByAppendingPathComponent:@"PC.project"]; + PCLogInfo(self, @"Not found! Load subproject: %@ at path: %@", + name, spFile); sp = [projectManager loadProjectAt:spFile]; - [sp setIsSubproject:YES]; - [sp setSuperProject:self]; - [loadedSubprojects addObject:sp]; + if (sp) + { + [sp setIsSubproject:YES]; + [sp setSuperProject:self]; + [sp setProjectManager:projectManager]; + [loadedSubprojects addObject:sp]; + } } } return sp; } - - (void)addSubproject:(PCProject *)aSubproject { NSMutableArray *_subprojects; + if (!aSubproject) + { + return; + } + _subprojects = [NSMutableArray arrayWithArray:[projectDict objectForKey:PCSubprojects]]; @@ -1139,67 +1124,95 @@ NSString [self setProjectDictObject:_subprojects forKey:PCSubprojects]; } -- (void)newSubprojectNamed:(NSString *)aName +- (void)addSubprojectWithName:(NSString *)name { + NSMutableArray *_subprojects = nil; + + if (!name) + { + return; + } + + _subprojects = [NSMutableArray + arrayWithArray:[projectDict objectForKey:PCSubprojects]]; + [_subprojects addObject:name]; + [self setProjectDictObject:_subprojects forKey:PCSubprojects]; } -- (void)removeSubproject:(PCProject *)aSubproject +- (BOOL)removeSubprojectWithName:(NSString *)subprojectName +{ + NSString *extension = [subprojectName pathExtension]; + NSString *sName = subprojectName; + + if (extension && [extension isEqualToString:@"subproj"]) + { + sName = [subprojectName stringByDeletingPathExtension]; + } + + return [self removeSubproject:[self subprojectWithName:sName]]; +} + +- (BOOL)removeSubproject:(PCProject *)aSubproject { if ([loadedSubprojects containsObject:aSubproject]) { [aSubproject close:self]; [loadedSubprojects removeObject:aSubproject]; } + + return YES; } @end @implementation PCProject (CategoryPaths) +// TODO: Think about moving all category related methods into PCProjectBrowser - (NSArray *)contentAtCategoryPath:(NSString *)categoryPath { - NSString *key = [self keyForCategoryPath:categoryPath]; + NSString *key = [self keyForRootCategoryInCategoryPath:categoryPath]; NSArray *pathArray = nil; pathArray = [categoryPath componentsSeparatedByString:@"/"]; + PCLogInfo(self, @"{%@}{contentAtCategoryPath:} %@", + projectName, categoryPath); + + // Click on /Category if ([pathArray count] == 2) { - [projectManager setActiveProject:self]; + if ([projectManager activeProject] != self) + { + [projectManager setActiveProject:self]; + } activeSubproject = nil; } if ([categoryPath isEqualToString:@""] || [categoryPath isEqualToString:@"/"]) { + if ([projectManager activeProject] != self) + { + [projectManager setActiveProject:self]; + } return rootCategories; } - else if ([key isEqualToString:PCSubprojects]) - { + else if ([key isEqualToString:PCSubprojects] && [pathArray count] > 2) + { // Click on "/Subprojects/Name+" PCProject *_subproject = nil; NSString *spCategoryPath = nil; NSMutableArray *mCategoryPath = nil; mCategoryPath = [pathArray mutableCopy]; - if ([pathArray count] == 2) - { // Click on "/Subprojects" - return [projectDict objectForKey:PCSubprojects]; - } - else if ([pathArray count] > 2) - { // CLick on "/Subprojects/Name.subproj+" - _subproject = [self - subprojectWithName:[pathArray objectAtIndex:2]]; + _subproject = [self subprojectWithName:[pathArray objectAtIndex:2]]; + activeSubproject = _subproject; - [projectManager setActiveProject:_subproject]; - activeSubproject = _subproject; + [mCategoryPath removeObjectAtIndex:1]; + [mCategoryPath removeObjectAtIndex:1]; - [mCategoryPath removeObjectAtIndex:1]; - [mCategoryPath removeObjectAtIndex:1]; + spCategoryPath = [mCategoryPath componentsJoinedByString:@"/"]; - spCategoryPath = [mCategoryPath componentsJoinedByString:@"/"]; - - return [_subproject contentAtCategoryPath:spCategoryPath]; - } + return [_subproject contentAtCategoryPath:spCategoryPath]; } return [projectDict objectForKey:key]; @@ -1207,11 +1220,29 @@ NSString - (BOOL)hasChildrenAtCategoryPath:(NSString *)categoryPath { - NSString *listEntry = nil; - + NSString *listEntry = nil; + NSString *categoryKey = nil; + NSString *category = nil; + PCProject *activeProject = [projectManager activeProject]; + + if (self != activeProject) + { + return [activeProject hasChildrenAtCategoryPath:categoryPath]; + } + + PCLogInfo(self, @"{%@} hasChildrenAtCategoryPath: %@", + [self projectName], categoryPath); + listEntry = [[categoryPath componentsSeparatedByString:@"/"] lastObject]; - if ([rootCategories containsObject:listEntry] - || [[projectDict objectForKey:PCSubprojects] containsObject:listEntry]) + if ([rootCategories containsObject:listEntry]) + { + return YES; + } + + category = [projectBrowser nameOfSelectedCategory]; + categoryKey = [self keyForCategory:category]; + if ([categoryKey isEqualToString:PCSubprojects] + && [[projectDict objectForKey:PCSubprojects] containsObject:listEntry]) { return YES; } @@ -1252,8 +1283,10 @@ NSString if ([key isEqualToString:PCSubprojects]) { // /Subprojects/Name/Classes/Class.m, should return Classes - // 0 1 2 3 4 + // 0 1 2 3 4 // ("",Subprojects,Name,Classes,Class.m) + // 0 1 2 3 4 + // ("",Subprojects,Name,Subprojects,Name) if ([pathComponents count] > 4 && activeSubproject) { i = [pathComponents count] - 1; @@ -1272,10 +1305,10 @@ NSString return category; } -- (NSString *)keyForCategoryPath:(NSString *)categoryPath +- (NSString *)keyForRootCategoryInCategoryPath:(NSString *)categoryPath { - NSString *category = nil; - NSString *key = nil; + NSString *category = nil; + NSString *key = nil; if (categoryPath == nil || [categoryPath isEqualToString:@""] @@ -1284,14 +1317,19 @@ NSString return nil; } - category = [self categoryForCategoryPath:categoryPath]; + category = [self rootCategoryForCategoryPath:categoryPath]; key = [self keyForCategory:category]; - PCLogInfo(self, @"{%@}(keyForCategoryPath): %@ key:%@", - projectName, category, key); + PCLogInfo(self, @"{%@}(keyForRootCategoryInCategoryPath): %@ key:%@", + projectName, categoryPath, key); return key; } +- (NSString *)keyForCategoryPath:(NSString *)categoryPath +{ + return [self keyForCategory:[self categoryForCategoryPath:categoryPath]]; +} + @end diff --git a/Library/PCProjectBrowser.h b/Library/PCProjectBrowser.h index 3de8d53..e08b77d 100644 --- a/Library/PCProjectBrowser.h +++ b/Library/PCProjectBrowser.h @@ -50,11 +50,16 @@ extern NSString *PCBrowserDidSetPathNotification; - (NSView *)view; - (NSString *)nameOfSelectedFile; -- (NSString *)pathOfSelectedFile; +- (NSString *)pathToSelectedFile; +- (NSString *)nameOfSelectedCategory; +- (NSString *)pathToSelectedCategory; +- (NSString *)nameOfSelectedRootCategory; + - (NSArray *)selectedFiles; +- (NSString *)path; - (BOOL)setPath:(NSString *)path; -- (BOOL)setPathForFile:(NSString *)file category:(NSString *)category; +- (void)reloadLastColumn; // ============================================================================ // ==== Actions @@ -71,7 +76,8 @@ extern NSString *PCBrowserDidSetPathNotification; @interface PCProjectBrowser (ProjectBrowserDelegate) -- (void)browser:(NSBrowser *)sender createRowsForColumn:(int)column inMatrix:(NSMatrix *)matrix; +- (void)browser:(NSBrowser *)sender createRowsForColumn:(int)column + inMatrix:(NSMatrix *)matrix; @end diff --git a/Library/PCProjectBrowser.m b/Library/PCProjectBrowser.m index 0eb08c2..8433c66 100644 --- a/Library/PCProjectBrowser.m +++ b/Library/PCProjectBrowser.m @@ -26,8 +26,8 @@ #include "PCFileManager.h" #include "PCProjectManager.h" #include "PCProject.h" -#include "PCProjectEditor.h" #include "PCProjectBrowser.h" +#include "PCProjectEditor.h" #include "PCLogController.h" @@ -62,8 +62,7 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; addObserver:self selector:@selector(projectDictDidChange:) name:PCProjectDictDidChangeNotification - object:project]; - + object:nil]; } return self; @@ -88,22 +87,109 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; return browser; } +// Returns nil if multiple files selected - (NSString *)nameOfSelectedFile { NSString *name = nil; - // Doesn't work with subprojects! - if ([browser selectedColumn] != 0 && [[browser selectedCells] count] == 1) + if ([[browser selectedCells] count] == 1) { - name = [[[browser path] componentsSeparatedByString:@"/"] lastObject]; + name = [[browser path] lastPathComponent]; + if ([name isEqualToString:[self nameOfSelectedCategory]]) + { + return nil; + } + } + + return name; +} + +// Returns nil if multiple files selected +- (NSString *)pathToSelectedFile +{ + NSString *name = nil; + NSString *path = nil; + + if ([[browser selectedCells] count] == 1) + { + name = [[browser path] lastPathComponent]; + if ([name isEqualToString:[self nameOfSelectedCategory]]) + { + path = nil; + } + else + { + path = [browser path]; + } + } + + return path; +} + +// Returns nil of multiple categories selected +- (NSString *)nameOfSelectedCategory +{ + NSString *name = nil; + NSArray *pathArray = [[browser path] componentsSeparatedByString:@"/"]; + PCProject *activeProject = [[project projectManager] activeProject]; + NSArray *rootCategories = [activeProject rootCategories]; + int i; + + if ([rootCategories containsObject:[pathArray lastObject]] + && [[browser selectedCells] count] > 1) + { + return nil; + } + + for (i = [pathArray count] - 1; i >= 0; i--) + { + if ([rootCategories containsObject:[pathArray objectAtIndex:i]]) + { + name = [pathArray objectAtIndex:i]; + break; + } } return name; } -- (NSString *)pathOfSelectedFile +// Returns nil of multiple categories selected +- (NSString *)pathToSelectedCategory { - return [browser path]; + NSString *path = nil; + NSString *selectedCategory = [self nameOfSelectedCategory]; + NSMutableArray *bPathArray = nil; + int i; + + if (selectedCategory) + { + bPathArray = [NSMutableArray arrayWithArray:[[browser path] + componentsSeparatedByString:@"/"]]; + i = [bPathArray count] - 1; + while (![[bPathArray objectAtIndex:i] isEqualToString:selectedCategory]) + { + [bPathArray removeObjectAtIndex:i]; + i = [bPathArray count] - 1; + } + path = [bPathArray componentsJoinedByString:@"/"]; + } + + return path; +} + +- (NSString *)nameOfSelectedRootCategory +{ + NSString *categoryPath = [self pathToSelectedCategory]; + NSArray *pathComponents = nil; + + if ([categoryPath isEqualToString:@"/"] || [categoryPath isEqualToString:@""]) + { + return nil; + } + + pathComponents = [categoryPath componentsSeparatedByString:@"/"]; + + return [pathComponents objectAtIndex:1]; } - (NSArray *)selectedFiles @@ -112,39 +198,34 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; NSMutableArray *files = [[NSMutableArray alloc] initWithCapacity: 1]; int i; int count = [cells count]; + PCProject *activeProject = [[project projectManager] activeProject]; + + // Return nil if categories selected + if ([cells count] == 0 + || [[activeProject rootCategories] + containsObject:[[cells objectAtIndex:0] stringValue]]) + { + return nil; + } for (i = 0; i < count; i++) { [files addObject: [[cells objectAtIndex: i] stringValue]]; } - + return (NSArray *)files; } +- (NSString *)path +{ + return [browser path]; +} + - (BOOL)setPath:(NSString *)path { int selectedColumn; NSMatrix *columnMatrix = nil; - - while ((selectedColumn = [browser selectedColumn]) >= 0) - { - columnMatrix = [browser matrixInColumn:selectedColumn]; - [columnMatrix deselectAllCells]; - } - - PCLogInfo(self, @"[setPath]: %@", path); - - return [browser setPath:path]; -} - -- (BOOL)setPathForFile:(NSString *)file category:(NSString *)category -{ - NSArray *comp = [NSArray arrayWithObjects: @"/",category,@"/",file,nil]; - NSString *path = [NSString pathWithComponents:comp]; - BOOL result; - - int selectedColumn; - NSMatrix *columnMatrix = nil; + BOOL res; if ([[browser path] isEqualToString: path]) { @@ -159,15 +240,40 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; } // End of HACK - result = [browser setPath:path]; + PCLogInfo(self, @"[setPath]: %@", path); - [self click:browser]; + res = [browser setPath:path]; + + [[NSNotificationCenter defaultCenter] + postNotificationName:PCBrowserDidSetPathNotification + object:self]; + + return res; +} + +- (void)reloadLastColumn +{ + int column = [browser lastColumn]; + NSString *category = [self nameOfSelectedCategory]; + int selectedColumn = [browser selectedColumn]; + NSMatrix *colMatrix = [browser matrixInColumn:selectedColumn]; + int rowCount = 0, colCount = 0, spCount = 0; + PCProject *activeProject = [[project projectManager] activeProject]; + + [colMatrix getNumberOfRows:&rowCount columns:&colCount]; + spCount = [[[activeProject projectDict] objectForKey:PCSubprojects] count]; + + if ([category isEqualToString:@"Subprojects"] && rowCount != spCount + && ![[[browser selectedCell] stringValue] isEqualToString:@"Subprojects"]) + { + column = selectedColumn; + } -/* [[NSNotificationCenter defaultCenter] - postNotificationName:PCBrowserDidSetPathNotification - object:self];*/ + [browser reloadColumn:column]; - return result; + [[NSNotificationCenter defaultCenter] + postNotificationName:PCBrowserDidSetPathNotification + object:self]; } // ============================================================================ @@ -176,38 +282,33 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; - (void)click:(id)sender { + NSUserDefaults *ud = nil; NSString *category = nil; NSString *fileName = nil; - PCProject *sp = nil; NSString *filePath = nil; - NSUserDefaults *ud = nil; + NSString *key = nil; + PCProject *activeProject = nil; if (sender != browser) { return; } - + if ([[sender selectedCell] isLeaf] && [[self selectedFiles] count] == 1) { ud = [NSUserDefaults standardUserDefaults]; - category = [project categoryForCategoryPath:[browser path]]; + category = [self nameOfSelectedCategory]; fileName = [[sender selectedCell] stringValue]; - if ((sp = [project activeSubproject]) != nil) - { - filePath = [[sp projectPath] - stringByAppendingPathComponent:fileName]; - } - else - { - filePath = [[project projectPath] - stringByAppendingPathComponent:fileName]; - } + + activeProject = [[project projectManager] activeProject]; + key = [activeProject keyForCategory:category]; + filePath = [activeProject dirForCategoryKey:key]; + filePath = [filePath stringByAppendingPathComponent:fileName]; PCLogInfo(self, @"[click] category: %@ filePath: %@", category, filePath); - if ([project isEditableCategory:category] - || [sp isEditableCategory:category]) + if ([activeProject isEditableCategory:category]) { if (![[ud objectForKey:SeparateEditor] isEqualToString:@"YES"]) { @@ -218,6 +319,11 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; } } + PCLogStatus(self, @"nameOfSelectedCategory: %@", + [self nameOfSelectedCategory]); + PCLogStatus(self, @"nameOfSelectedFile: %@", + [self nameOfSelectedFile]); + [[NSNotificationCenter defaultCenter] postNotificationName:PCBrowserDidSetPathNotification object:self]; @@ -225,32 +331,31 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; - (void)doubleClick:(id)sender { + id selectedCell; + if (sender != browser) { return; } - if ([[sender selectedCell] isLeaf]) + selectedCell = [sender selectedCell]; + + if ([selectedCell isLeaf]) { - NSString *category = [project categoryForCategoryPath:[browser path]]; + NSString *category = [self nameOfSelectedCategory]; NSString *fileName = [[sender selectedCell] stringValue]; - PCProject *sp = nil; NSString *filePath = nil; + NSString *key = nil; + PCProject *activeProject = nil; + + activeProject = [[project projectManager] activeProject]; + key = [activeProject keyForCategory:category]; + filePath = [activeProject dirForCategoryKey:key]; + filePath = [filePath stringByAppendingPathComponent:fileName]; - if ((sp = [project activeSubproject]) != nil) - { - filePath = [sp dirForCategoryKey:[sp keyForCategory:category]]; - filePath = [filePath stringByAppendingPathComponent:fileName]; - } - else - { - filePath = [project dirForCategoryKey: - [project keyForCategory:category]]; - filePath = [filePath stringByAppendingPathComponent:fileName]; - } + PCLogInfo(self, @"{doubleClick} filePath: %@", filePath); - if ([project isEditableCategory:category] - || [sp isEditableCategory:category]) + if ([activeProject isEditableCategory:category]) { [[project projectEditor] editorForFile:filePath categoryPath:[browser path] @@ -265,7 +370,14 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; } else { - [[project projectManager] addProjectFiles]; + if ([[selectedCell title] isEqualToString:@"Subprojects"]) + { + [[project projectManager] addSubproject]; + } + else + { + [[project projectManager] addProjectFiles]; + } } } @@ -275,23 +387,20 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; - (void)projectDictDidChange:(NSNotification *)aNotif { - if (browser && - ([aNotif object] == project - || [[project loadedSubprojects] containsObject:[aNotif object]])) - { - NSString *browserPath = [browser path]; - NSString *slctdCategory = [project selectedRootCategory]; - - if (slctdCategory && browserPath && ![browserPath isEqualToString:@"/"]) - { - if ([[[project projectEditor] allEditors] count] == 0 - && [project isEditableCategory:slctdCategory]) - { - [self setPathForFile:nil category:slctdCategory]; - } - } + PCProject *changedProject = nil; + PCProject *activeProject = nil; - [browser reloadColumn:[browser lastColumn]]; + if (!browser) + { + return; + } + + changedProject = [aNotif object]; + activeProject = [[project projectManager] activeProject]; + + if (changedProject == project || changedProject == activeProject) + { + [self reloadLastColumn]; } } @@ -299,21 +408,25 @@ NSString *PCBrowserDidSetPathNotification = @"PCBrowserDidSetPathNotification"; @implementation PCProjectBrowser (ProjectBrowserDelegate) -- (void)browser:(NSBrowser *)sender createRowsForColumn:(int)column inMatrix:(NSMatrix *)matrix +- (void)browser:(NSBrowser *)sender createRowsForColumn:(int)column + inMatrix:(NSMatrix *)matrix { - NSString *pathToCol = nil; - NSArray *files = nil; - int i = 0; - int count = 0; + NSString *pathToCol = nil; + NSArray *files = nil; + int i = 0; + int count = 0; - if (sender != browser || !matrix ||![matrix isKindOfClass:[NSMatrix class]]) + if (sender != browser || !matrix || ![matrix isKindOfClass:[NSMatrix class]]) { return; } pathToCol = [sender pathToColumn:column]; files = [project contentAtCategoryPath:pathToCol]; - count = [files count]; + if (files) + { + count = [files count]; + } for (i = 0; i < count; ++i) { diff --git a/Library/PCProjectEditor.m b/Library/PCProjectEditor.m index 7518940..9d32916 100644 --- a/Library/PCProjectEditor.m +++ b/Library/PCProjectEditor.m @@ -252,7 +252,9 @@ NSString *PCEditorDidResignActiveNotification = - (void)orderFrontEditorForFile:(NSString *)path { PCEditor *editor = [editorsDict objectForKey:path]; - + + NSLog(@"PCProjectEditor: orderFrontEditorForFile"); + if ([editor isWindowed]) { [editor show]; @@ -463,12 +465,12 @@ NSString *PCEditorDidResignActiveNotification = lastEditorKey = [[editorsDict allKeys] lastObject]; [componentView setContentView:[lastEditor componentView]]; - [[project projectWindow] makeFirstResponder:[lastEditor editorView]]; +// [[project projectWindow] makeFirstResponder:[lastEditor editorView]]; [self setActiveEditor:lastEditor]; } else { - [[project projectWindow] makeFirstResponder:scrollView]; +// [[project projectWindow] makeFirstResponder:scrollView]; [componentView setContentView:scrollView]; [self setActiveEditor:nil]; } @@ -478,8 +480,11 @@ NSString *PCEditorDidResignActiveNotification = { PCEditor *editor = [aNotif object]; NSString *categoryPath = nil; - - if ([editorsDict objectForKey:[editor path]] != editor) + + NSLog(@"PCPE: editorDidBecomeActive: %@", [editor path]); + + if ([editorsDict objectForKey:[editor path]] != editor + || activeEditor == editor) { return; } @@ -497,6 +502,7 @@ NSString *PCEditorDidResignActiveNotification = - (void)editorDidResignActive:(NSNotification *)aNotif { + [self setActiveEditor:nil]; } @end diff --git a/Library/PCProjectInspector.m b/Library/PCProjectInspector.m index 17c190c..d2cb22d 100644 --- a/Library/PCProjectInspector.m +++ b/Library/PCProjectInspector.m @@ -724,8 +724,8 @@ return; } - PCLogInfo(self, @"file name changed from: %@ to: %@", - fileName, [fileNameField stringValue]); + PCLogInfo(self, @"{%@} file name changed from: %@ to: %@", + [project projectName], fileName, [fileNameField stringValue]); if ([project renameFile:fileName toFile:[fileNameField stringValue]] == NO) { diff --git a/Library/PCProjectLoadedFiles.m b/Library/PCProjectLoadedFiles.m index f901896..1d7a9f5 100644 --- a/Library/PCProjectLoadedFiles.m +++ b/Library/PCProjectLoadedFiles.m @@ -18,6 +18,8 @@ { NSAssert(aProj, @"Project is mandatory!"); + NSLog(@"PCProjectLoadedFiles: init"); + if ((self = [super init])) { project = aProj; @@ -186,8 +188,8 @@ - (void)click:(id)sender { - int row = [filesList selectedRow]; - NSString *path = [[self editedFilesRep] objectAtIndex:row]; + int row = [filesList selectedRow]; + NSString *path = [[self editedFilesRep] objectAtIndex:row]; [[project projectEditor] orderFrontEditorForFile:path]; } diff --git a/Library/PCProjectManager.h b/Library/PCProjectManager.h index c87b499..ba98c61 100644 --- a/Library/PCProjectManager.h +++ b/Library/PCProjectManager.h @@ -233,18 +233,13 @@ extern NSString *PCActiveProjectDidChangeNotification; @interface PCProjectManager (Subprojects) -// --- New - (BOOL)newSubproject; +- (BOOL)addSubproject; - (void)closeNewSubprojectPanel:(id)sender; - (BOOL)createSubproject:(id)sender; +- (PCProject *)createSubprojectOfType:(NSString *)projectType + path:(NSString *)aPath; - (BOOL)createSubproject; - -// --- Add -- (BOOL)addSubprojectAt:(NSString *)path; - -// --- Remove -- (void)removeSubproject; - @end #endif diff --git a/Library/PCProjectManager.m b/Library/PCProjectManager.m index 7547af3..71c423d 100644 --- a/Library/PCProjectManager.m +++ b/Library/PCProjectManager.m @@ -60,6 +60,11 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; { NSUserDefaults *defs = [NSUserDefaults standardUserDefaults]; + buildPanel = nil; + launchPanel = nil; + loadedFilesPanel = nil; + findPanel = nil; + [self loadProjectTypeBunldes]; loadedProjects = [[NSMutableDictionary alloc] init]; @@ -240,9 +245,13 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; - (NSPanel *)loadedFilesPanel { - if (!loadedFilesPanel) + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + if (!loadedFilesPanel + && [[ud objectForKey:SeparateLoadedFiles] isEqualToString:@"YES"]) { - loadedFilesPanel = [[PCLoadedFilesPanel alloc] initWithProjectManager:self]; + loadedFilesPanel = + [[PCLoadedFilesPanel alloc] initWithProjectManager:self]; } return loadedFilesPanel; @@ -259,7 +268,10 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; - (NSPanel *)buildPanel { - if (!buildPanel) + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + if (!buildPanel + && [[ud objectForKey:SeparateBuilder] isEqualToString:@"YES"]) { buildPanel = [[PCBuildPanel alloc] initWithProjectManager:self]; } @@ -269,7 +281,10 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; - (NSPanel *)launchPanel { - if (!launchPanel) + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + if (!launchPanel + && [[ud objectForKey:SeparateLauncher] isEqualToString:@"YES"]) { launchPanel = [[PCLaunchPanel alloc] initWithProjectManager:self]; } @@ -419,7 +434,9 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; { PCLogStatus(self, @"Project %@ loaded as %@", [project projectName], [projectCreator projectTypeName]); + // Started only if there's not save timer yet [self startSaveTimer]; + [project validateProjectDict]; return project; } @@ -456,25 +473,24 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; return NO; } - [project setProjectManager:self]; - [project validateProjectDict]; [loadedProjects setObject:project forKey:projectName]; [self setActiveProject:project]; + [project setProjectManager:self]; // Windows and panels wap = [[NSDictionary dictionaryWithContentsOfFile:aPath] objectForKey:@"PC_WINDOWS"]; if ([[wap allKeys] containsObject:@"ProjectBuild"]) { - [[self buildPanel] orderFront:self]; + [[project projectWindow] showProjectBuild:self]; } if ([[wap allKeys] containsObject:@"ProjectLaunch"]) { - [[self launchPanel] orderFront:self]; + [[project projectWindow] showProjectLaunch:self]; } if ([[wap allKeys] containsObject:@"LoadedFiles"]) { - [[self loadedFilesPanel] orderFront:self]; + [[project projectWindow] showProjectLoadedFiles:self]; } [[project projectWindow] orderFront:self]; @@ -591,16 +607,15 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; - (BOOL)addProjectFiles { - NSString *categoryKey = nil; - NSArray *fileTypes = nil; + PCProject *project = [self rootActiveProject]; + NSString *category = [[project projectBrowser] nameOfSelectedCategory]; + NSString *categoryKey = [activeProject keyForCategory:category]; NSMutableArray *files = nil; - categoryKey = [activeProject selectedRootCategoryKey]; - fileTypes = [activeProject fileTypesForCategoryKey:categoryKey]; - files = [fileManager filesForAdd]; - PCLogInfo(self, @"[addProjectFiles] %@", files); + PCLogInfo(self, @"[addProjectFiles] %@ to category: %@ of project %@", + files, categoryKey, [activeProject projectName]); // No files was selected if (!files) @@ -621,44 +636,24 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; - (BOOL)removeProjectFiles { - NSArray *files = nil; - NSString *categoryKey = nil; - NSString *directory = nil; - NSString *bPath = nil; - PCProject *project = activeProject; + PCProject *project = [self rootActiveProject]; + NSArray *files = [[project projectBrowser] selectedFiles]; + NSString *category = [[project projectBrowser] nameOfSelectedCategory]; + NSString *categoryKey = [project keyForCategory:category]; + NSString *directory = [activeProject dirForCategoryKey:categoryKey]; NSString *removeString = [NSString stringWithString:@"Remove files..."]; - NSMutableArray *subprojs = nil; + NSMutableArray *subprojs = [NSMutableArray array]; int i; - if (!activeProject) - { - return NO; - } - - // We need to get root project - while ([project isSubproject]) - { - project = [project superProject]; - } - bPath = [[activeProject projectBrowser] pathOfSelectedFile]; - categoryKey = [project keyForCategoryPath:bPath]; - - files = [[activeProject projectBrowser] selectedFiles]; - directory = [activeProject dirForCategoryKey:categoryKey]; - // Determining target project - if ([categoryKey isEqualToString:PCSubprojects] - && [activeProject isSubproject]) + if ([categoryKey isEqualToString:PCSubprojects]) { - subprojs = [NSMutableArray array]; - project = [activeProject superProject]; - removeString = [NSString stringWithString:@"Remove subprojects..."]; - for (i = 0; i < [files count]; i++) + if ([activeProject isSubproject]) { - [subprojs addObject: - [[files objectAtIndex:i] - stringByAppendingPathExtension:@"subproj"]]; + project = [activeProject superProject]; + [self setActiveProject:project]; } + removeString = [NSString stringWithString:@"Remove subprojects..."]; directory = [project dirForCategoryKey:categoryKey]; } else @@ -667,13 +662,12 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; } PCLogInfo(self, @"%@: %@ from %@", removeString, files, directory); - PCLogInfo(self, @"[removeProjectFiles]:%@ KEY:%@ bPath:%@", - [activeProject projectName], categoryKey, bPath); + PCLogInfo(self, @"[removeProjectFiles]:%@ KEY:%@", + [activeProject projectName], categoryKey); if (files) { - int ret; - NSMutableArray *bPathArray = nil; + int ret; if ([categoryKey isEqualToString:PCLibraries]) { @@ -696,20 +690,24 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; { BOOL flag = (ret == NSAlertDefaultReturn) ? YES : NO; + // Remove from projectDict ret = [project removeFiles:files forKey:categoryKey]; + // Remove files from disk if (flag && ret && ![categoryKey isEqualToString:PCLibraries]) { if ([categoryKey isEqualToString:PCSubprojects]) { - ret = [fileManager removeFiles:subprojs - fromDirectory:directory]; - } - else - { - ret = [fileManager removeFiles:files - fromDirectory:directory]; + for (i = 0; i < [files count]; i++) + { + [subprojs addObject: + [[files objectAtIndex:i] + stringByAppendingPathExtension:@"subproj"]]; + } + files = subprojs; } + ret = [fileManager removeFiles:files + fromDirectory:directory]; } if (!ret) @@ -719,24 +717,12 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; @"OK", nil, nil, [activeProject projectName]); return NO; } - - // Save project because we've removed file(s) from disk - // Should be fixed later (add pending removal of files?) else if (flag) { - [project save]; + // Save project because we've removed file(s) from disk + // Should be fixed later (add pending removal of files?) + [activeProject save]; } - bPathArray = [NSMutableArray - arrayWithArray:[bPath componentsSeparatedByString:@"/"]]; - i = [bPathArray count]; - while ([[bPathArray objectAtIndex:i-1] isEqualToString:@""]) - { - [bPathArray removeObjectAtIndex:i-1]; - i = [bPathArray count]; - } - [bPathArray removeObjectAtIndex:i-1]; - [[activeProject projectBrowser] - setPath:[bPathArray componentsJoinedByString:@"/"]]; } else { @@ -980,7 +966,6 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; @implementation PCProjectManager (Subprojects) -// --- New - (BOOL)newSubproject { PCLogInfo(self, @"newSubproject"); @@ -1031,7 +1016,6 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; - (BOOL)createSubproject { - PCProject *superProject = activeProject; PCProject *subproject = nil; NSString *spName = [nsNameField stringValue]; NSString *spPath = nil; @@ -1045,20 +1029,50 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; spPath = [[activeProject projectPath] stringByAppendingPathComponent:spName]; - PCLogInfo(self, @"creating subproject with type %@ at path %@", - spType, spPath); + PCLogStatus(self, @"creating subproject with type %@ at path %@", + spType, spPath); + // Create subproject - subproject = [self createProjectOfType:spType path:spPath]; - - // For now root project can contain subproject but suboproject can't. - [subproject setIsSubproject:YES]; - [subproject setSuperProject:superProject]; - - [superProject addSubproject:subproject]; + subproject = [self createSubprojectOfType:spType path:spPath]; return YES; } +- (PCProject *)createSubprojectOfType:(NSString *)projectType + path:(NSString *)aPath +{ + NSString *className = [projectTypes objectForKey:projectType]; + Class creatorClass = NSClassFromString(className); + PCProject *subproject = nil; +/* NSString *subprojectName = [aPath lastPathComponent]; + + if ((project = [activeProject objectForKey:projectName]) != nil) + { + [[project projectWindow] makeKeyAndOrderFront:self]; + return project; + }*/ + + if (![creatorClass conformsToProtocol:@protocol(ProjectType)]) + { + [NSException raise:NOT_A_PROJECT_TYPE_EXCEPTION + format:@"%@ does not conform to ProjectType!", projectType]; + return nil; + } + + if (!(subproject = [[creatorClass sharedCreator] createProjectAt:aPath])) + { + return nil; + } + [subproject setIsSubproject:YES]; + [subproject setSuperProject:activeProject]; + [subproject setProjectManager:self]; + + PCLogInfo(self, @"{createSubproject} add to %@", [activeProject projectName]); + [activeProject addSubproject:subproject]; + + return subproject; +} + - (void)controlTextDidChange:(NSNotification *)aNotif { if ([aNotif object] != nsNameField) @@ -1077,15 +1091,51 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; } } -// --- Add -- (BOOL)addSubprojectAt:(NSString *)path +- (BOOL)addSubproject { - return NO; -} + NSFileManager *fm = [NSFileManager defaultManager]; + NSMutableArray *files = nil; + NSString *pcProject = nil; + NSString *spDir = nil; + NSDictionary *spDict = nil; + NSString *spName = nil; + int i; -// --- Remove -- (void)removeSubproject -{ + files = [fileManager filesForAdd]; + + // Validate if it real projects + for (i = 0; i < [files count]; i++) + { + spDir = [files objectAtIndex:i]; + pcProject = [spDir stringByAppendingPathComponent:@"PC.project"]; + if (![[spDir pathExtension] isEqualToString:@"subproj"] + || ![fm fileExistsAtPath:pcProject]) + { + [files removeObjectAtIndex:i]; + } + } + + PCLogInfo(self, @"{addSubproject} %@", files); + + if (![fileManager copyFiles:files + intoDirectory:[activeProject projectPath]]) + { + return NO; + } + + for (i = 0; i < [files count]; i++) + { + spDir = [files objectAtIndex:i]; + pcProject = [spDir stringByAppendingPathComponent:@"PC.project"]; + spDict = [NSDictionary dictionaryWithContentsOfFile:pcProject]; + spName = [spDict objectForKey:PCProjectName]; + + PCLogInfo(self, @"{addSubproject} dir: %@ file: %@", spDir, pcProject); + + [activeProject addSubprojectWithName:spName]; + } + + return YES; } @end diff --git a/Library/PCProjectWindow.m b/Library/PCProjectWindow.m index 32928fd..4a29714 100644 --- a/Library/PCProjectWindow.m +++ b/Library/PCProjectWindow.m @@ -168,6 +168,7 @@ */ fileIcon = [[NSImageView alloc] initWithFrame: NSMakeRect (496,0,48,48)]; [fileIcon setRefusesFirstResponder:YES]; + [fileIcon setEditable:NO]; [fileIcon setAutoresizingMask: (NSViewMinXMargin | NSViewMinYMargin)]; [fileIcon setImage: IMAGE (@"projectSuitcase")]; [toolbarView addSubview: fileIcon]; @@ -354,68 +355,75 @@ - (void)setFileIcon:(NSNotification *)notification { id object = [notification object]; - NSString *path = nil; - NSArray *pathComponents = nil; - NSString *lastComponent = nil; + NSString *categoryName = nil; + NSString *fileName = nil; NSString *fileExtension = nil; NSString *iconName = nil; NSImage *icon = nil; - path = [object pathOfSelectedFile]; - pathComponents = [path pathComponents]; - lastComponent = [path lastPathComponent]; - fileExtension = [lastComponent pathExtension]; + fileName = [object nameOfSelectedFile]; + if (fileName) + { + fileExtension = [fileName pathExtension]; + } + else + { + categoryName = [object nameOfSelectedCategory]; + } + + PCLogInfo(self,@"{setFileIcon} file %@ category %@", + fileName, categoryName); // Should be provided by PC*Proj bundles - if ([[object selectedFiles] count] > 1 && [pathComponents count] > 2) + if ([[object selectedFiles] count] > 1) { iconName = [[NSString alloc] initWithString:@"MultiFiles"]; } - else if ([lastComponent isEqualToString: @"/"]) + else if (!categoryName && !fileName) // Nothing selected { iconName = [[NSString alloc] initWithString:@"projectSuitcase"]; } - else if ([lastComponent isEqualToString: @"Classes"]) + else if ([categoryName isEqualToString: @"Classes"]) { iconName = [[NSString alloc] initWithString:@"classSuitcase"]; } - else if ([lastComponent isEqualToString: @"Headers"]) + else if ([categoryName isEqualToString: @"Headers"]) { iconName = [[NSString alloc] initWithString:@"headerSuitcase"]; } - else if ([lastComponent isEqualToString: @"Other Sources"]) + else if ([categoryName isEqualToString: @"Other Sources"]) { iconName = [[NSString alloc] initWithString:@"genericSuitcase"]; } - else if ([lastComponent isEqualToString: @"Interfaces"]) + else if ([categoryName isEqualToString: @"Interfaces"]) { iconName = [[NSString alloc] initWithString:@"nibSuitcase"]; } - else if ([lastComponent isEqualToString: @"Images"]) + else if ([categoryName isEqualToString: @"Images"]) { iconName = [[NSString alloc] initWithString:@"iconSuitcase"]; } - else if ([lastComponent isEqualToString: @"Other Resources"]) + else if ([categoryName isEqualToString: @"Other Resources"]) { iconName = [[NSString alloc] initWithString:@"otherSuitcase"]; } - else if ([lastComponent isEqualToString: @"Subprojects"]) + else if ([categoryName isEqualToString: @"Subprojects"]) { iconName = [[NSString alloc] initWithString:@"subprojectSuitcase"]; } - else if ([lastComponent isEqualToString: @"Documentation"]) + else if ([categoryName isEqualToString: @"Documentation"]) { iconName = [[NSString alloc] initWithString:@"helpSuitcase"]; } - else if ([lastComponent isEqualToString: @"Supporting Files"]) + else if ([categoryName isEqualToString: @"Supporting Files"]) { iconName = [[NSString alloc] initWithString:@"genericSuitcase"]; } - else if ([lastComponent isEqualToString: @"Libraries"]) + else if ([categoryName isEqualToString: @"Libraries"]) { iconName = [[NSString alloc] initWithString:@"librarySuitcase"]; } - else if ([lastComponent isEqualToString: @"Non Project Files"]) + else if ([categoryName isEqualToString: @"Non Project Files"]) { iconName = [[NSString alloc] initWithString:@"projectSuitcase"]; } @@ -427,7 +435,7 @@ } else if (fileExtension != nil && ![fileExtension isEqualToString:@""]) { - icon = [[NSWorkspace sharedWorkspace] iconForFile:lastComponent]; + icon = [[NSWorkspace sharedWorkspace] iconForFile:fileName]; } // Set icon to Project Window and Project Inspector @@ -437,15 +445,19 @@ } // Set title - if ([[object selectedFiles] count] > 1 && [pathComponents count] > 2) + if ([[object selectedFiles] count] > 1) { [fileIconTitle setStringValue: [NSString stringWithFormat: @"%i files", [[object selectedFiles] count]]]; } - else + else if (fileName) { - [fileIconTitle setStringValue:lastComponent]; + [fileIconTitle setStringValue:fileName]; + } + else if (categoryName) + { + [fileIconTitle setStringValue:categoryName]; } // Project Inspector @@ -531,7 +543,7 @@ if ([self hasLoadedFilesView]) { - if ([panel isVisible]) + if (panel && [panel isVisible]) { [panel close]; } @@ -542,7 +554,6 @@ } else { -// [[[project projectLoadedFiles] componentView] removeFromSuperview]; [componentView setBorderType:NSNoBorder]; [panel orderFront:nil]; [v_split adjustSubviews]; @@ -602,7 +613,7 @@ } else { - if (launchPanel) + if ([launchPanel isVisible]) { [launchPanel close]; } @@ -705,10 +716,10 @@ - (void)projectDictDidChange:(NSNotification *)aNotif { - NSArray *sps = [project loadedSubprojects]; + PCProject *changedProject = [aNotif object]; - if ([aNotif object] != project - && ![sps containsObject:[aNotif object]]) + if (changedProject != project + && [[project projectManager] activeProject] != changedProject) { return; } @@ -716,7 +727,7 @@ [self setTitle]; // TODO: if window isn't visible and "edited" attribute set, after ordering - // out window doesn't show broken close button. Fix it in GNUstep. + // front window doesn't show broken close button. Fix it in GNUstep. // Workaround is in windowDidBecomeKey. [projectWindow setDocumentEdited:YES]; } @@ -868,10 +879,6 @@ { firstResponder = aResponder; [projectWindow makeFirstResponder:firstResponder]; - if (![projectWindow isKeyWindow]) - { - [self makeKeyWindow]; - } return YES; } @@ -879,17 +886,25 @@ - (void)windowDidBecomeKey:(NSNotification *)aNotification { [projectWindow makeMainWindow]; - [projectWindow makeFirstResponder:(NSResponder *)firstResponder]; +// [projectWindow makeFirstResponder:(NSResponder *)firstResponder]; - if ([project activeSubproject] != nil) + PCLogInfo(self, @"windowDidBecomeKey: activeSubproject %@", + [[project activeSubproject] projectName]); + + if ([[project projectManager] rootActiveProject] != project) { - [[project projectManager] setActiveProject:[project activeSubproject]]; - } - else - { - [[project projectManager] setActiveProject:project]; + if ([project activeSubproject] != nil) + { + [[project projectManager] + setActiveProject:[project activeSubproject]]; + } + else + { + [[project projectManager] setActiveProject:project]; + } } + // Workaround if ([projectWindow isDocumentEdited]) { @@ -900,7 +915,7 @@ - (void)windowDidResignKey:(NSNotification *)aNotification { - [projectWindow makeFirstResponder:nil]; +// [projectWindow makeFirstResponder:nil]; } - (void)windowDidBecomeMain:(NSNotification *)aNotification @@ -914,20 +929,6 @@ - (void)windowWillClose:(NSNotification *)aNotification { -/* [project close]; - if ([aNotification object] == projectWindow) - { - if ([projectWindow isDocumentEdited]) - { - if (NSRunAlertPanel(@"Close Project", - @"The project %@ has been edited!\nShould it be saved before closing?", - @"Yes",@"No",nil,[project projectName])) - { - [project save]; - } - } - [project close]; - }*/ } @end diff --git a/Modules/ApplicationProject/PCAppProject+Inspector.m b/Modules/ApplicationProject/PCAppProject+Inspector.m index 5caeac5..94a8c33 100644 --- a/Modules/ApplicationProject/PCAppProject+Inspector.m +++ b/Modules/ApplicationProject/PCAppProject+Inspector.m @@ -393,7 +393,7 @@ NSString *PCITextFieldGetFocus = @"PCITextFieldGetFocusNotification"; - (void)updateInspectorValues:(NSNotification *)aNotif { - NSLog (@"PCAppProject: updateInspectorValues"); +// NSLog (@"PCAppProject: updateInspectorValues"); // Project Attributes view [projectTypeField setStringValue:[projectDict objectForKey:PCProjectType]]; diff --git a/Modules/ApplicationProject/PCAppProject.m b/Modules/ApplicationProject/PCAppProject.m index a5739c5..c8b5efc 100644 --- a/Modules/ApplicationProject/PCAppProject.m +++ b/Modules/ApplicationProject/PCAppProject.m @@ -285,32 +285,36 @@ { NSString *mainNibFile = [projectDict objectForKey:PCMainInterfaceFile]; NSString *appIcon = [projectDict objectForKey:PCAppIcon]; - NSString *key = [self selectedRootCategoryKey]; + NSString *categoryKey = nil; NSString *ff = [fromFile copy]; NSString *tf = [toFile copy]; BOOL success = NO; + categoryKey = [self + keyForCategory:[projectBrowser nameOfSelectedRootCategory]]; // Check for main NIB file - if ([key isEqualToString:PCInterfaces] + if ([categoryKey isEqualToString:PCInterfaces] && [fromFile isEqualToString:mainNibFile]) { [self clearMainNib:self]; if ([super renameFile:ff toFile:tf] == YES) { [self setMainNibWithFileAtPath: - [[self dirForCategoryKey:key] stringByAppendingPathComponent:tf]]; + [[self dirForCategoryKey:categoryKey] + stringByAppendingPathComponent:tf]]; success = YES; } } // Check for application icon files - else if ([key isEqualToString:PCImages] + else if ([categoryKey isEqualToString:PCImages] && [fromFile isEqualToString:appIcon]) { [self clearAppIcon:self]; if ([super renameFile:ff toFile:tf] == YES) { [self setAppIconWithImageAtPath: - [[self dirForCategoryKey:key] stringByAppendingPathComponent:tf]]; + [[self dirForCategoryKey:categoryKey] + stringByAppendingPathComponent:tf]]; success = YES; } } @@ -319,9 +323,6 @@ success = YES; } - [projectBrowser setPathForFile:toFile - category:[self categoryForKey:key]]; - [ff release]; [tf release]; diff --git a/Modules/BundleProject/PCBundleProject.m b/Modules/BundleProject/PCBundleProject.m index 51a96b8..e8741b8 100644 --- a/Modules/BundleProject/PCBundleProject.m +++ b/Modules/BundleProject/PCBundleProject.m @@ -76,6 +76,7 @@ - (void)dealloc { + NSLog(@"PCBundleProject: dealloc"); [rootCategories release]; [rootKeys release]; [rootEntries release]; diff --git a/Modules/RenaissanceProject/PCRenaissanceProject.m b/Modules/RenaissanceProject/PCRenaissanceProject.m index 1e40151..7f63474 100644 --- a/Modules/RenaissanceProject/PCRenaissanceProject.m +++ b/Modules/RenaissanceProject/PCRenaissanceProject.m @@ -99,7 +99,7 @@ - (void)dealloc { - NSLog (@"PCAppProject: dealloc"); + NSLog (@"PCRenaissanceProject: dealloc"); [[NSNotificationCenter defaultCenter] removeObserver:self]; @@ -139,8 +139,6 @@ - (NSArray *)fileTypesForCategoryKey:(NSString *)key { -// NSLog(@"fileTypesForCategoryKey: %@", key); - if ([key isEqualToString:PCClasses]) { return [NSArray arrayWithObjects:@"m",nil]; @@ -298,32 +296,37 @@ { NSString *mainNibFile = [projectDict objectForKey:PCMainInterfaceFile]; NSString *appIcon = [projectDict objectForKey:PCAppIcon]; - NSString *key = [self selectedRootCategoryKey]; + NSString *categoryKey = nil; NSString *ff = [fromFile copy]; NSString *tf = [toFile copy]; BOOL success = NO; + categoryKey = [self + keyForCategory:[projectBrowser nameOfSelectedRootCategory]]; + // Check for main NIB file - if ([key isEqualToString:PCInterfaces] + if ([categoryKey isEqualToString:PCInterfaces] && [fromFile isEqualToString:mainNibFile]) { [self clearMainNib:self]; if ([super renameFile:ff toFile:tf] == YES) { [self setMainNibWithFileAtPath: - [[self dirForCategoryKey:key] stringByAppendingPathComponent:tf]]; + [[self dirForCategoryKey:categoryKey] + stringByAppendingPathComponent:tf]]; success = YES; } } // Check for application icon files - else if ([key isEqualToString:PCImages] + else if ([categoryKey isEqualToString:PCImages] && [fromFile isEqualToString:appIcon]) { [self clearAppIcon:self]; if ([super renameFile:ff toFile:tf] == YES) { [self setAppIconWithImageAtPath: - [[self dirForCategoryKey:key] stringByAppendingPathComponent:tf]]; + [[self dirForCategoryKey:categoryKey] + stringByAppendingPathComponent:tf]]; success = YES; } } @@ -332,9 +335,6 @@ success = YES; } - [projectBrowser setPathForFile:toFile - category:[self categoryForKey:key]]; - [ff release]; [tf release]; diff --git a/PCMenuController.h b/PCMenuController.h index eead451..c853300 100644 --- a/PCMenuController.h +++ b/PCMenuController.h @@ -70,7 +70,6 @@ // Subproject - (void)subprojectNew:(id)sender; - (void)subprojectAdd:(id)sender; -- (void)subprojectRemove:(id)sender; // File - (void)fileNew:(id)sender; diff --git a/PCMenuController.m b/PCMenuController.m index ddb3fde..c315519 100644 --- a/PCMenuController.m +++ b/PCMenuController.m @@ -140,16 +140,7 @@ - (void)subprojectAdd:(id)sender { - NSString *proj = nil; - - // Show open panel - - [projectManager addSubprojectAt:proj]; -} - -- (void)subprojectRemove:(id)sender -{ - [projectManager removeSubproject]; + [projectManager addSubproject]; } // File @@ -371,8 +362,10 @@ - (BOOL)validateMenuItem:(id )menuItem { - NSString *menuTitle = [[menuItem menu] title]; - PCProject *aProject = [projectManager activeProject]; + NSString *menuTitle = [[menuItem menu] title]; + PCProject *aProject = [projectManager activeProject]; + PCProjectEditor *projectEditor = [aProject projectEditor]; + PCProjectBrowser *projectBrowser = [aProject projectBrowser]; if ([[projectManager loadedProjects] count] == 0) { @@ -456,10 +449,26 @@ // Project related menu items if ([menuTitle isEqualToString: @"Project"] - && [aProject selectedRootCategory] == nil) + && [projectBrowser nameOfSelectedFile] == nil + && [projectBrowser selectedFiles] == nil) + { + if ([[menuItem title] isEqualToString:@"Remove Files..."]) return NO; + } + if ([menuTitle isEqualToString: @"Project"] + && [[projectEditor allEditors] count] == 0) + { + if ([[menuItem title] isEqualToString:@"Save Files..."]) return NO; + } + if ([menuTitle isEqualToString: @"Project"] + && [projectBrowser nameOfSelectedCategory] == nil) { if ([[menuItem title] isEqualToString:@"Add Files..."]) return NO; - if ([[menuItem title] isEqualToString:@"Remove Files..."]) return NO; + if ([[menuItem title] isEqualToString:@"Add Subproject..."]) return NO; + } + if ([menuTitle isEqualToString: @"Project"] + && ![[projectBrowser nameOfSelectedRootCategory] isEqualToString:@"Subprojects"]) + { + if ([[menuItem title] isEqualToString:@"Add Subproject..."]) return NO; } // File related menu items @@ -474,7 +483,7 @@ if ([[menuItem title] isEqualToString:@"Close"]) return NO; } } - if ([[aProject projectBrowser] nameOfSelectedFile] == nil) + if ([projectBrowser nameOfSelectedFile] == nil) { if ([[menuItem title] isEqualToString:@"Rename"]) return NO; }