//
//  EXPModelObject.m
//  Expression
//
//  Created by ashley on 15/11/2008.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "EXPModelObject.h"
#import "EXPStockComponent.h"
#import "EXPCloudComponent.h"
#import "EXPFlowComponent.h"
#import "EXPAuxiliaryComponent.h"
#import "EXPParameterComponent.h"
#import "EXPConnectorComponent.h"
#import "EXPTableComponent.h"
#import "EXPPrinterComponent.h"
#import "EXPModelView.h"
#import "EXPGraphComponent.h"
#import "EXPSymbolTable.h"

@implementation EXPModelObject

- (id) init
{
	self = [super init];

	if (self!=nil) {
		NSMutableArray *objects = [[NSMutableArray alloc] init];
		[self setObjects:objects];
		[objects release];
		
		_tables = [[NSMutableArray alloc] init];

		_options = [[NSMutableDictionary alloc] initWithObjectsAndKeys: 
					@"0.0", @"tstart",
					@"10.0", @"tstop",
					@"1.0e-2", @"tstep",
					@"1.0e-08", @"epsilon",
					@"1.0e-1", @"outstep",
					@"2000", @"histsize", 
					@"aqt", @"device",
					@"", @"plotfile", 
					@"No", @"printheader", 
				    nil];

		_defaults = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
			@"Gill Sans", @"FontName", 
			[NSNumber numberWithFloat:14.0], @"FontSize", 
			[NSColor blackColor], @"TextColour", 
//		[NSColor colorWithCalibratedRed:173/255.0 green:216/255.0 blue:230/255.0 alpha:1.0], @"StockFillColour", 			//173-216-230
			[NSColor whiteColor],																				@"BackgroundColour", 
			[NSColor blueColor],																				@"ConnectorColour",
			[NSColor colorWithCalibratedRed:102/255.0 green:204/255.0 blue:255/255.0 alpha:1.0],				@"StockFillColour", 			// "Sky"
			[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"StockStrokeColour",
			[NSColor colorWithCalibratedRed:255/255.0 green:102/255.0 blue:102/255.0 alpha:1.0],				@"ParameterFillColour", 			
			[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"ParameterStrokeColour",
			[NSColor colorWithCalibratedRed:0/255.0 green:255/255.0 blue:0/255.0 alpha:1.0],					@"AuxiliaryFillColour", 			
			[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"AuxiliaryStrokeColour",
			[NSColor blackColor],																				@"FlowStrokeColour", 
			[NSColor colorWithCalibratedRed:208/255.0 green:208/255.0 blue:208/255.0 alpha:1.0],				@"CloudFillColour", 	
			[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"CloudStrokeColour",
			[NSColor colorWithCalibratedRed:255/255.0 green:255/255.0 blue:102/255.0 alpha:1.0],				@"ValveFillColour", 	
			[NSNumber numberWithFloat:100.0],																	@"StockWidth", 
			[NSNumber numberWithFloat:50.0],																	@"StockHeight", 
			[NSNumber numberWithFloat:10.0],																	@"FlowThickness", 
			[NSNumber numberWithFloat:20.0],																	@"FlowArrowheadSize", 
			[NSNumber numberWithFloat:20.0],																	@"ValveRadius", 
			[NSNumber numberWithFloat:5.0],																		@"ConnectorArrowheadSize", 
			[NSNumber numberWithFloat:2.0],																		@"ConnectorThickness", 
			[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"StockSize", 
			[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"CloudSize", 
			[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"FlowSize", 
			[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"ConnectorSize", 
			[NSArray arrayWithObjects:[NSNumber numberWithInt:40], [NSNumber numberWithInt:40], nil],			@"AuxiliarySize", 
			[NSArray arrayWithObjects:[NSNumber numberWithInt:40], [NSNumber numberWithInt:40], nil],			@"ParameterSize", 
			[NSNumber numberWithFloat:8.0],																		@"ControlSquareSize", 
//		@"Above",																							@"namePosition", 
			@"Below",																							@"namePosition", 
			nil];
	
/*		_nextNewStock = 1;
		_nextNewFlow = 1;
		_nextNewAuxiliary = 1;
		_nextNewParameter = 1; */
		_nextComponentNumbers = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
			[NSNumber numberWithInt:1], @"Stock", 
			[NSNumber numberWithInt:1], @"Flow", 
			[NSNumber numberWithInt:1], @"Cloud", 
			[NSNumber numberWithInt:1], @"Auxiliary", 
			[NSNumber numberWithInt:1], @"Parameter",
			[NSNumber numberWithInt:1], @"Connector",
			[NSNumber numberWithInt:1], @"Graph"];

		_drawGrid = YES;
		_selection = nil;
	}

	return self;
}

/* - (id) initWithData:(NSData *)data
{
	self = [super init];

	NSXMLDocument *doc = [[NSXMLDocument alloc] initWithData:data options:NSXMLDocumentTidyXML error:nil];
	NSXMLElement *root = [doc rootElement];
	NSArray *diagrams = [root elementsForName:@"diagram"];
	
	EXPSymbolTable *symboltable = [[EXPSymbolTable alloc] init];

	int k;
	for(k=0; k<[diagrams count]; k++) {
		NSArray *children = [[diagrams objectAtIndex:k] children];
		NSMutableArray *objects = [[NSMutableArray alloc] init];
		NSMutableArray *stocks = [[NSMutableArray alloc] init];
		NSMutableArray *flows = [[NSMutableArray alloc] init];
		NSMutableArray *auxiliaries = [[NSMutableArray alloc] init];
		NSMutableArray *connectors = [[NSMutableArray alloc] init];
		NSMutableArray *parameters = [[NSMutableArray alloc] init];
		
		int i;
		int count = [children count];
		for (i=0; i < count; i++) {
			NSXMLElement *child = [children objectAtIndex:i];
			if ([[child name] isEqualToString:@"component"]) {
				NSArray *array = [child elementsForName:@"type"];
				NSString *type;
				if ([array count]>0) {
					type = [[array objectAtIndex:0] stringValue];
				} else {
					continue;
				}

// Use a dictionary of classes?			
				EXPComponent *component;
				BOOL addComponentToSymboltable = YES;
				if ([type isEqualToString:@"Stock"]) {
					component = [[EXPStockComponent alloc] init];
					[stocks addObject:component];
				} else if ([type isEqualToString:@"Cloud"]) {
					component = [[EXPCloudComponent alloc] init];
					addComponentToSymboltable = NO;
					[stocks addObject:component];
				} else if ([type isEqualToString:@"Flow"]) {
					component = [[EXPFlowComponent alloc] init];
					[flows addObject:component];
				} else if ([type isEqualToString:@"Auxiliary"]) {
					component = [[EXPAuxiliaryComponent alloc] init];
					[auxiliaries addObject:component];
				} else if ([type isEqualToString:@"Connector"]) {
					component = [[EXPConnectorComponent alloc] init];
					addComponentToSymboltable = NO;
					[connectors addObject:component];
				} else if ([type isEqualToString:@"Parameter"]) {
					component = [[EXPParameterComponent alloc] init];
					[parameters addObject:component];
				}
				[component setFromElement:child];
				[component setModelObject:self];
				[objects addObject:component];
				if (addComponentToSymboltable) {
					[symboltable declareSymbol:component];
				}
				[component release];
			}
		}
		
//	Process expressions. And inputs, outputs, inflows, outflows??
		for(i=0; i<[objects count]; i++) {
			EXPComponent *component = [objects objectAtIndex:i];
			[component process:symboltable];
		}
		
		[self setObjects:objects];
		
		[stocks release];
		[flows release];
		[connectors release];
		[auxiliaries release];
		[parameters release];
		[objects release];
	
	}
	
	[symboltable release];
	[doc release];
		
	_defaults = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
		@"Gill Sans", @"FontName", 
		[NSNumber numberWithFloat:14.0], @"FontSize", 
		[NSColor blackColor], @"TextColour", 
		[NSColor whiteColor],																				@"BackgroundColour", 
		[NSColor blueColor],																				@"ConnectorColour",
		[NSColor colorWithCalibratedRed:102/255.0 green:204/255.0 blue:255/255.0 alpha:1.0],				@"StockFillColour", 			// "Sky"
		[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"StockStrokeColour",
		[NSColor colorWithCalibratedRed:255/255.0 green:102/255.0 blue:102/255.0 alpha:1.0],				@"ParameterFillColour", 			
		[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"ParameterStrokeColour",
		[NSColor colorWithCalibratedRed:0/255.0 green:255/255.0 blue:0/255.0 alpha:1.0],					@"AuxiliaryFillColour", 			
		[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"AuxiliaryStrokeColour",
		[NSColor blackColor],																				@"FlowStrokeColour", 
		[NSColor colorWithCalibratedRed:208/255.0 green:208/255.0 blue:208/255.0 alpha:1.0],				@"CloudFillColour", 	
		[NSColor colorWithCalibratedRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0],						@"CloudStrokeColour",
		[NSColor colorWithCalibratedRed:255/255.0 green:255/255.0 blue:102/255.0 alpha:1.0],				@"ValveFillColour", 	
		[NSNumber numberWithFloat:100.0],																	@"StockWidth", 
		[NSNumber numberWithFloat:50.0],																	@"StockHeight", 
		[NSNumber numberWithFloat:10.0],																	@"FlowThickness", 
		[NSNumber numberWithFloat:20.0],																	@"FlowArrowheadSize", 
		[NSNumber numberWithFloat:20.0],																	@"ValveRadius", 
		[NSNumber numberWithFloat:5.0],																		@"ConnectorArrowheadSize", 
		[NSNumber numberWithFloat:2.0],																		@"ConnectorThickness", 
		[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"StockSize", 
		[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"CloudSize", 
		[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"FlowSize", 
		[NSArray arrayWithObjects:[NSNumber numberWithInt:100], [NSNumber numberWithInt:50], nil],			@"ConnectorSize", 
		[NSArray arrayWithObjects:[NSNumber numberWithInt:40], [NSNumber numberWithInt:40], nil],			@"AuxiliarySize", 
		[NSArray arrayWithObjects:[NSNumber numberWithInt:40], [NSNumber numberWithInt:40], nil],			@"ParameterSize", 
		[NSNumber numberWithFloat:8.0],																		@"ControlSquareSize", 
//		@"Above",																							@"namePosition", 
		@"Below",																							@"namePosition", 
		nil];
	
	_drawGrid = YES;
	_selection = nil;
	
	return self;
} */

- (BOOL) loadData:(NSData *)data
{
	NSXMLDocument *doc = [[NSXMLDocument alloc] initWithData:data options:NSXMLDocumentTidyXML error:nil];
	NSXMLElement *root = [doc rootElement];
	
	NSArray *simElements = [root elementsForName:@"simulation"];
	if ([simElements count]>0) {
		NSXMLElement *simElement = [simElements objectAtIndex:0];
		NSArray *optionElements = [simElement children];
		int i;
		for(i=0; i<[optionElements count]; i++) {
			NSXMLElement *child = [optionElements objectAtIndex:i];
			NSString *name = [child name];
			NSString *value = [child stringValue];
			if ([name isEqualToString:@"name"]) {
				[self setName:value];
			} else if ([name isEqualToString:@"integrator"]) {
				[self setIntegrator:value];
			} else if ([name isEqualToString:@"fixedstep"]) {
				[self setFixedStep:[value isEqualToString:@"Yes"]];
			} else {
				[self setOption:value forName:name];
			}
		}
	} else {
		[self setOption:@"0.0" forName:@"tstart"];
		[self setOption:@"10.0" forName:@"tstop"];
		[self setOption:@"1.0E-7" forName:@"tolerance"];
		[self setOption:@"1.0" forName:@"outstep"];
	}
	
	NSArray *names = [root elementsForName:@"name"];
	if ([names count]>0) {
		[self setName:[[names objectAtIndex:0] stringValue]];
	}
	
	NSArray *diagrams = [root elementsForName:@"diagram"];
	
	EXPSymbolTable *symboltable = [[EXPSymbolTable alloc] init];

	int k;
	for(k=0; k<[diagrams count]; k++) {
		NSArray *children = [[diagrams objectAtIndex:k] children];
		NSMutableArray *objects = [[NSMutableArray alloc] init];
		NSMutableArray *stocks = [[NSMutableArray alloc] init];
		NSMutableArray *flows = [[NSMutableArray alloc] init];
		NSMutableArray *auxiliaries = [[NSMutableArray alloc] init];
		NSMutableArray *connectors = [[NSMutableArray alloc] init];
		NSMutableArray *parameters = [[NSMutableArray alloc] init];
		
		int i;
		int count = [children count];
		for (i=0; i < count; i++) {
			NSXMLElement *child = [children objectAtIndex:i];
			if ([[child name] isEqualToString:@"component"]) {
				NSArray *array = [child elementsForName:@"type"];
				NSString *type;
				if ([array count]>0) {
					type = [[array objectAtIndex:0] stringValue];
				} else {
					continue;
				}
				NSLog(@"Type = %@", type);

// Use a dictionary of classes?			
				EXPComponent *component;
				BOOL addComponentToSymboltable = YES;
				if ([type isEqualToString:@"Stock"]) {
					component = [[EXPStockComponent alloc] init];
					[stocks addObject:component];
				} else if ([type isEqualToString:@"Cloud"]) {
					component = [[EXPCloudComponent alloc] init];
					addComponentToSymboltable = NO;
					[stocks addObject:component];
				} else if ([type isEqualToString:@"Flow"]) {
					component = [[EXPFlowComponent alloc] init];
					[flows addObject:component];
				} else if ([type isEqualToString:@"Auxiliary"]) {
					component = [[EXPAuxiliaryComponent alloc] init];
					[auxiliaries addObject:component];
				} else if ([type isEqualToString:@"Connector"]) {
					component = [[EXPConnectorComponent alloc] init];
					addComponentToSymboltable = NO;
					[connectors addObject:component];
				} else if ([type isEqualToString:@"Parameter"]) {
					component = [[EXPParameterComponent alloc] init];
					[parameters addObject:component];
				} else if ([type isEqualToString:@"Table"]) {
					component = [[EXPTableComponent alloc] init];
					[[self tables] addObject:component];
//					[parameters addObject:component];
				} else if ([type isEqualToString:@"Printer"]) {
					component = [[EXPPrinterComponent alloc] init];
					addComponentToSymboltable = NO;
				} else if ([type isEqualToString:@"Graph"]) {
					component = [[EXPGraphComponent alloc] init];
					addComponentToSymboltable = NO;
				} else {
					component = nil;
				}
				if (component!=nil) {
					[component setFromElement:child];
					[component setModelObject:self];
					[objects addObject:component];
					if ([component name]==nil) {
						[self setNameForNewComponent:component];
					}
//					if (addComponentToSymboltable) {
						[symboltable declareSymbol:component];
//					}
				}
				[component release];
			}
		}
		
//	Process expressions. And inputs, outputs, inflows, outflows??
		for(i=0; i<[objects count]; i++) {
			EXPComponent *component = [objects objectAtIndex:i];
			[component process:symboltable];
		}
		
		[self setObjects:objects];
		
		[stocks release];
		[flows release];
		[connectors release];
		[auxiliaries release];
		[parameters release];
		[objects release];
	
	}
	
	[symboltable release];
	[doc release];
		
	return YES;
}

- (id) XMLRepresentation
{
	NSXMLElement *root = (NSXMLElement *)[NSXMLNode elementWithName:@"xmodel"];
	NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithRootElement:root];
	[xmlDoc setVersion:@"1.0"];
	[xmlDoc setCharacterEncoding:@"UTF-8"];
	
	NSXMLElement *newElement;
    NSXMLElement *information = [NSXMLNode elementWithName:@"information"];
	newElement = [[NSXMLElement alloc] initWithName:@"xmodelversion"];
	[newElement setStringValue:@"1.0"];
	[information addChild:newElement];
	[newElement release];
	newElement = [[NSXMLElement alloc] initWithName:@"author"];
	[newElement setStringValue:@"Ashley Buckner"];
	[information addChild:newElement];
	[newElement release];
    [root addChild:information];
	
    NSXMLElement *simulation = [NSXMLNode elementWithName:@"simulation"];
	newElement = [[NSXMLElement alloc] initWithName:@"tstart"];
	[newElement setStringValue:[self option:@"tstart"]];
	[simulation addChild:newElement];
	[newElement release];
	newElement = [[NSXMLElement alloc] initWithName:@"tstop"];
	[newElement setStringValue:[self option:@"tstop"]];
	[simulation addChild:newElement];
	[newElement release];
	newElement = [[NSXMLElement alloc] initWithName:@"tstep"];
	[newElement setStringValue:[self option:@"outstep"]];
	[simulation addChild:newElement];
	[newElement release];
	newElement = [[NSXMLElement alloc] initWithName:@"tolerance"];
	[newElement setStringValue:[self option:@"epsilon"]];
	[simulation addChild:newElement];
	[newElement release];
    [root addChild:simulation];
	
    NSXMLElement *nameNode = [NSXMLNode elementWithName:@"name"];
	[nameNode setStringValue:@"!!!!!"];
    [root addChild:nameNode];
	
//	NSXMLElement *model = [[NSXMLElement alloc] init];
//	[model setName:@"model"];
/*	NSXMLElement *newElement = [[NSXMLElement alloc] init];
	[newElement setName:@"name"];
	[newElement setStringValue:@"!!!!!"];
	[model addChild:newElement];
	[newElement release]; */

	NSXMLElement *diagram = [[NSXMLElement alloc] init];
	[diagram setName:@"diagram"];
	newElement = [[NSXMLElement alloc] init];
	[newElement setName:@"name"];
	[newElement setStringValue:@"Diagram 1"];
	[diagram addChild:newElement];
	[newElement release];
	
	NSArray *objects = [self objects];
	int i;
	for(i=0; i<[objects count]; i++) {
		EXPComponent *component = [objects objectAtIndex:i];
		NSXMLElement *componentNode = [[NSXMLElement alloc] init];
		[component putToElement:componentNode];
		[diagram addChild:componentNode];
		[componentNode release];
	}
//	[model addChild:diagram];
	[root addChild:diagram];

//	NSData *data = [xmlDoc XMLData];
	
	[diagram release];
//	[model release];
//	[xmlDoc release];
	
	return [xmlDoc autorelease];
}

- (id) defaults
{
	return _defaults;
}

- (id) textAttributes
{
	NSDictionary *defaults = [self defaults];
	NSDictionary *attribs = [[NSDictionary alloc] initWithObjectsAndKeys:
							[NSFont fontWithName:[defaults objectForKey:@"FontName"] size:[[defaults objectForKey:@"FontSize"] floatValue]], NSFontAttributeName,
							[defaults objectForKey:@"TextColour"], NSForegroundColorAttributeName,
							nil];
	return attribs;
}

- (void) deleteComponents:(id)components
{
	NSMutableArray *componentsToDelete = [[NSMutableArray alloc] init];
	NSEnumerator *enumerator = [components objectEnumerator];
	EXPComponent *component;
 
	while ((component = [enumerator nextObject])) {
		NSLog(@"Deleting \"%@\"", [component name]);
//		[modelObject deleteComponent:component];
		[componentsToDelete addObject:component];
		[component addObjectsForDeletionTo:componentsToDelete];
	}	
	
	NSMutableArray *objects = [self objects];
	int i;
	for(i=0; i<[componentsToDelete count]; i++) {
		component = [componentsToDelete objectAtIndex:i];
		[objects removeObject:component];
	}
	
	[componentsToDelete release];
}

- (void) setNameForNewComponent:(id)component
{
	NSString *componentType = [component componentType];
/*	int number;
	if ([componentType isEqualToString:@"Stock"]) {
		number = _nextNewStock++;
	} */
	NSNumber *number = [_nextComponentNumbers objectForKey:componentType];
	NSString *name = [[NSString alloc] initWithFormat:@"New %@ %@", componentType, number];
	[(EXPComponent *)component setName:name];
	[_nextComponentNumbers setObject:[NSNumber numberWithInt:([number intValue] + 1)] forKey:componentType];
	[name release];
}

- (int) lineStyleForLine:(int)line;
{
	return 1;
}

- (float) lineThicknessForLine:(int)line
{
	return 1.0;
}

- (int) markerStyleForLine:(int)line
{
	return 0;
}

- (NSColor *) lineColourForLine:(int)line
{
	return [NSColor blackColor];
}

- (NSColor *) markerColourForLine:(int)line
{
	return [NSColor blackColor];
}

- (float) markerSizeForLine:(int)line
{
	return 1.0;
}

- (void) setObjects:(id)objects
{
	[objects retain];
	[_objects release];
	_objects = objects;
}

- (id) objects
{
	return _objects;
}

- (void) setSelection:(id)selection
{
	[selection retain];
	[_selection release];
	_selection = selection;
}

- (id) selection
{
	return _selection;
}

- (void) setTables:(id)tables
{
	[tables retain];
	[_tables release];
	_tables = tables;
}

- (id) tables
{
	return _tables;
}

- (void) setName:(id)name
{
	[name retain];
	[_name release];
	_name = name;
}

- (id) name
{
	return _name;
}

- (void) setIntegrator:(id)integrator
{
	[integrator retain];
	[_integrator release];
	_integrator = integrator;
}

- (id) integrator
{
	return _integrator;
}

- (void) setFixedStep:(BOOL)fixedStep
{
	_fixedStep = fixedStep;
}

- (BOOL) fixedStep
{
	return _fixedStep;
}

- (void) setDoesDrawGrid:(BOOL)drawGrid
{
	_drawGrid = drawGrid;
}

- (BOOL) doesDrawGrid
{
	return _drawGrid;
}

- (void) setDocument:(id)document;
{
	_doc = document;
}

- (id) document;
{
	return _doc;
}

- (void) setOutputMatrix:(id)matrix
{
	[matrix retain];
	[_matrix release];
	_matrix = matrix;
}

- (id) matrix
{
	return _matrix;
}

- (id) option:(NSString *)name
{
	id option = [_options valueForKey:name];
	return option;
}

- (void) setOption:(id)value forName:(NSString *)name
{
	if ([_options valueForKey:name]!=nil) {
		[_options setValue:value forKey:name];
	}
}

- (void) dump
{
	NSArray *objects = [self objects];
	int n = [objects count];
	
	printf("\n************ Dumping Model ************\n");
	
	int i;
	for(i=0; i<n; i++) {
		EXPComponent *component = [objects objectAtIndex:i];
		[component dump];
		printf("\n");
	}
}

- (NSRect) drawingBounds
{
	NSRect bounds = {0.0, 0.0, 0.0, 0.0};
	NSArray *objects = [self objects];
	int n = [objects count];
	
	int i;
	for(i=0; i<n; i++) {
		EXPComponent *component = [objects objectAtIndex:i];
		NSRect rect = [component drawingBounds];
		if (i==0) {
			bounds = rect;
		} else {
			bounds = NSUnionRect(bounds, rect);
		}
//		printf("Component %s\nRect = %s\nBounds = %s\n\n", [[component name] UTF8String], [NSStringFromRect(rect) UTF8String], [NSStringFromRect(bounds) UTF8String]);
	}
	
	return NSInsetRect(bounds, -50.0, -50.0);
}

/*- (void) exportDiagramToFile:(NSString *)fileName
{
//	NSString *fileName = [savePanel filename];
	NSString *ext = [fileName pathExtension];
	NSBitmapImageFileType imageFileType;
	if ([ext caseInsensitiveCompare:@"png"]==NSOrderedSame) {
		imageFileType = NSPNGFileType;
	} else if (([ext caseInsensitiveCompare:@"jpeg"]==NSOrderedSame) || ([ext caseInsensitiveCompare:@"jpg"]==NSOrderedSame)) {
		imageFileType = NSJPEGFileType;
	} else if (([ext caseInsensitiveCompare:@"tiff"]==NSOrderedSame) || ([ext caseInsensitiveCompare:@"tif"]==NSOrderedSame)) {
		imageFileType = NSTIFFFileType;
	} else if ([ext caseInsensitiveCompare:@"gif"]==NSOrderedSame) {
		imageFileType = NSGIFFileType;
	} else if ([ext caseInsensitiveCompare:@"bmp"]==NSOrderedSame) {
		imageFileType = NSBMPFileType;
	} else {
		(void)NSRunAlertPanel(@"DDESolve", @"Invalid image file type.", @"Dismiss", nil, nil);
		return;
	}

// 1121, 763
	NSRect bounds;
//	EXPModelObject *modelObject = [self modelObject];
	bounds = [self drawingBounds];
//	bounds = NSMakeRect(0.0, 0.0, 1121.0, 763.0);
//	bounds = [modelObject drawingBounds]; 
	if (NSIsEmptyRect(bounds)) {
		return;
	}
	
	BOOL grid = [self doesDrawGrid];
	[self setDoesDrawGrid:NO];
	
	EXPModelView *view = [[EXPModelView alloc] initWithFrame:bounds];
	[view setDelegate:self];
	NSWindow* offscreenWindow = [[NSWindow alloc]
									initWithContentRect:NSMakeRect(0.0, 0.0, bounds.size.width + bounds.origin.x, bounds.size.height + bounds.origin.y)
									styleMask:NSBorderlessWindowMask
									backing:NSBackingStoreRetained
									defer:NO];
 
	[offscreenWindow setContentView:view];
	[[offscreenWindow contentView] display];
	
	[view lockFocus];
 
	NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:bounds];
	[view unlockFocus];
	
	NSArray *keys = [[NSArray alloc] initWithObjects:NSImageCompressionFactor, nil];
	NSNumber *compressionFactor = [[NSNumber alloc] initWithFloat:1.0];
	NSArray *attribValues = [[NSArray alloc] initWithObjects:compressionFactor, nil];
	[compressionFactor release];
	NSDictionary *attribs = [[NSDictionary alloc] initWithObjects:attribValues forKeys:keys];
	[keys release];
	[attribValues release];
	NSData *dataRepresentation = [imageRep representationUsingType:imageFileType properties:attribs];
	
	[dataRepresentation writeToFile:fileName atomically:YES];
	
	[imageRep release];
	[offscreenWindow release];
	[view release];

	[self setDoesDrawGrid:grid];

} */

- (void) drawInView:(id)view
{
	NSArray *objects = [self objects];
	NSRect bounds = [view bounds];
	NSDictionary *defaults = [self defaults];
	[[defaults objectForKey:@"BackgroundColour"] set];
	[NSBezierPath fillRect:bounds];
	
	if ([self doesDrawGrid]) {
		float gridSpacing = 50.0;
		float lineDash[2];
		lineDash[0] = 4.0;
		lineDash[1] = 6.0;
		[[NSColor lightGrayColor] set];

		float xp = bounds.origin.x;
		float yp = bounds.origin.y;
		while (xp<=(bounds.origin.x + bounds.size.width)) {
			NSPoint point1 = NSMakePoint(xp, yp);
			NSPoint point2 = NSMakePoint(xp, yp + bounds.size.height);
			NSBezierPath *path = [[NSBezierPath alloc] init];
			[path setLineDash:lineDash count:2 phase:0.0];
			[path moveToPoint:point1];
			[path lineToPoint:point2];
			[path setLineWidth:1.0];
			[path stroke];
//			[NSBezierPath strokeLineFromPoint:point1 toPoint:point2];
			[path release];
			xp += gridSpacing;
		}

		xp = bounds.origin.x;
		yp = bounds.origin.y;
		while (yp<=(bounds.origin.y + bounds.size.height)) {
			NSPoint point1 = NSMakePoint(xp, yp);
			NSPoint point2 = NSMakePoint(xp + bounds.size.width, yp);
//			[[NSColor lightGrayColor] set];
			NSBezierPath *path = [[NSBezierPath alloc] init];
			[path setLineDash:lineDash count:2 phase:0.0];
//			[NSBezierPath strokeLineFromPoint:point1 toPoint:point2];
			[path moveToPoint:point1];
			[path lineToPoint:point2];
			[path setLineWidth:1.0];
			[path stroke];
			[path release];
			yp += gridSpacing;
		}

	}
	
	BOOL drawBoundingBoxes = NO;
	int i;
	for(i=0; i<[objects count]; i++) {
		EXPComponent *component = [objects objectAtIndex:i];
		if (drawBoundingBoxes) {
			NSRect bounds = [component drawingBounds];
			[[NSColor magentaColor] set];
			NSFrameRect(bounds);
		}
		NSSet *selection = [self selection];
		BOOL isSelected = [selection containsObject:component];
		[component drawInView:view isSelected:isSelected];
	}
	
	NSString *XMLString = [[self XMLRepresentation] XMLStringWithOptions:NSXMLNodePrettyPrint];
	NSString *pathName = @"/Users/Ashley/Projects/Objective-C/MathsProgs/DDESolver/EXP-Examples";
	NSString *fileStub = @"output";
	NSString *fileName = [fileStub stringByAppendingPathExtension:@"xmodel"];
	[XMLString writeToFile:[pathName stringByAppendingPathComponent:fileName] atomically:YES encoding:NSUTF8StringEncoding error:nil];
//	fileName = [fileStub stringByAppendingPathExtension:@"png"];
//	[self exportDiagramToFile:[pathName stringByAppendingPathComponent:fileName]];
//	NSRect drawingBounds = [self drawingBounds];
//	NSFrameRect(drawingBounds);
}

- (void) dealloc
{
	[_selection release];
	[_objects release];
	[_tables release];
	[_options release];
	[_defaults release];
	[_nextComponentNumbers release];
	[_matrix release];
	[super dealloc];
}

@end