apps-projectcenter/PCLib/PCProject.m
Robert Slover 611d39e478 Initial revision
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/apps/projectcenter/trunk@7258 72102866-910b-0410-8b05-ffd578937521
2000-08-27 19:11:42 +00:00

800 lines
21 KiB
Objective-C

/*
GNUstep ProjectCenter - http://www.projectcenter.ch
Copyright (C) 2000 Philippe C.D. Robert
Author: Philippe C.D. Robert <phr@projectcenter.ch>
This file is part of ProjectCenter.
This application 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 application 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
Library General Public License for more details.
You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
$Id$
*/
#import "PCProject.h"
#import "ProjectCenter.h"
#import "PCProjectBuilder.h"
#if defined(GNUSTEP)
#import <AppKit/IMLoading.h>
#endif
@interface PCProject (CreateUI)
- (void)_initUI;
@end
@implementation PCProject (CreateUI)
- (void)_initUI
{
NSView *_c_view;
unsigned int style = NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask | NSResizableWindowMask;
NSBrowser *browser;
NSSplitView *split;
NSScrollView * scrollView;
NSRect _w_frame;
NSMatrix* matrix;
NSButtonCell* buttonCell = [[[NSButtonCell alloc] init] autorelease];
id textField;
id button;
browserController = [[PCBrowserController alloc] init];
/*
* Project Window
*
*/
_w_frame = NSMakeRect(100,100,512,320);
projectWindow = [[NSWindow alloc] initWithContentRect:_w_frame
styleMask:style
backing:NSBackingStoreBuffered
defer:NO];
[projectWindow setDelegate:self];
[projectWindow setMinSize:NSMakeSize(512,320)];
browser = [[[NSBrowser alloc] initWithFrame:NSMakeRect(30,30,280,400)] autorelease];
[browser setDelegate:browserController];
[browser setMaxVisibleColumns:3];
[browser setAllowsMultipleSelection:NO];
[browserController setBrowser:browser];
[browserController setProject:self];
textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,472,88)];
[textView setMaxSize:NSMakeSize(1e7, 1e7)];
[textView setVerticallyResizable:YES];
[textView setHorizontallyResizable:YES];
[textView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
[textView setBackgroundColor:[NSColor whiteColor]];
[[textView textContainer] setWidthTracksTextView:YES];
scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect (0,0,496,92)];
[scrollView setDocumentView:textView];
[textView setMinSize:NSMakeSize(0.0,[scrollView contentSize].height)];
[[textView textContainer] setContainerSize:NSMakeSize([scrollView contentSize].width,1e7)];
[scrollView setHasHorizontalScroller: YES];
[scrollView setHasVerticalScroller: YES];
[scrollView setBorderType: NSBezelBorder];
[scrollView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[scrollView autorelease];
split = [[[NSSplitView alloc] initWithFrame:NSMakeRect(8,0,496,264)] autorelease];
[split setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[split addSubview: browser];
[split addSubview: scrollView];
_c_view = [projectWindow contentView];
[_c_view addSubview:split];
// Left button matrix
_w_frame = NSMakeRect(8,268,144,48);
matrix = [[[NSMatrix alloc] initWithFrame: _w_frame
mode: NSHighlightModeMatrix
prototype: buttonCell
numberOfRows: 1
numberOfColumns: 3] autorelease];
[matrix setSelectionByRect:YES];
[matrix setAutoresizingMask: (NSViewMaxXMargin | NSViewMinYMargin)];
[_c_view addSubview:matrix];
button = [matrix cellAtRow:0 column:0];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_build.tiff"] autorelease]];
[button setButtonType:NSMomentaryPushButton];
[button setTarget:self];
[button setAction:@selector(build:)];
button = [matrix cellAtRow:0 column:1];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_clean.tiff"] autorelease]];
[button setButtonType:NSMomentaryPushButton];
[button setTarget:self];
[button setAction:@selector(clean:)];
button = [matrix cellAtRow:0 column:2];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_prefs.tiff"] autorelease]];
[button setTarget:self];
[button setAction:@selector(showBuildTarget:)];
[button setButtonType:NSMomentaryPushButton];
[button setTarget:self];
[button setAction:@selector(showBuildTargetPanel:)];
// Right button matrix
_w_frame = NSMakeRect(304,268,192,48);
matrix = [[[NSMatrix alloc] initWithFrame: _w_frame
mode: NSHighlightModeMatrix
prototype: buttonCell
numberOfRows: 1
numberOfColumns: 4] autorelease];
[matrix setSelectionByRect:YES];
[matrix setAutoresizingMask: (NSViewMinXMargin | NSViewMinYMargin)];
[_c_view addSubview:matrix];
button = [matrix cellAtRow:0 column:0];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_run.tiff"] autorelease]];
[button setButtonType:NSMomentaryPushButton];
button = [matrix cellAtRow:0 column:1];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_uml.tiff"] autorelease]];
[button setButtonType:NSMomentaryPushButton];
button = [matrix cellAtRow:0 column:2];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_documentation.tiff"] autorelease]];
[button setButtonType:NSMomentaryPushButton];
button = [matrix cellAtRow:0 column:3];
[button setImagePosition:NSImageOnly];
[button setImage:[[[NSImage alloc] initWithContentsOfFile:@"ProjectCentre_find.tiff"] autorelease]];
[button setButtonType:NSMomentaryPushButton];
// Status
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(152,296,48,15)];
[textField setAlignment: NSRightTextAlignment];
[textField setBordered: NO];
[textField setEditable: NO];
[textField setBezeled: NO];
[textField setDrawsBackground: NO];
[textField setStringValue:@"Status:"];
[textField setAutoresizingMask: (NSViewMaxXMargin |
NSViewMinYMargin)];
[_c_view addSubview:[textField autorelease]];
// Status message
buildStatusField = [[NSTextField alloc] initWithFrame:NSMakeRect(204,296,104,15)];
[buildStatusField setAlignment: NSLeftTextAlignment];
[buildStatusField setBordered: NO];
[buildStatusField setEditable: NO];
[buildStatusField setBezeled: NO];
[buildStatusField setDrawsBackground: NO];
[buildStatusField setStringValue:@"waiting..."];
[buildStatusField setAutoresizingMask: (NSViewMaxXMargin |
NSViewWidthSizable |
NSViewMinYMargin)];
[_c_view addSubview:[buildStatusField autorelease]];
// Target
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(152,272,48,15)];
[textField setAlignment: NSRightTextAlignment];
[textField setBordered: NO];
[textField setBezeled: NO];
[textField setEditable: NO];
[textField setDrawsBackground: NO];
[textField setStringValue:@"Target:"];
[textField setAutoresizingMask: (NSViewMaxXMargin |
NSViewMinYMargin)];
[_c_view addSubview:[textField autorelease]];
// Target message
targetField = [[NSTextField alloc] initWithFrame:NSMakeRect(204,272,104,15)];
[targetField setAlignment: NSLeftTextAlignment];
[targetField setBordered: NO];
[targetField setEditable: NO];
[targetField setBezeled: NO];
[targetField setDrawsBackground: NO];
[targetField setStringValue:@"Default..."];
[targetField setAutoresizingMask: (NSViewMaxXMargin |
NSViewWidthSizable |
NSViewMinYMargin)];
[_c_view addSubview:[targetField autorelease]];
/*
* Build Panel
*
*/
_w_frame = NSMakeRect(100,100,272,104);
buildTargetPanel = [[NSWindow alloc] initWithContentRect:_w_frame styleMask:style backing:NSBackingStoreBuffered defer:NO];
[buildTargetPanel setReleasedWhenClosed:NO];
[buildTargetPanel setTitle:@"Build Options"];
_c_view = [buildTargetPanel contentView];
buildTargetPopup = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(72,24,184,20)];
[buildTargetPopup addItemWithTitle:@"Default"];
[buildTargetPopup addItemWithTitle:@"Debug"];
[buildTargetPopup addItemWithTitle:@"Profile"];
[buildTargetPopup addItemWithTitle:@"Install"];
[buildTargetPopup autorelease];
[buildTargetPopup setTarget:self];
[buildTargetPopup setAction:@selector(setTarget:)];
[_c_view addSubview:buildTargetPopup];
// Target (popup)
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(16,24,56,21)];
[textField setAlignment: NSRightTextAlignment];
[textField setBordered: NO];
[textField setEditable: NO];
[textField setBezeled: NO];
[textField setDrawsBackground: NO];
[textField setStringValue:@"Target:"];
[_c_view addSubview:[textField autorelease]];
// Host
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(16,48,56,21)];
[textField setAlignment: NSRightTextAlignment];
[textField setBordered: NO];
[textField setEditable: NO];
[textField setBezeled: NO];
[textField setDrawsBackground: NO];
[textField setStringValue:@"Host:"];
[_c_view addSubview:[textField autorelease]];
// Host message
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(72,48,184,21)];
[textField setAlignment: NSLeftTextAlignment];
[textField setBordered: NO];
[textField setEditable: YES];
[textField setBezeled: YES];
[textField setDrawsBackground: YES];
[textField setStringValue:@"localhost"];
[_c_view addSubview:[textField autorelease]];
// Args
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(12,68,60,21)];
[textField setAlignment: NSRightTextAlignment];
[textField setBordered: NO];
[textField setEditable: NO];
[textField setBezeled: NO];
[textField setDrawsBackground: NO];
[textField setStringValue:@"Arguments:"];
[_c_view addSubview:[textField autorelease]];
// Args message
textField = [[NSTextField alloc] initWithFrame:NSMakeRect(72,68,184,21)];
[textField setAlignment: NSLeftTextAlignment];
[textField setBordered: NO];
[textField setEditable: YES];
[textField setBezeled: YES];
[textField setDrawsBackground: YES];
[textField setStringValue:@""];
[_c_view addSubview:[textField autorelease]];
// Redisplay!
[browser loadColumnZero];
_needsReleasing = YES;
}
@end
@implementation PCProject
//===========================================================================================
// ==== Init and free
//===========================================================================================
- (id)init
{
if ((self = [super init])) {
_buildTarget = defaultTarget;
_needsReleasing = NO;
#if defined(GNUSTEP)
[self _initUI];
#else
if(![NSBundle loadNibNamed:@"Project.nib" owner:self]) {
[[NSException exceptionWithName:NIB_NOT_FOUND_EXCEPTION reason:@"Could not load Project.gmodel" userInfo:nil] raise];
return nil;
}
#endif
}
return self;
}
- (id)initWithProjectDictionary:(NSDictionary *)dict path:(NSString *)path;
{
NSAssert(dict,@"No valid project dictionary!");
if ((self = [self init])) {
if ([[path lastPathComponent] isEqualToString:@"PC.project"]) {
projectPath = [[path stringByDeletingLastPathComponent] copy];
}
else {
projectPath = [path copy];
}
if(![self assignProjectDict:dict]) {
NSLog(@"<%@ %x>: could not load the project...",[self class],self);
[self autorelease];
return nil;
}
}
return self;
}
- (void)dealloc
{
[projectName release];
[projectPath release];
[projectDict release];
if (_needsReleasing) {
[browserController release];
[projectWindow release];
[buildTargetPanel release];
}
[super dealloc];
}
//===========================================================================================
// ==== Accessor methods
//===========================================================================================
- (id)browserController
{
return browserController;
}
- (void)setProjectName:(NSString *)aName
{
[projectName autorelease];
projectName = [aName copy];
}
- (NSString *)projectName
{
return projectName;
}
- (NSWindow *)projectWindow
{
if (!projectWindow) NSLog(@"No window??????");
return projectWindow;
}
- (Class)principalClass
{
return [self class];
}
//===========================================================================================
// ==== Delegate and manager
//===========================================================================================
- (id)delegate
{
return delegate;
}
- (void)setDelegate:(id)aDelegate
{
delegate = aDelegate;
}
- (void)setProjectBuilder:(id<ProjectBuilder>)aBuilder
{
[projectBuilder autorelease];
projectBuilder = [aBuilder retain];
}
- (id<ProjectBuilder>)projectBuilder
{
return projectBuilder;
}
//===========================================================================================
// ==== To be overriden
//===========================================================================================
- (BOOL)writeMakefile
{
return [projectDict writeToFile:[projectPath stringByAppendingPathComponent:@"PC.project"] atomically:YES];
}
- (BOOL)isValidDictionary:(NSDictionary *)aDict
{
return NO;
}
- (NSArray *)sourceFileKeys
{
return nil;
}
- (NSArray *)resourceFileKeys
{
return nil;
}
- (NSArray *)otherKeys
{
return nil;
}
- (NSArray *)buildTargets
{
return nil;
}
- (NSString *)projectDescription
{
return @"Abstract PCProject class!";
}
- (id)textView
{
return textView;
}
//===========================================================================================
// ==== Miscellaneous
//===========================================================================================
- (BOOL)doesAcceptFile:(NSString *)file forKey:(NSString *)type
{
if ([[projectDict allKeys] containsObject:type]) {
NSArray *files = [projectDict objectForKey:type];
if (![files containsObject:file]) {
return YES;
}
}
return NO;
}
- (void)addFile:(NSString *)file forKey:(NSString *)type
{
NSMutableArray *files = [NSMutableArray arrayWithArray:[projectDict objectForKey:type]];
NSMutableString *newFile = [NSMutableString stringWithString:[file lastPathComponent]];
if ([type isEqualToString:PCLibraries]) {
[newFile deleteCharactersInRange:NSMakeRange(0,3)];
newFile = [newFile stringByDeletingPathExtension];
}
if ([files containsObject:newFile]) {
NSRunAlertPanel(@"Attention!",@"The file %@ is already contained in this project!",@"OK",nil,nil,newFile);
return;
}
NSLog(@"<%@ %x>: adding file %@ for key %@",[self class],self,newFile,type);
// Add the new file
[files addObject:newFile];
[projectDict setObject:files forKey:type];
// Synchronise the makefile!
[self writeMakefile];
}
- (void)removeFile:(NSString *)file forKey:(NSString *)key
{
NSMutableArray *array;
if (!file || !key) {
return;
}
array = [NSMutableArray arrayWithArray:[projectDict objectForKey:key]];
[array removeObject:file];
[projectDict setObject:array forKey:key];
[self writeMakefile];
}
- (BOOL)removeSelectedFilePermanently:(BOOL)yn
{
NSString *file = [browserController nameOfSelectedFile];
NSMutableArray *array;
NSString *key;
if (!file) {
return NO;
}
key = [self projectKeyForKeyPath:[browserController pathOfSelectedFile]];
[self removeFile:file forKey:key];
// Remove the file permanently?!
if (yn) {
NSString *pth = [projectPath stringByAppendingPathComponent:file];
[[NSFileManager defaultManager] removeFileAtPath:pth handler:nil];
}
return YES;
}
- (BOOL)assignProjectDict:(NSDictionary *)aDict
{
NSAssert(aDict,@"No valid project dictionary!");
if (![self isValidDictionary:aDict]) {
return NO;
}
[projectDict autorelease];
projectDict = [[NSMutableDictionary alloc] initWithDictionary:aDict];
[self setProjectName:[projectDict objectForKey:PCProjectName]];
[projectWindow setTitle:[NSString stringWithFormat:@"%@ - %@",projectName,projectPath]];
// Update the GNUmakefile!
[self writeMakefile];
[[NSNotificationCenter defaultCenter] postNotificationName:@"ProjectDictDidChangeNotification" object:self];
return YES;
}
- (NSDictionary *)projectDict
{
return (NSDictionary *)projectDict;
}
- (void)setProjectPath:(NSString *)aPath
{
[projectPath autorelease];
projectPath = [aPath copy];
}
- (NSString *)projectPath
{
return projectPath;
}
- (NSDictionary *)rootCategories
{
return rootCategories;
}
- (BOOL)save
{
}
- (BOOL)saveAt:(NSString *)projPath
{
}
- (BOOL)saveFileNamed:(NSString *)file
{
}
- (BOOL)saveAllFiles
{
}
- (BOOL)saveAllFilesIfNeeded
{
}
- (NSArray *)subprojects
{
return [projectDict objectForKey:PCSubprojects];
}
- (void)addSubproject:(PCProject *)aSubproject
{
}
- (PCProject *)superProject
{
return nil;
}
- (PCProject *)rootProject
{
return self;
}
- (void)newSubprojectNamed:(NSString *)aName
{
}
- (void)removeSubproject:(PCProject *)aSubproject
{
}
- (BOOL)isSubProject
{
}
@end
@implementation PCProject (ProjectBuilding)
- (void)showInspector:(id)sender
{
[projectBuilder showInspectorForProject:self];
}
- (id)updatedAttributeView
{
return projectAttributeInspectorView;
}
- (id)updatedProjectView
{
return projectProjectInspectorView;
}
- (id)updatedFilesView
{
return projectFileInspectorView;
}
- (void)showBuildTargetPanel:(id)sender
{
[buildTargetPanel center];
[buildTargetPanel makeKeyAndOrderFront:self];
}
- (void)setTarget:(id)sender
{
_buildTarget = [buildTargetPopup indexOfSelectedItem];
}
- (void)setHost:(id)sender
{
NSLog(@"Setting host...");
}
- (void)setArguments:(id)sender
{
NSLog(@"Setting args...");
}
- (void)build:(id)sender
{
BOOL ret = YES;
NSString *target = [buildTargetPopup titleOfSelectedItem];
NSMutableDictionary *optionDict = [NSMutableDictionary dictionary];
[buildStatusField setStringValue:@"Building..."];
// Check the panel for this option!
if ([target isEqualToString:@"Debug"]) {
[optionDict setObject:TARGET_MAKE_DEBUG forKey:BUILD_KEY];
}
if ([target isEqualToString:@"Profile"]) {
[optionDict setObject:TARGET_MAKE_PROFILE forKey:BUILD_KEY];
}
if ([target isEqualToString:@"Install"]) {
[optionDict setObject:TARGET_MAKE_INSTALL forKey:BUILD_KEY];
}
else {
[optionDict setObject:TARGET_MAKE forKey:BUILD_KEY];
}
[[PCProjectBuilder sharedBuilder] buildProject:self options:optionDict];
if (ret) {
[buildStatusField setStringValue:@"Build completed!"];
}
else {
[buildStatusField setStringValue:@"Build failed!"];
}
}
- (void)clean:(id)sender
{
BOOL ret = YES;
NSMutableDictionary *optionDict = [NSMutableDictionary dictionary];
[buildStatusField setStringValue:@"Cleaning..."];
// Check the panel for this option!
[optionDict setObject:TARGET_MAKE_CLEAN forKey:BUILD_KEY];
[[PCProjectBuilder sharedBuilder] buildProject:self options:optionDict];
if (ret) {
[buildStatusField setStringValue:@"Cleaning completed!"];
}
else {
[buildStatusField setStringValue:@"Cleaning failed!"];
}
}
@end
@implementation PCProject (ProjectKeyPaths)
- (NSArray *)contentAtKeyPath:(NSString *)keyPath
{
NSString *key;
NSLog(@"<%@ %x>: content at path %@",[self class],self,keyPath);
if ([keyPath isEqualToString:@""] || [keyPath isEqualToString:@"/"]) {
return [rootCategories allKeys];
}
key = [[keyPath componentsSeparatedByString:@"/"] lastObject];
return [projectDict objectForKey:[rootCategories objectForKey:key]];
}
- (BOOL)hasChildrenAtKeyPath:(NSString *)keyPath
{
NSString *key;
if (!keyPath || [keyPath isEqualToString:@""]) {
return NO;
}
key = [[keyPath componentsSeparatedByString:@"/"] lastObject];
if ([[rootCategories allKeys] containsObject:key] || [[projectDict objectForKey:PCSubprojects] containsObject:key]) {
return YES;
}
return NO;
}
- (NSString *)projectKeyForKeyPath:(NSString *)kp
{
NSString *type = [[kp componentsSeparatedByString:@"/"] objectAtIndex:1];
return [rootCategories objectForKey:type];
}
@end
@implementation PCProject (ProjectWindowDelegate)
- (void)windowDidBecomeKey:(NSNotification *)aNotification
{
[projectBuilder setActiveProject:self];
}
- (void)windowDidBecomeMain:(NSNotification *)aNotification
{
[projectBuilder setActiveProject:self];
}
- (void)windowWillClose:(NSNotification *)aNotification
{
if ([[self projectWindow] isDocumentEdited]) {
if (NSRunAlertPanel(@"Project changed!",@"The project %@ has unsaved files! Should they be saved before closing it?",@"Yes",@"No",nil,[self projectName])) {
[self save];
}
}
// The PCProjectController is our delegate!
[projectBuilder closeProject:self];
}
@end