Skip to content

Commit 0afb853

Browse files
committed
Add code to create new document
1 parent 2e32e07 commit 0afb853

3 files changed

Lines changed: 247 additions & 0 deletions

File tree

Applications/ycode/AppController.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#import <AppKit/AppKit.h>
1515

1616
@class YCodeWindowController;
17+
@class YCodeProject;
1718

1819
@interface AppController : NSObject
1920
{
@@ -45,6 +46,21 @@
4546
*/
4647
- (void) applicationDidFinishLaunching: (NSNotification *)aNotif;
4748

49+
/**
50+
* Creates a new project.
51+
*/
52+
- (IBAction) newProject: (id)sender;
53+
54+
/**
55+
* Creates a new project at the specified URL.
56+
*/
57+
- (void) createNewProjectAtURL:(NSURL *)projectURL;
58+
59+
/**
60+
* Gets project name from user input.
61+
*/
62+
- (NSString *) getProjectNameFromUser;
63+
4864
/**
4965
* Determines whether the application should terminate.
5066
*/

Applications/ycode/AppController.m

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#import "AppController.h"
1212
#import "YCodeWindowController.h"
13+
#import "YCodeProject.h"
1314

1415
@implementation AppController
1516

@@ -90,6 +91,103 @@ - (void) applicationWillTerminate: (NSNotification *)aNotif
9091
}
9192
}
9293

94+
- (IBAction) newProject: (id)sender
95+
{
96+
// Show new project dialog
97+
NSOpenPanel *panel = [NSOpenPanel openPanel];
98+
[panel setCanChooseDirectories:YES];
99+
[panel setCanChooseFiles:NO];
100+
[panel setCanCreateDirectories:YES];
101+
[panel setAllowsMultipleSelection:NO];
102+
[panel setTitle:@"Create New Project"];
103+
[panel setPrompt:@"Create"];
104+
[panel setMessage:@"Choose location for new project:"];
105+
106+
NSInteger result = [panel runModal];
107+
if (result == NSModalResponseOK) {
108+
NSURL *selectedURL = [[panel URLs] firstObject];
109+
if (selectedURL) {
110+
[self createNewProjectAtURL:selectedURL];
111+
}
112+
}
113+
}
114+
115+
- (void) createNewProjectAtURL:(NSURL *)projectURL
116+
{
117+
// Show project type selection dialog
118+
NSAlert *alert = [[NSAlert alloc] init];
119+
[alert setMessageText:@"Choose Project Type"];
120+
[alert setInformativeText:@"Select the type of project you want to create:"];
121+
[alert addButtonWithTitle:@"Xcode Project"];
122+
[alert addButtonWithTitle:@"ProjectCenter Project"];
123+
[alert addButtonWithTitle:@"Cancel"];
124+
125+
NSInteger choice = [alert runModal];
126+
RELEASE(alert);
127+
128+
if (choice == NSAlertThirdButtonReturn) {
129+
return; // Cancel
130+
}
131+
132+
// Get project name
133+
NSString *projectName = [self getProjectNameFromUser];
134+
if (!projectName || [projectName length] == 0) {
135+
return;
136+
}
137+
138+
BOOL isXcodeProject = (choice == NSAlertFirstButtonReturn);
139+
NSString *projectPath = [[projectURL path] stringByAppendingPathComponent:projectName];
140+
141+
// Create the project
142+
YCodeProject *newProject = [YCodeProject createNewProjectAtPath:projectPath
143+
name:projectName
144+
type:isXcodeProject ? @"Xcode" : @"ProjectCenter"];
145+
146+
if (newProject) {
147+
// Open the new project
148+
if (!windowController) {
149+
windowController = [[YCodeWindowController alloc] init];
150+
}
151+
[windowController setProject:newProject];
152+
[windowController showWindow:self];
153+
154+
// Save the project immediately
155+
[newProject saveProjectToPath:projectPath];
156+
} else {
157+
NSAlert *errorAlert = [[NSAlert alloc] init];
158+
[errorAlert setMessageText:@"Project Creation Failed"];
159+
[errorAlert setInformativeText:@"Could not create the new project. Please check the selected location and try again."];
160+
[errorAlert addButtonWithTitle:@"OK"];
161+
[errorAlert runModal];
162+
RELEASE(errorAlert);
163+
}
164+
}
165+
166+
- (NSString *) getProjectNameFromUser
167+
{
168+
NSAlert *alert = [[NSAlert alloc] init];
169+
[alert setMessageText:@"Project Name"];
170+
[alert setInformativeText:@"Enter a name for your new project:"];
171+
[alert addButtonWithTitle:@"Create"];
172+
[alert addButtonWithTitle:@"Cancel"];
173+
174+
NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
175+
[input setStringValue:@"MyProject"];
176+
[alert setAccessoryView:input];
177+
178+
NSInteger result = [alert runModal];
179+
NSString *projectName = nil;
180+
181+
if (result == NSAlertFirstButtonReturn) {
182+
projectName = [input stringValue];
183+
}
184+
185+
RELEASE(input);
186+
RELEASE(alert);
187+
188+
return projectName;
189+
}
190+
93191
- (BOOL) application: (NSApplication *)application
94192
openFile: (NSString *)fileName
95193
{

Applications/ycode/YCodeProject.m

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,139 @@
4141

4242
@implementation YCodeProject
4343

44+
#pragma mark - Class Methods
45+
46+
+ (YCodeProject *)createNewProjectAtPath:(NSString *)path name:(NSString *)name type:(NSString *)type
47+
{
48+
NSFileManager *fileManager = [NSFileManager defaultManager];
49+
50+
// Create project directory if it doesn't exist
51+
if (![fileManager fileExistsAtPath:path]) {
52+
NSError *error;
53+
if (![fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]) {
54+
NSLog(@"Failed to create project directory: %@", [error localizedDescription]);
55+
return nil;
56+
}
57+
}
58+
59+
// Create project instance
60+
YCodeProject *project = [[YCodeProject alloc] init];
61+
[project setProjectPath:path];
62+
63+
if ([type isEqualToString:@"Xcode"]) {
64+
[project createXcodeProjectWithName:name atPath:path];
65+
} else {
66+
[project createProjectCenterProjectWithName:name atPath:path];
67+
}
68+
69+
return AUTORELEASE(project);
70+
}
71+
72+
- (BOOL)createXcodeProjectWithName:(NSString *)name atPath:(NSString *)path
73+
{
74+
// Create basic Xcode project structure
75+
NSString *projectFile = [NSString stringWithFormat:@"%@.xcodeproj", name];
76+
NSString *projectPath = [path stringByAppendingPathComponent:projectFile];
77+
78+
NSFileManager *fileManager = [NSFileManager defaultManager];
79+
if (![fileManager createDirectoryAtPath:projectPath withIntermediateDirectories:YES attributes:nil error:nil]) {
80+
return NO;
81+
}
82+
83+
// Create project structure
84+
PBXProject *pbxProject = [[PBXProject alloc] init];
85+
[pbxProject setProjectDirPath:@""];
86+
[pbxProject setProjectRoot:@""];
87+
[pbxProject setCompatibilityVersion:@"Xcode 15.0"];
88+
[pbxProject setDevelopmentRegion:@"en"];
89+
90+
// Create main group
91+
PBXGroup *mainGroup = [[PBXGroup alloc] init];
92+
[mainGroup setName:name];
93+
[pbxProject setMainGroup:mainGroup];
94+
95+
// Create a simple target
96+
PBXNativeTarget *target = [[PBXNativeTarget alloc] init];
97+
[target setName:name];
98+
[target setProductName:name];
99+
[pbxProject addTarget:target];
100+
101+
// Create container
102+
PBXContainer *container = [[PBXContainer alloc] init];
103+
[container setProject:pbxProject];
104+
105+
[self setProject:pbxProject];
106+
[self setContainer:container];
107+
108+
// Create basic main.m file
109+
[self createMainFileAtPath:path];
110+
111+
RELEASE(pbxProject);
112+
RELEASE(mainGroup);
113+
RELEASE(target);
114+
RELEASE(container);
115+
116+
return YES;
117+
}
118+
119+
- (BOOL)createProjectCenterProjectWithName:(NSString *)name atPath:(NSString *)path
120+
{
121+
// Create ProjectCenter project file
122+
NSString *projectFile = [NSString stringWithFormat:@"%@.pcproj", name];
123+
NSString *projectPath = [path stringByAppendingPathComponent:projectFile];
124+
125+
NSMutableDictionary *projectDict = [NSMutableDictionary dictionary];
126+
[projectDict setObject:name forKey:@"PROJECT_NAME"];
127+
[projectDict setObject:@"Application" forKey:@"PROJECT_TYPE"];
128+
[projectDict setObject:name forKey:@"PRINCIPAL_CLASS"];
129+
[projectDict setObject:[NSArray array] forKey:@"CLASS_FILES"];
130+
[projectDict setObject:[NSArray array] forKey:@"HEADER_FILES"];
131+
[projectDict setObject:[NSArray array] forKey:@"LOCALIZED_RESOURCES"];
132+
[projectDict setObject:[NSArray array] forKey:@"LIBRARIES"];
133+
134+
BOOL success = [projectDict writeToFile:projectPath atomically:YES];
135+
136+
if (success) {
137+
// Load the project we just created
138+
[self loadProjectCenterProject:projectDict fromPath:path];
139+
140+
// Create basic main.m file
141+
[self createMainFileAtPath:path];
142+
143+
// Create basic GNUmakefile
144+
[self createGNUMakefileAtPath:path withName:name];
145+
}
146+
147+
return success;
148+
}
149+
150+
- (void)createMainFileAtPath:(NSString *)path
151+
{
152+
NSString *mainContent = @"#import <Foundation/Foundation.h>\n"
153+
@"#import <AppKit/AppKit.h>\n\n"
154+
@"int main(int argc, const char *argv[])\n"
155+
@"{\n"
156+
@" return NSApplicationMain(argc, argv);\n"
157+
@"}\n";
158+
159+
NSString *mainPath = [path stringByAppendingPathComponent:@"main.m"];
160+
[mainContent writeToFile:mainPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
161+
}
162+
163+
- (void)createGNUMakefileAtPath:(NSString *)path withName:(NSString *)name
164+
{
165+
NSString *makefileContent = [NSString stringWithFormat:
166+
@"include $(GNUSTEP_MAKEFILES)/common.make\n\n"
167+
@"APP_NAME = %@\n"
168+
@"%@_OBJC_FILES = main.m\n"
169+
@"%@_RESOURCE_FILES = \n\n"
170+
@"include $(GNUSTEP_MAKEFILES)/application.make\n",
171+
name, name, name];
172+
173+
NSString *makefilePath = [path stringByAppendingPathComponent:@"GNUmakefile"];
174+
[makefileContent writeToFile:makefilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
175+
}
176+
44177
- (instancetype)init
45178
{
46179
self = [super init];

0 commit comments

Comments
 (0)