/* PaletteProjectType.m Implementation of the PaletteProjectType class for the ProjectManager application. Copyright (C) 2005, 2006 Saso Kiselkov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #import "PaletteProjectType.h" #import #import #import #import #import #import #import #import #import #import #import "../../CommonFunctions/MakefileChecking.h" #import "../../ProjectDocument.h" #import "../../ProjectModule.h" #import "../../ProjectModules/FileManager/FileManager.h" #import "../../ProjectModules/MakeBuilder/MakeBuilder.h" #import "../../ProjectModules/SubprojectsManager/SubprojectsManager.h" #import "../../NSImageAdditions.h" #import "PaletteGeneralAttributes.h" static inline void InsertMakefileVariable(NSMutableString * makefileString, NSString * name, NSString * value) { [makefileString appendString: [NSString stringWithFormat: @"\n" @"%@ = %@\n", name, value]]; } static void InsertMakefileEnumerationVariable(NSMutableString * makefileString, NSString * name, NSArray * values) { NSEnumerator * e; NSString * value; [makefileString appendString: [NSString stringWithFormat: @"\n" @"%@ = ", name]]; e = [values objectEnumerator]; while ((value = [e nextObject]) != nil) { [makefileString appendString: [NSString stringWithFormat: @"%@ \\\n", value]]; } } /** * Returns a string containg `string' prefixed with a '/' character. */ static inline NSString * PreSlash(NSString * string) { return [NSString stringWithFormat: @"/%@", string]; } static NSString * const ClassFilesCategoryName = @"Class Files", * const HeaderFilesCategoryName = @"Header Files", * const OtherSourceFilesCategoryName = @"Other Source Files", * const InterfaceFilesCategoryName = @"Interfaces", * const ResourceFilesCategoryName = @"Resource Files", * const LocalizedResourceFilesCategoryName = @"Localized Resource Files", * const SupportingFilesCategoryName = @"Supporting Files", * const FrameworksCategoryName = @"Frameworks"; @interface PaletteProjectType (Private) + (void) loadCategoryIcons; - (BOOL) prepareMakefile; - (BOOL) prepareInfoFile; - (BOOL) preparePaletteTableFile; @end static NSImage * ClassFilesIcon = nil, * HeaderFilesIcon = nil, * InterfaceFilesIcon = nil, * OtherSourceFilesIcon = nil, * ResourceFilesIcon = nil, * LocalizedResourceFilesIcon = nil, * SupportingFilesIcon = nil; @implementation PaletteProjectType (Private) /** * Loads all icons for standard categories. */ + (void) loadCategoryIcons { NSBundle * myBundle = [NSBundle bundleForClass: self]; ASSIGN(ClassFilesIcon, [NSImage imageNamed: @"ClassFiles" owner: self]); ASSIGN(HeaderFilesIcon, [NSImage imageNamed: @"HeaderFiles" owner: self]); ASSIGN(InterfaceFilesIcon, [NSImage imageNamed: @"InterfaceFiles" owner: self]); ASSIGN(OtherSourceFilesIcon, [NSImage imageNamed: @"OtherSourceFiles" owner: self]); ASSIGN(ResourceFilesIcon, [NSImage imageNamed: @"ResourceFiles" owner: self]); ASSIGN(LocalizedResourceFilesIcon, [NSImage imageNamed: @"LocalizedResourceFiles" owner: self]); ASSIGN(SupportingFilesIcon, [NSImage imageNamed: @"SupportingFiles" owner: self]); } /** * Prepares the project's makefile. */ - (BOOL) prepareMakefile { NSString * buildDir = [owner projectDirectory]; NSString * makefile = [buildDir stringByAppendingPathComponent: @"GNUmakefile"]; NSMutableString * makefileString = [NSMutableString string]; NSString * projectName = [owner projectName]; NSMutableSet * languages; NSMutableSet * localizedResourceFiles; if (oldMakeHash != 0) { if (oldMakeHash != ComputeHashFromMakefile(makefile)) { switch (NSRunAlertPanel(_(@"Warning: GNUmakefile changed"), _(@"It seems the build settings in the GNUmakefile have been\n" @"edited since I've last regenerated it. You shouldn't do\n" @"this. Please, put build customizations in GNUmakefile." @"preamble\n" @"or GNUmakefile.postamble. For now, I can backup your current\n" @"GNUmakefile (it will be named GNUmakefile~) or overwrite it."), _(@"Back it up"), _(@"Overwrite"), _(@"Cancel"))) { case NSAlertDefaultReturn: if (![[NSFileManager defaultManager] movePath: makefile toPath: [makefile stringByAppendingString: @"~"] handler: nil]) { NSRunAlertPanel(_(@"Backup failed"), _(@"Failed to move the old GNUmakefile to GNUmakefile~.\n" @"Safety stop."), nil, nil, nil); return NO; } break; case NSAlertAlternateReturn: break; case NSAlertOtherReturn: return NO; } } } [makefileString appendString: [NSString stringWithContentsOfFile: [[NSBundle bundleForClass: [self class]] pathForResource: @"MakefileEditWarning" ofType: @"txt"]]]; [makefileString appendString: @"\n" @"include $(GNUSTEP_MAKEFILES)/common.make\n"]; // prepend some definitions to turn on compiler warnings as necessary [makefileString appendString: @"\n" @"ifeq ($(warnings), yes)\n" @"ADDITIONAL_OBJCFLAGS += -W\n" @"ADDITIONAL_OBJCPPFLAGS += -W\n" @"ADDITIONAL_CFLAGS += -W\n" @"ADDITIONAL_CPPFLAGS += -W\n" @"endif\n" @"ifeq ($(allwarnings), yes)\n" @"ADDITIONAL_OBJCFLAGS += -Wall\n" @"ADDITIONAL_OBJCPPFLAGS += -Wall\n" @"ADDITIONAL_CFLAGS += -Wall\n" @"ADDITIONAL_CPPFLAGS += -Wall\n" @"endif\n"]; InsertMakefileVariable(makefileString, @"PALETTE_NAME", projectName); // OBJC_FILES, OBJCC_FILES and C_FILES { NSArray * sourceFiles = [[fileManager filesAtPath: PreSlash(ClassFilesCategoryName) ofType: FMFileTypePlain recursive: YES] arrayByAddingObjectsFromArray: [fileManager filesAtPath: PreSlash(OtherSourceFilesCategoryName) ofType: FMFileTypePlain recursive: YES]]; unsigned int n = [sourceFiles count]; NSMutableArray * objcFiles = [NSMutableArray arrayWithCapacity: n], * objccFiles = [NSMutableArray arrayWithCapacity: n], * cFiles = [NSMutableArray arrayWithCapacity: n]; NSEnumerator * e; NSString * filename; // filter out files by extension e = [sourceFiles objectEnumerator]; while ((filename = [e nextObject]) != nil) { if (![[filename pathExtension] caseInsensitiveCompare: @"m"]) { [objcFiles addObject: filename]; } else if (![[filename pathExtension] caseInsensitiveCompare: @"mm"]) { [objccFiles addObject: filename]; } else if (![[filename pathExtension] caseInsensitiveCompare: @"c"]) { [cFiles addObject: filename]; } } InsertMakefileEnumerationVariable(makefileString, [NSString stringWithFormat: @"%@_OBJC_FILES", projectName], objcFiles); InsertMakefileEnumerationVariable(makefileString, [NSString stringWithFormat: @"%@_OBJCC_FILES", projectName], objccFiles); InsertMakefileEnumerationVariable(makefileString, [NSString stringWithFormat: @"%@_C_FILES", projectName], cFiles); } // RESOURCE_FILES { NSArray * files = [fileManager filesAtPath: PreSlash(ResourceFilesCategoryName) ofType: FMFileTypePlain recursive: YES]; NSMutableArray * resourceFiles = [NSMutableArray arrayWithCapacity: [files count]]; NSEnumerator * e; NSString * filename; e = [files objectEnumerator]; while ((filename = [e nextObject]) != nil) { [resourceFiles addObject: [@"Resources" stringByAppendingPathComponent: filename]]; } InsertMakefileEnumerationVariable(makefileString, [NSString stringWithFormat: @"%@_RESOURCE_FILES", projectName], resourceFiles); } // LANGUAGES languages = [[NSMutableSet new] autorelease]; [languages addObjectsFromArray: [fileManager filesAtPath: PreSlash(LocalizedResourceFilesCategoryName) ofType: FMFileTypeCategory recursive: YES]]; [languages addObjectsFromArray: [fileManager filesAtPath: PreSlash(InterfaceFilesCategoryName) ofType: FMFileTypeCategory recursive: YES]]; InsertMakefileEnumerationVariable(makefileString, [NSString stringWithFormat: @"%@_LANGUAGES", projectName], [languages allObjects]); // LOCALIZED_RESOURCE_FILES localizedResourceFiles = [[NSMutableSet new] autorelease]; [localizedResourceFiles addObjectsFromArray: [fileManager filesAtPath: PreSlash(LocalizedResourceFilesCategoryName) ofType: FMFileTypePlain recursive: YES]]; [localizedResourceFiles addObjectsFromArray: [fileManager filesAtPath: PreSlash(InterfaceFilesCategoryName) ofType: FMFileTypePlain recursive: YES]]; InsertMakefileEnumerationVariable(makefileString, [NSString stringWithFormat: @"%@_LOCALIZED_RESOURCE_FILES", projectName], [localizedResourceFiles allObjects]); if (mainNibFile != nil) { InsertMakefileVariable(makefileString, [NSString stringWithFormat: @"%@_MAIN_MODEL_FILE", projectName], mainNibFile); } if (iconName != nil) { InsertMakefileVariable(makefileString, [NSString stringWithFormat: @"%@_PALETTE_ICON", projectName], iconName); } if (principalClass != nil) { InsertMakefileVariable(makefileString, [NSString stringWithFormat: @"%@_PRINCIPAL_CLASS", projectName], principalClass); } { NSMutableArray * frameworks; NSArray * origFrameworks; NSString * framework; NSEnumerator * e; origFrameworks = [fileManager filesAtPath: PreSlash(FrameworksCategoryName) ofType: FMFileTypeVirtual recursive: YES]; frameworks = [NSMutableArray arrayWithCapacity: [origFrameworks count]]; e = [origFrameworks objectEnumerator]; while ((framework = [e nextObject]) != nil) { if (![framework isEqualToString: @"Foundation.framework"] && ![framework isEqualToString: @"AppKit.framework"]) { // strip an initial 'lib' prefix if ([framework hasPrefix: @"lib"]) { framework = [framework stringByDeletingPrefix: @"lib"]; } [frameworks addObject: [NSString stringWithFormat: @"-l%@", [framework stringByDeletingPathExtension]]]; } } InsertMakefileEnumerationVariable(makefileString, @"ADDITIONAL_LDFLAGS", frameworks); } // SUBPROJECTS { SubprojectsManager * subprojectsManager = [owner projectModuleWithName: @"SubprojectsManager"]; NSArray * subprojectNames = [subprojectsManager subprojectNames]; NSEnumerator * e; NSString * subprojectName; NSMutableArray * subprojects = [NSMutableArray arrayWithCapacity: [subprojectNames count]]; e = [subprojectNames objectEnumerator]; while ((subprojectName = [e nextObject]) != nil) { [subprojects addObject: [@"Subprojects" stringByAppendingPathComponent: subprojectName]]; } InsertMakefileEnumerationVariable(makefileString, @"SUBPROJECTS", subprojects); } [makefileString appendString: @"\n" @"-include GNUmakefile.preamble\n" @"include $(GNUSTEP_MAKEFILES)/palette.make\n" @"include $(GNUSTEP_MAKEFILES)/aggregate.make\n" @"-include GNUmakefile.postamble\n"]; oldMakeHash = ComputeHashFromMakeString(makefileString); return [makefileString writeToFile: makefile atomically: NO]; } /** * Prepares the project's info-plist file. */ - (BOOL) prepareInfoFile { NSString * infoPath = [[owner projectDirectory] stringByAppendingPathComponent: [[[owner projectName] stringByAppendingString: @"Info"] stringByAppendingPathExtension: @"plist"]]; NSMutableDictionary * infoDict; // try reading in an already existant Info.plist file infoDict = [[[NSDictionary dictionaryWithContentsOfFile: infoPath] mutableCopy] autorelease]; if (infoDict == nil) { infoDict = [NSMutableDictionary dictionary]; } [infoDict setObject: [owner projectName] forKey: @"PaletteName"]; if (authors != nil) { [infoDict setObject: authors forKey: @"Authors"]; } if (copyright != nil) { [infoDict setObject: copyright forKey: @"Copyright"]; } if (copyrightDescription != nil) { [infoDict setObject: copyrightDescription forKey: @"CopyrightDescription"]; } if (iconName != nil) { [infoDict setObject: iconName forKey: @"Icon"]; [infoDict setObject: iconName forKey: @"NSIcon"]; } return [infoDict writeToFile: infoPath atomically: YES]; } - (BOOL) preparePaletteTableFile { NSString * filename = [[owner projectDirectory] stringByAppendingPathComponent: [NSString stringWithFormat: @"%@palette.table", [owner projectName]]]; NSMutableDictionary * paletteDict; // try reading in an already existant palette.table file paletteDict = [[[NSDictionary dictionaryWithContentsOfFile: filename] mutableCopy] autorelease]; if (paletteDict == nil) { paletteDict = [NSMutableDictionary dictionary]; } if (exportedClasses != nil) { [paletteDict setObject: exportedClasses forKey: @"ExportedClasses"]; } return [paletteDict writeToFile: filename atomically: YES]; } @end @implementation PaletteProjectType + (NSString *) projectTypeID { return @"Palette"; } + (NSString *) humanReadableProjectTypeName { return _(@"Gorm Palette"); } + (NSString *) projectTypeDescription { return [NSString stringWithContentsOfFile: [[NSBundle bundleForClass: self] pathForResource: @"Description" ofType: @"txt"]]; } + (NSImage *) projectTypeIcon { static NSImage * icon = nil; if (icon == nil) { ASSIGN(icon, [NSImage imageNamed: @"PaletteProjectType" owner: self]); } return icon; } + (NSArray *) projectModules { return [NSArray arrayWithObjects: @"ProjectAttributes", @"FileManager", @"MakeBuilder", // @"ProjectIndexer", @"SubprojectsManager", nil]; } + (NSDictionary *) projectTemplateDescriptions { return [NSDictionary dictionaryWithObjectsAndKeys: PMCreateTemplateDescription(_(@"A standard palette with a principal " @"class defined and a main Gorm file."), [NSImage imageNamed: @"PaletteProjectType" owner: self]), _(@"Standard Palette"), nil]; } + (NSString *) pathToProjectTemplate: (NSString *) templateName { NSBundle * myBundle = [NSBundle bundleForClass: self]; return [myBundle pathForResource: @"StandardPalette" ofType: @"template"]; } - initWithDocument: (ProjectDocument *) anOwner infoDictionary: (NSDictionary *) infoDict projectModules: (NSArray *) projectModules { if ((self = [self init]) != nil) { NSNotificationCenter * nc = [NSNotificationCenter defaultCenter]; owner = anOwner; ASSIGN(mainNibFile, [infoDict objectForKey: @"MainNibFile"]); ASSIGN(principalClass, [infoDict objectForKey: @"PrincipalClass"]); ASSIGN(authors, [NSArray arrayWithArray: [infoDict objectForKey: @"Authors"]]); ASSIGN(copyright, [infoDict objectForKey: @"Copyright"]); ASSIGN(copyrightDescription, [infoDict objectForKey: @"CopyrightDescription"]); ASSIGN(iconName, [infoDict objectForKey: @"IconName"]); ASSIGN(authors, [NSArray arrayWithArray: [infoDict objectForKey: @"ExportedClasses"]]); ASSIGN(fileManager, [owner projectModuleWithName: @"FileManager"]); ASSIGN(builder, [owner projectModuleWithName: @"MakeBuilder"]); oldMakeHash = [[infoDict objectForKey: @"MakefileHash"] intValue]; } return self; } - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; TEST_RELEASE(mainNibFile); TEST_RELEASE(principalClass); TEST_RELEASE(authors); TEST_RELEASE(copyright); TEST_RELEASE(copyrightDescription); TEST_RELEASE(iconName); TEST_RELEASE(exportedClasses); TEST_RELEASE(generalAttributes); TEST_RELEASE(fileManager); TEST_RELEASE(builder); [super dealloc]; } - (NSDictionary *) infoDictionary { NSMutableDictionary * dict = [NSMutableDictionary dictionary]; if (mainNibFile != nil) { [dict setObject: mainNibFile forKey: @"MainNibFile"]; } if (principalClass != nil) { [dict setObject: principalClass forKey: @"PrincipalClass"]; } [dict setObject: authors forKey: @"Authors"]; if (copyright != nil) { [dict setObject: copyright forKey: @"Copyright"]; } if (copyrightDescription != nil) { [dict setObject: copyrightDescription forKey: @"CopyrightDescription"]; } if (iconName != nil) { [dict setObject: iconName forKey: @"IconName"]; } if (exportedClasses != nil) { [dict setObject: exportedClasses forKey: @"ExportedClasses"]; } [dict setObject: [NSNumber numberWithInt: oldMakeHash] forKey: @"MakefileHash"]; return dict; } - (BOOL) regenerateDerivedFiles { return [self prepareMakefile] && [self prepareInfoFile] && [self preparePaletteTableFile]; } - (NSString *) pathToSubprojectsDirectory { return [[owner projectDirectory] stringByAppendingPathComponent: @"Subprojects"]; } - (BOOL) canCreateCategoriesAtPath: (NSString *) aPath { return YES; } - (BOOL) canCreatePlainFilesAtPath: (NSString *) aPath { aPath = [aPath stringByStandardizingPath]; // don't allow creating plain files in the following categories: // - "/" // - "/Interfaces" // - "/Localized Resource Files" // - "/Frameworks" and any of it's descendents if ([aPath isEqualToString: @"/"] || [aPath isEqualToString: PreSlash(InterfaceFilesCategoryName)] || [aPath isEqualToString: PreSlash(LocalizedResourceFilesCategoryName)] || [aPath hasPrefix: PreSlash(FrameworksCategoryName)]) { return NO; } else { return YES; } } - (BOOL) canCreateLinksAtPath: (NSString *) aPath { // same rules for links as for plain files return [self canCreatePlainFilesAtPath: aPath]; } - (BOOL) canCreateVirtualFilesAtPath: (NSString *) aPath { // allow creating virtual files only in the /Frameworks category // and it's subcategories return [aPath hasPrefix: PreSlash(FrameworksCategoryName)]; } - (BOOL) canDeletePath: (NSString *) aPath { aPath = [aPath stringByStandardizingPath]; // don't allow deleting any of the mandatory top-level categories // and the AppKit and Foundation frameworks if ([aPath isEqualToString: PreSlash(ClassFilesCategoryName)] || [aPath isEqualToString: PreSlash(HeaderFilesCategoryName)] || [aPath isEqualToString: PreSlash(OtherSourceFilesCategoryName)] || [aPath isEqualToString: PreSlash(InterfaceFilesCategoryName)] || [aPath isEqualToString: PreSlash(ResourceFilesCategoryName)] || [aPath isEqualToString: PreSlash(LocalizedResourceFilesCategoryName)] || [aPath isEqualToString: PreSlash(SupportingFilesCategoryName)] || [aPath isEqualToString: PreSlash(FrameworksCategoryName)] || [aPath isEqualToString: @"/Frameworks/AppKit.framework"] || [aPath isEqualToString: @"/Frameworks/Foundation.framework"]) { return NO; } else { return YES; } } - (FileOpenResult) openFile: (NSString *) aPath { // TODO return FileOpenCannotHandle; } - (NSString *) pathToFile: (NSString *) fileName isCategory: (BOOL) isCategory { NSArray * pathComponents; NSString * path; if ([fileName hasPrefix: PreSlash(ClassFilesCategoryName)] || [fileName hasPrefix: PreSlash(HeaderFilesCategoryName)] || [fileName hasPrefix: PreSlash(OtherSourceFilesCategoryName)] || [fileName hasPrefix: PreSlash(SupportingFilesCategoryName)]) { path = [owner projectDirectory]; } else if ([fileName hasPrefix: PreSlash(ResourceFilesCategoryName)]) { path = [[owner projectDirectory] stringByAppendingPathComponent: @"Resources"]; } else if ([fileName hasPrefix: PreSlash(InterfaceFilesCategoryName)] || [fileName hasPrefix: PreSlash(LocalizedResourceFilesCategoryName)]) { NSArray * pathComponents = [fileName pathComponents]; // we need at least 3 path components here - the last one indicates // the language if ([pathComponents count] >= 3) { path = [[owner projectDirectory] stringByAppendingPathComponent: [NSString stringWithFormat: @"%@.lproj", [pathComponents objectAtIndex: 2]]]; } else { path = nil; } } else if ([fileName hasPrefix: PreSlash(FrameworksCategoryName)]) { path = nil; } else { path = [[owner projectDirectory] stringByAppendingPathComponent: @"OtherFiles"]; } if (isCategory == NO) { path = [path stringByAppendingPathComponent: [fileName lastPathComponent]]; } return path; } - (NSImage *) iconForPath: (NSString *) aPath { if (ClassFilesIcon == nil) { [[self class] loadCategoryIcons]; } if ([aPath isEqualToString: PreSlash(ClassFilesCategoryName)]) { return ClassFilesIcon; } else if ([aPath isEqualToString: PreSlash(HeaderFilesCategoryName)]) { return HeaderFilesIcon; } else if ([aPath isEqualToString: PreSlash(InterfaceFilesCategoryName)]) { return InterfaceFilesIcon; } else if ([aPath isEqualToString: PreSlash(OtherSourceFilesCategoryName)]) { return OtherSourceFilesIcon; } else if ([aPath isEqualToString: PreSlash(ResourceFilesCategoryName)]) { return ResourceFilesIcon; } else if ([aPath isEqualToString: PreSlash(LocalizedResourceFilesCategoryName)]) { return LocalizedResourceFilesIcon; } else if ([aPath isEqualToString: PreSlash(SupportingFilesCategoryName)]) { return SupportingFilesIcon; } else { return nil; } } - (NSArray *) permissibleFileExtensionsInCategory: (NSString *) category { if ([category hasPrefix: PreSlash(ClassFilesCategoryName)]) { return [NSArray arrayWithObjects: @"m", @"mm", @"cc", @"cpp", @"java", nil]; } else if ([category hasPrefix: PreSlash(OtherSourceFilesCategoryName)]) { return [NSArray arrayWithObjects: @"c", @"m", @"mm", @"cc", @"cpp", @"java", nil]; } else if ([category hasPrefix: PreSlash(HeaderFilesCategoryName)]) { return [NSArray arrayWithObject: @"h"]; } else if ([category hasPrefix: PreSlash(InterfaceFilesCategoryName)]) { return [NSArray arrayWithObjects: @"gorm", @"nib", @"gsmarkup", @"gmodel", nil]; } else if ([category hasPrefix: PreSlash(FrameworksCategoryName)]) { return [NSArray arrayWithObjects: @"framework", @"so", nil]; } else { return nil; } } - (FileImportResult) importFile: (NSString *) aFile intoCategory: (NSString *) aCategory error: (NSError **) error { if ([aCategory hasPrefix: PreSlash(FrameworksCategoryName)]) { return [fileManager createVirtualFileNamed: [aFile lastPathComponent] atPath: aCategory error: error]; } else { return FileImportCannotHandle; } } - (NSString *) pathToFileTemplatesDirectoryForCategory: (NSString *) category { NSArray * pathComponents = [category pathComponents]; if ([pathComponents count] <= 1) { return nil; } else { // the name of the templates directory is the same as the category // name, but with ' ' substituted for '_' (as gnustep-make doesn't // allow for spaces in resource filenames) return [[NSBundle bundleForClass: [PaletteProjectType class]] pathForResource: [[pathComponents objectAtIndex: 1] stringByReplacingString: @" " withString: @"_"] ofType: @"templates"]; } } - (NSDictionary *) filesAssociatedWithTemplateFile: (NSString *) aFile fromTemplatesDirectory: (NSString *) templatesDir forCategory: (NSString *) targetCategory { NSString * templatesDirName = [templatesDir lastPathComponent]; NSString * newFilename = nil; NSString * category = nil; if ([templatesDirName isEqualToString: @"Class_Files.templates"]) { NSMutableArray * temp; newFilename = [[templatesDir stringByDeletingLastPathComponent] stringByAppendingPathComponent: @"Header_Files.templates"]; newFilename = [newFilename stringByAppendingPathComponent: [aFile stringByDeletingPrefix: templatesDir]]; newFilename = [[newFilename stringByDeletingPathExtension] stringByAppendingPathExtension: @"h"]; category = PreSlash(HeaderFilesCategoryName); temp = [[targetCategory pathComponents] mutableCopy]; [temp replaceObjectAtIndex: 1 withObject: HeaderFilesCategoryName]; category = [NSString pathWithComponents: temp]; } else if ([templatesDirName isEqualToString: @"Header_Files.templates"]) { NSMutableArray * temp; newFilename = [[templatesDir stringByDeletingLastPathComponent] stringByAppendingPathComponent: @"Class_Files.templates"]; newFilename = [newFilename stringByAppendingPathComponent: [aFile stringByDeletingPrefix: templatesDir]]; newFilename = [[newFilename stringByDeletingPathExtension] stringByAppendingPathExtension: @"m"]; category = PreSlash(ClassFilesCategoryName); temp = [[targetCategory pathComponents] mutableCopy]; [temp replaceObjectAtIndex: 1 withObject: ClassFilesCategoryName]; category = [NSString pathWithComponents: temp]; } // accept the file if it exists if (newFilename != nil && [[NSFileManager defaultManager] fileExistsAtPath: newFilename]) { return [NSDictionary dictionaryWithObject: category forKey: newFilename]; } else { return nil; } } - (NSArray *) tabIdentifiersForProjectAttributes: (id) sender { return [NSArray arrayWithObjects: @"PaletteInfo", nil]; } - (NSString *) projectAttributes: (id) sender toolbarItemLabelForTabIdentifier: (NSString *) tab { return _(@"Palette Info"); } - (NSString *) projectAttributes: (id) sender toolbarItemToolTipForTabIdentifier: (NSString *) tab { return _(@"General palette settings"); } - (NSImage *) projectAttributes: (id) sender toolbarItemIconForTabIdentifier: (NSString *) tab { return [NSImage imageNamed: @"PaletteInfoAttributes" owner: self]; } - (NSView *) projectAttributes: (id) sender viewForTabIdentifier: (NSString *) tab { if (generalAttributes == nil) { generalAttributes = [[PaletteGeneralAttributes alloc] initWithOwner: self]; } return [generalAttributes view]; } - (void) setMainNibFile: (NSString *) aFile { ASSIGN(mainNibFile, aFile); [owner updateChangeCount: NSChangeDone]; } - (NSString *) mainNibFile { return mainNibFile; } - (void) setPrincipalClass: (NSString *) aClass { ASSIGN(principalClass, aClass); [owner updateChangeCount: NSChangeDone]; } - (NSString *) principalClass { return principalClass; } - (void) setAuthors: (NSArray *) anArray { ASSIGNCOPY(authors, anArray); [owner updateChangeCount: NSChangeDone]; } - (NSArray *) authors { return authors; } - (void) setCopyright: (NSString *) aCopyright { ASSIGN(copyright, aCopyright); [owner updateChangeCount: NSChangeDone]; } - (NSString *) copyright { return copyright; } - (void) setCopyrightDescription: (NSString *) aCopyrightDescription { ASSIGN(copyrightDescription, aCopyrightDescription); [owner updateChangeCount: NSChangeDone]; } - (NSString *) copyrightDescription { return copyrightDescription; } - (void) setIconName: (NSString *) anIconName { ASSIGN(iconName, anIconName); [owner updateChangeCount: NSChangeDone]; } - (NSString *) iconName { return iconName; } - (void) setExportedClasses: (NSArray *) someClasses { ASSIGNCOPY(exportedClasses, someClasses); [owner updateChangeCount: NSChangeDone]; } - (NSArray *) exportedClasses { return exportedClasses; } - (NSArray *) buildTargetsForMakeBuilder: (id) sender { return [NSArray arrayWithObjects: _(@"Default"), _(@"Debug"), _(@"Profile"), _(@"Install"), nil]; } - (BOOL) prepareForBuildByBuilder: (id) sender target: (NSString *) aTarget { return [self prepareMakefile] && [self prepareInfoFile]; } - (NSArray *) buildArgumentsForBuilder: (id) sender target: (NSString *) aTarget { if ([aTarget isEqualToString: _(@"Default")]) { return nil; } else if ([aTarget isEqualToString: _(@"Debug")]) { return [NSArray arrayWithObject: @"debug=yes"]; } else if ([aTarget isEqualToString: _(@"Profile")]) { return [NSArray arrayWithObject: @"profile=yes"]; } else if ([aTarget isEqualToString: _(@"Install")]) { return [NSArray arrayWithObject: @"install"]; } else { NSLog(@"Unknown target \"%@\" passed to " @"-prepareForBuildByBuilder:target:", aTarget); return nil; } } - (BOOL) prepareForCleanByBuilder: (id) sender target: (NSString *) aTarget { return [self prepareMakefile]; } - (NSArray *) cleanArgumentsForBuilder: (id) sender target: (NSString *) aTarget { if ([aTarget isEqualToString: _(@"Default")] || [aTarget isEqualToString: _(@"Install")]) { return [NSArray arrayWithObject: @"clean"]; } else { return [NSArray arrayWithObject: @"distclean"]; } } @end