diff --git a/Documentation/TODO b/Documentation/TODO index 4f3671a..fd7400a 100644 --- a/Documentation/TODO +++ b/Documentation/TODO @@ -47,9 +47,9 @@ ProjectCenter 0.6 - Implement support for integrated debugging [90% done] - change project type from file to bundle casamento/mottola - Finish FileNameIcon (draggable, files can be dragged to it) [done!] -- Review all situations when dialogs must be popped up stoyan +- More options for file creation [done!] +- Review all situations when dialogs must be popped up [50% done] - Rewrite Preferences (3rd party sections etc.) stoyan -- More options for file creation stoyan --- Project Editor --------------------------------------------- - Implement indentation stoyan - Implement interaction with Builder (errors, warnings) stoyan diff --git a/English.lproj/Info.gorm/data.info b/English.lproj/Info.gorm/data.info index cc6bdca..da98e43 100644 Binary files a/English.lproj/Info.gorm/data.info and b/English.lproj/Info.gorm/data.info differ diff --git a/English.lproj/Info.gorm/objects.gorm b/English.lproj/Info.gorm/objects.gorm index a462553..8014d1c 100644 Binary files a/English.lproj/Info.gorm/objects.gorm and b/English.lproj/Info.gorm/objects.gorm differ diff --git a/Framework/English.lproj/NewFile.gorm/data.classes b/Framework/English.lproj/NewFile.gorm/data.classes index e82f40c..5d42cef 100644 --- a/Framework/English.lproj/NewFile.gorm/data.classes +++ b/Framework/English.lproj/NewFile.gorm/data.classes @@ -21,7 +21,8 @@ nfDescriptionTV, nfNameField, nfCancelButton, - nfCreateButton + nfCreateButton, + nfAddHeaderButton ); Super = NSObject; }; diff --git a/Framework/English.lproj/NewFile.gorm/data.info b/Framework/English.lproj/NewFile.gorm/data.info index e17240e..da98e43 100644 Binary files a/Framework/English.lproj/NewFile.gorm/data.info and b/Framework/English.lproj/NewFile.gorm/data.info differ diff --git a/Framework/English.lproj/NewFile.gorm/objects.gorm b/Framework/English.lproj/NewFile.gorm/objects.gorm index cbe0a41..8098a7b 100644 Binary files a/Framework/English.lproj/NewFile.gorm/objects.gorm and b/Framework/English.lproj/NewFile.gorm/objects.gorm differ diff --git a/Framework/English.lproj/NewSubproject.gorm/data.info b/Framework/English.lproj/NewSubproject.gorm/data.info index 0030663..da98e43 100644 Binary files a/Framework/English.lproj/NewSubproject.gorm/data.info and b/Framework/English.lproj/NewSubproject.gorm/data.info differ diff --git a/Framework/English.lproj/NewSubproject.gorm/objects.gorm b/Framework/English.lproj/NewSubproject.gorm/objects.gorm index 1df8c7b..045983a 100644 Binary files a/Framework/English.lproj/NewSubproject.gorm/objects.gorm and b/Framework/English.lproj/NewSubproject.gorm/objects.gorm differ diff --git a/Framework/PCFileCreator.m b/Framework/PCFileCreator.m index c9d4e58..bc5fc4e 100644 --- a/Framework/PCFileCreator.m +++ b/Framework/PCFileCreator.m @@ -46,50 +46,79 @@ static NSDictionary *dict = nil; NSDictionary *protocolDict; NSDictionary *gsmarkupDict; NSString *descr; + NSString *template; + NSBundle *bundle; _creator = [[[self class] alloc] init]; + bundle = [NSBundle bundleForClass:[self class]]; // Setting up the dictionary needed for registration! - descr = [NSString stringWithString:@"Generic Objective-C class.\n\nThis is a plain subclass of NSObject which includes only Foundation.h."]; - classDict = [NSDictionary dictionaryWithObjectsAndKeys: - _creator,@"Creator", - PCClasses,@"ProjectKey", - descr,@"TypeDescription", - nil]; - descr = [NSString stringWithString:@"Generic Objective-C header.\n\nThis is a plain interface subclassing NSObject. The file includes Foundation.h"]; + // Objective C Class + descr = [NSString stringWithString: + @"Generic Objective-C class.\n\nThis is a plain subclass of NSObject which includes only Foundation.h."]; + template = [bundle pathForResource:@"class" ofType:@"template"]; + classDict = [NSDictionary dictionaryWithObjectsAndKeys: + PCClasses, @"ProjectKey", + descr, @"TypeDescription", + template,@"TemplateFile", + nil]; + + // Objective C Header + descr = [NSString stringWithString: + @"Generic Objective-C header.\n\n" + "This is a plain interface subclassing NSObject." + " The file includes Foundation.h"]; + template = [bundle pathForResource:@"header" ofType:@"template"]; headerDict =[NSDictionary dictionaryWithObjectsAndKeys: - _creator,@"Creator", PCHeaders,@"ProjectKey", descr,@"TypeDescription", + template,@"TemplateFile", nil]; - descr = [NSString stringWithString:@"Generic ANSI-C implementation file.\n\nThis file contains no Objective-C dependency in any form."]; + // C File + descr = [NSString stringWithString: + @"Generic ANSI-C implementation file.\n\n" + "This file contains no Objective-C dependency in any form."]; + template = [bundle pathForResource:@"cfile" ofType:@"template"]; ccDict = [NSDictionary dictionaryWithObjectsAndKeys: - _creator,@"Creator", PCOtherSources,@"ProjectKey", descr,@"TypeDescription", + template,@"TemplateFile", nil]; - descr = [NSString stringWithString:@"Generic ANSI-C header.\n\nThis file contains no Objective-C dependency in any form."]; + // C Header + descr = [NSString stringWithString: + @"Generic ANSI-C header.\n\n" + "This file contains no Objective-C dependency in any form."]; + template = [bundle pathForResource:@"cheader" ofType:@"template"]; chDict = [NSDictionary dictionaryWithObjectsAndKeys: - _creator,@"Creator", PCHeaders,@"ProjectKey", descr,@"TypeDescription", + template,@"TemplateFile", nil]; - descr = [NSString stringWithString:@"Generic Objective-C protocol.\n\nThis is common Objective-C protocol, comparable i.e. to a Java interface."]; + // Objective C Protocol + descr = [NSString stringWithString: + @"Generic Objective-C protocol.\n\n" + "This is common Objective-C protocol, comparable" + " i.e. to a Java interface."]; + template = [bundle pathForResource:@"protocol" ofType:@"template"]; protocolDict = [NSDictionary dictionaryWithObjectsAndKeys: - _creator,@"Creator", PCHeaders,@"ProjectKey", descr,@"TypeDescription", + template,@"TemplateFile", nil]; - descr = [NSString stringWithString:@"Generic GSMarkup File.\n\nThis is the interface description of GNUstep Renaissance."]; + // GSMarkup + descr = [NSString stringWithString: + @"Generic GSMarkup File.\n\n" + "This is the interface description of GNUstep Renaissance."]; + template = [bundle pathForResource:@"gsmarkup" ofType:@"template"]; gsmarkupDict =[NSDictionary dictionaryWithObjectsAndKeys: - _creator,@"Creator", PCGSMarkupFiles,@"ProjectKey", descr,@"TypeDescription", + template, @"TemplateFile", nil]; @@ -103,6 +132,8 @@ static NSDictionary *dict = nil; nil]; } + [dict writeToFile:@"PCFileTypes.plist" atomically:NO]; + return _creator; } @@ -134,111 +165,109 @@ static NSDictionary *dict = nil; [self showNewFilePanel]; } -- (NSDictionary *)createFileOfType:(NSString *)type - path:(NSString *)path - project:(PCProject *)aProject +- (void)createFileOfType:(NSString *)fileType + path:(NSString *)path + project:(PCProject *)project +{ + NSDictionary *newFiles; + + newFiles = [self filesToCreateForFileOfType:fileType + path:path + withComplementary:YES]; + + [self createFiles:newFiles inProject:project]; +} + +- (NSDictionary *)filesToCreateForFileOfType:(NSString *)type + path:(NSString *)path + withComplementary:(BOOL)complementary { - PCFileManager *pcfm = [PCFileManager defaultManager]; - NSString *_file = nil; - NSString *newFile = nil; NSMutableDictionary *files = nil; - NSBundle *bundle = nil; + NSString *newFile = nil; // A class and possibly a header files = [NSMutableDictionary dictionaryWithCapacity:2]; - PCLogStatus(self, @"create %@ at %@", type, path); - - bundle = [NSBundle bundleForClass:[self class]]; - newFile = [path copy]; - // Remove file extension from "path" if (![[path pathExtension] isEqualToString: @""]) { path = [path stringByDeletingPathExtension]; } - /* - * Objective-C Class - */ + // Objective-C Class if ([type isEqualToString:ObjCClass]) { - _file = [bundle pathForResource:@"class" ofType:@"template"]; newFile = [path stringByAppendingPathExtension:@"m"]; - [pcfm copyFile:_file toFile:newFile]; - [self replaceTagsInFileAtPath:newFile withProject:aProject]; - [files setObject:ObjCClass forKey:newFile]; + [files setObject:[dict objectForKey:ObjCClass] forKey:newFile]; } - - /* - * Objective-C Header - * When creating Objective C Class file also create Objective C Header file - */ - if ([type isEqualToString:ObjCHeader] || - [type isEqualToString:ObjCClass]) + // C File + else if ([type isEqualToString:CFile]) { - _file = [bundle pathForResource:@"header" ofType:@"template"]; - newFile = [path stringByAppendingPathExtension:@"h"]; - [pcfm copyFile:_file toFile:newFile]; - [self replaceTagsInFileAtPath:newFile withProject:aProject]; - [files setObject:ObjCHeader forKey:newFile]; - } - - /* - * C File - */ - if ([type isEqualToString:CFile]) - { - _file = [bundle pathForResource:@"cfile" ofType:@"template"]; newFile = [path stringByAppendingPathExtension:@"c"]; - [pcfm copyFile:_file toFile:newFile]; - [self replaceTagsInFileAtPath:newFile withProject:aProject]; - [files setObject:CFile forKey:newFile]; + [files setObject:[dict objectForKey:CFile] forKey:newFile]; } - /* - * C Header - * When creating C file also create C Header file - */ + // C Header + // When creating C file also create C Header file if ([type isEqualToString:CHeader] || - [type isEqualToString:CFile]) + ([type isEqualToString:CFile] && complementary)) { - _file = [bundle pathForResource:@"cheader" ofType:@"template"]; newFile = [path stringByAppendingPathExtension:@"h"]; - [pcfm copyFile:_file toFile:newFile]; - [self replaceTagsInFileAtPath:newFile withProject:aProject]; - [files setObject:CHeader forKey:newFile]; + [files setObject:[dict objectForKey:CHeader] forKey:newFile]; } - /* - * GSMarkup - */ + // Objective-C Header + // When creating Objective C Class file also create Objective C Header file + else if ([type isEqualToString:ObjCHeader] || + ([type isEqualToString:ObjCClass] && complementary)) + { + newFile = [path stringByAppendingPathExtension:@"h"]; + [files setObject:[dict objectForKey:ObjCHeader] forKey:newFile]; + } + // GSMarkup else if ([type isEqualToString:GSMarkupFile]) { - _file = [bundle pathForResource:@"gsmarkup" ofType:@"template"]; newFile = [path stringByAppendingPathExtension:@"gsmarkup"]; - [pcfm copyFile:_file toFile:newFile]; - [files setObject:GSMarkupFile forKey:newFile]; + [files setObject:[dict objectForKey:GSMarkupFile] forKey:newFile]; } - /* - * Objective-C Protocol - */ + // Objective-C Protocol else if ([type isEqualToString:ProtocolFile]) { - _file = [bundle pathForResource:@"protocol" ofType:@"template"]; newFile = [path stringByAppendingPathExtension:@"h"]; - [pcfm copyFile:_file toFile:newFile]; - [self replaceTagsInFileAtPath:newFile withProject:aProject]; - [files setObject:ProtocolFile forKey:newFile]; + [files setObject:[dict objectForKey:ProtocolFile] forKey:newFile]; } - /* - * Notify the browser! - */ + return files; +} + +- (BOOL)createFiles:(NSDictionary *)fileList + inProject:(PCProject *)aProject +{ + PCFileManager *pcfm = [PCFileManager defaultManager]; + NSEnumerator *enumerator = [[fileList allKeys] objectEnumerator]; + NSString *template = nil; + NSString *newFile = nil; + NSDictionary *fileType = nil; + NSString *key = nil; + + while ((newFile = [enumerator nextObject])) + { + fileType = [fileList objectForKey:newFile]; + key = [fileType objectForKey:@"ProjectKey"]; + template = [fileType objectForKey:@"TemplateFile"]; + + [pcfm copyFile:template toFile:newFile]; + [self replaceTagsInFileAtPath:newFile withProject:aProject]; + [aProject addFiles:[NSArray arrayWithObject:newFile] + forKey:key + notify:YES]; + } + + // Notify the browser! [[NSNotificationCenter defaultCenter] postNotificationName:@"ProjectDictDidChangeNotification" object:self]; - return files; + return YES; } - (void)replaceTagsInFileAtPath:(NSString *)newFile @@ -321,7 +350,6 @@ static NSDictionary *dict = nil; { [newFilePanel center]; } - [newFilePanel center]; [nfImage setImage:[NSApp applicationIconImage]]; [nfTypePB setRefusesFirstResponder:YES]; [nfTypePB removeAllItems]; @@ -329,8 +357,9 @@ static NSDictionary *dict = nil; [[dict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]]; [nfTypePB selectItemAtIndex:0]; - [nfCancleButton setRefusesFirstResponder:YES]; + [nfCancelButton setRefusesFirstResponder:YES]; [nfCreateButton setRefusesFirstResponder:YES]; + [nfAddHeaderButton setRefusesFirstResponder:YES]; [newFilePanel setDefaultButtonCell:[nfCreateButton cell]]; } @@ -339,29 +368,50 @@ static NSDictionary *dict = nil; [newFilePanel makeKeyAndOrderFront:self]; [nfNameField setStringValue:@""]; [newFilePanel makeFirstResponder:nfNameField]; + + [newFilePanel setLevel:NSModalPanelWindowLevel]; + [NSApp runModalForWindow:newFilePanel]; } - (void)closeNewFilePanel:(id)sender { [newFilePanel orderOut:self]; + [NSApp stopModal]; + activeProject = nil; } - (void)createFile:(id)sender { - [self createFile]; - [self closeNewFilePanel:self]; - activeProject = nil; + if ([self createFile]) + { + [self closeNewFilePanel:self]; + } + else + { + [newFilePanel makeKeyAndOrderFront:self]; + } } - (void)newFilePopupChanged:(id)sender { - NSString *type = [sender titleOfSelectedItem]; - NSDictionary *creator = [dict objectForKey:type]; + NSString *typeTitle = [sender titleOfSelectedItem]; + NSDictionary *fileType = [dict objectForKey:typeTitle]; - if (type) + if (!fileType) { - [nfDescriptionTV setString:[creator objectForKey:@"TypeDescription"]]; + return; + } + + [nfDescriptionTV setString:[fileType objectForKey:@"TypeDescription"]]; + if ([typeTitle isEqualToString:ObjCClass] || + [typeTitle isEqualToString:CFile]) + { + [nfAddHeaderButton setEnabled:YES]; + } + else + { + [nfAddHeaderButton setEnabled:NO]; } } @@ -383,52 +433,72 @@ static NSDictionary *dict = nil; } } -- (void)createFile +- (BOOL)createFile { - NSString *path = nil; - NSString *fileName = [nfNameField stringValue]; - NSString *fileType = [nfTypePB titleOfSelectedItem]; - NSDictionary *fileDict = [dict objectForKey:fileType]; - NSString *projectKey = [fileDict objectForKey:@"ProjectKey"]; + NSString *fileName = [nfNameField stringValue]; + NSString *fileType = [nfTypePB titleOfSelectedItem]; + NSString *path = nil; + NSString *key = nil; + NSDictionary *newFiles = nil; + NSEnumerator *enumerator = nil; + NSString *filePath = nil; + NSFileManager *fm = [NSFileManager defaultManager]; -// PCLogInfo(self, @"[createFile] %@", fileName); - - if ([activeProject doesAcceptFile:fileName forKey:projectKey]) - { - path = [[activeProject projectPath] - stringByAppendingPathComponent:fileName]; - } - -// PCLogInfo(self, @"creating file at %@", path); +/* NSLog(@"PCFileCreator: [createFile] %@ in category: %@", + fileName, projectKey);*/ + path = [[activeProject projectPath] stringByAppendingPathComponent:fileName]; // Create file if (path) { - NSDictionary *newFiles = nil; - NSEnumerator *enumerator; - NSString *aFile; + // Get file list for creation + newFiles = [self + filesToCreateForFileOfType:fileType + path:path + withComplementary:[nfAddHeaderButton state]==NSOnState ? YES : NO]; - // Do it finally... - newFiles = [self createFileOfType:fileType - path:path - project:activeProject]; - - // Add files to a project + // Check if project already has files with such names enumerator = [[newFiles allKeys] objectEnumerator]; - while ((aFile = [enumerator nextObject])) + while ((filePath = [enumerator nextObject])) { - fileType = [newFiles objectForKey:aFile]; - fileDict = [dict objectForKey:fileType]; - projectKey = [fileDict objectForKey:@"ProjectKey"]; - - if ([activeProject doesAcceptFile:aFile forKey:projectKey]) + key = [[newFiles objectForKey:filePath] objectForKey:@"ProjectKey"]; + fileName = [filePath lastPathComponent]; + if (![activeProject doesAcceptFile:fileName forKey:key]) { - [activeProject addFiles:[NSArray arrayWithObject:aFile] - forKey:projectKey - notify:YES]; + NSRunAlertPanel(@"New File in Project", + @"Project %@ already has file %@ in %@", + @"OK", nil, nil, + [activeProject projectName], fileName, key); + return NO; + } + if ([fm fileExistsAtPath:filePath]) + { + int ret; + + ret = NSRunAlertPanel + (@"New File in Project", + @"Project directory %@ already has file %@.\n" + "Do you want to overwrite it?", + @"Stop", @"Overwrite", nil, + [filePath stringByDeletingLastPathComponent], + fileName); + + if (ret == NSAlertDefaultReturn) // Stop + { + return NO; + } + else // Overwrite. Remove destination of copy operation + { + [fm removeFileAtPath:filePath handler:nil]; + } } } + + // Create files + return [self createFiles:newFiles inProject:activeProject]; } + + return NO; } @end diff --git a/Framework/PCProject.m b/Framework/PCProject.m index cc6f4db..6cf86f0 100644 --- a/Framework/PCProject.m +++ b/Framework/PCProject.m @@ -489,7 +489,7 @@ NSString { int ret; - ret = NSRunAlertPanel(@"Alert", + ret = NSRunAlertPanel(@"Close Project", @"Project or subprojects are modified", @"Save and Close",@"Don't save",@"Cancel"); switch (ret) @@ -1145,9 +1145,9 @@ NSString { if (![fileManager copyFiles:fileList intoDirectory:directory]) { - NSRunAlertPanel(@"Alert", - @"Error adding files to project %@!", - @"OK", nil, nil, projectName); + NSRunAlertPanel(@"Add File(s)", + @"Error adding files %@ to project %@!", + @"OK", nil, nil, fileList, projectName); return NO; } @@ -1156,9 +1156,9 @@ NSString if (![fileManager copyFiles:complementaryFiles intoDirectory:complementaryDir]) { - NSRunAlertPanel(@"Alert", - @"Error adding complementary files to project %@!", - @"OK", nil, nil, projectName); + NSRunAlertPanel(@"Add File(s)", + @"Error adding files %@ to project %@!", + @"OK", nil, nil, complementaryFiles, projectName); return NO; } } diff --git a/Framework/PCProjectManager.m b/Framework/PCProjectManager.m index 4811fef..71239c7 100644 --- a/Framework/PCProjectManager.m +++ b/Framework/PCProjectManager.m @@ -734,7 +734,7 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; if (!(project = [self createProjectOfType:projectType path:filePath])) { - NSRunAlertPanel(@"Attention!", + NSRunAlertPanel(@"New Project", @"Failed to create %@!", @"OK",nil,nil,filePath); } @@ -759,7 +759,7 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; // Save PC.project and the makefiles! if ([rootProject save] == NO) { - NSRunAlertPanel(@"Attention!", + NSRunAlertPanel(@"Save Project", @"Couldn't save project %@!", @"OK",nil,nil,[activeProject projectName]); return NO; @@ -857,7 +857,7 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; if ([categoryKey isEqualToString:PCLibraries]) { - ret = NSRunAlertPanel(@"Remove", + ret = NSRunAlertPanel(@"Remove File", @"Remove libraries from Project?", @"Remove", @"Cancel", @@ -865,7 +865,7 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; } else { - ret = NSRunAlertPanel(@"Remove", + ret = NSRunAlertPanel(@"Remove File", removeString, @"...from Project and Disk", @"...from Project only", @@ -900,7 +900,7 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; if (!ret) { - NSRunAlertPanel(@"Alert", + NSRunAlertPanel(@"Remove File", @"Error removing files from project %@!", @"OK", nil, nil, [activeProject projectName]); return NO; @@ -908,7 +908,7 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; else if (flag) { // Save project because we've removed file(s) from disk - // Should be fixed later (add pending removal of files?) + // TODO: Should be fixed later (add pending removal of files?) [activeProject save]; } } @@ -1161,17 +1161,21 @@ NSString *PCActiveProjectDidChangeNotification = @"PCActiveProjectDidChange"; [nsNameField setStringValue:@""]; [nsPanel makeFirstResponder:nsNameField]; + [nsPanel setLevel:NSModalPanelWindowLevel]; + [NSApp runModalForWindow:nsPanel]; + return YES; } - (void)closeNewSubprojectPanel:(id)sender { [nsPanel orderOut:self]; + [NSApp stopModal]; } - (BOOL)createSubproject:(id)sender { - [nsPanel orderOut:self]; + [self closeNewSubprojectPanel:self]; return [self createSubproject]; } diff --git a/Headers/ProjectCenter/PCFileCreator.h b/Headers/ProjectCenter/PCFileCreator.h index f6e3ae5..58d49ae 100644 --- a/Headers/ProjectCenter/PCFileCreator.h +++ b/Headers/ProjectCenter/PCFileCreator.h @@ -48,8 +48,9 @@ IBOutlet NSPopUpButton *nfTypePB; IBOutlet NSTextView *nfDescriptionTV; IBOutlet NSTextField *nfNameField; - IBOutlet NSButton *nfCancleButton; + IBOutlet NSButton *nfCancelButton; IBOutlet NSButton *nfCreateButton; + IBOutlet NSButton *nfAddHeaderButton; } + (id)sharedCreator; @@ -57,10 +58,17 @@ - (NSDictionary *)creatorDictionary; - (void)newFileInProject:(PCProject *)aProject; -// The implementation needs some heavy cleanup! -- (NSDictionary *)createFileOfType:(NSString *)type - path:(NSString *)path - project:(PCProject *)aProject; + +- (void)createFileOfType:(NSString *)fileType + path:(NSString *)path + project:(PCProject *)project; + +// Return list of file paths for creation +- (NSDictionary *)filesToCreateForFileOfType:(NSString *)type + path:(NSString *)path + withComplementary:(BOOL)complementary; +- (BOOL)createFiles:(NSDictionary *)fileList + inProject:(PCProject *)aProject; - (void)replaceTagsInFileAtPath:(NSString *)newFile withProject:(PCProject *)aProject; @@ -74,7 +82,7 @@ - (void)createFile:(id)sender; - (void)newFilePopupChanged:(id)sender; - (void)controlTextDidChange:(NSNotification *)aNotif; -- (void)createFile; +- (BOOL)createFile; @end