/*	MiscDiagramShape.m

	Copyright 1996 Uwe Hoffmann.

	This notice may not be removed from this source code.
	The use and distribution of this software is governed by the
	terms of the MiscKit license agreement.  Refer to the license
	document included with the MiscKit distribution for the terms.

	Version 2 (August 1996)
*/

#import <Foundation/Foundation.h>
#import <MiscFoundation/MiscUtilities.h>

#import "MiscDiagramShape.h"
#import "MiscCircleShape.h"
#import "MiscCylinderShape.h"
#import "MiscDiamondShape.h"
#import "MiscHexagonShape.h"
#import "MiscHorizontalArrowShape.h"
#import "MiscHorizontalTriangleShape.h"
#import "MiscParallelLinesShape.h"
#import "MiscParallelogramShape.h"
#import "MiscRectangleShape.h"
#import "MiscRoundedRectShape.h"
#import "MiscVerticalArrowShape.h"
#import "MiscVerticalTriangleShape.h"
#import "MiscTDUtils.h"								 


@implementation MiscDiagramShape
/*"The MiscDiagramShape class cluster manages shapes equivalent to the symbols 
found in Diagram(tm) from Lighthouse Design.


The shape type of an MiscDiagramShape instance cannot be changed. You have to instantiate
a new instance with the appropiate shape and the bounds of the old instance.

A MiscDiagramShape instance can be moved with #moveTo: and resized with #sizeTo: and #innerSizeTo:. 
The method #bounds returns the shape bounds
and #innerBounds returns the bounds of a rectangle of maximum size inscribed in the shape.
The class method #calcSizeForInnerSize: gives the minimal size for a shape type such that a
rectangle of a given size can be fully inscribed.
The bounds and innerBounds are defined like this:

Shapes can be drawn in a view with #drawOutline, #drawFill and #drawShadowWithDelta:.

The method #hit provides hit detection with a hit path and the method #calcIntersection:angle:toPoint:
calculates the intersection of a shape with a line running through the shape's middle.
The angle of the intersection is given in degrees and is defined like this: 

"*/ 

 

- initWithShapeType:(MiscShapeType)aShapeType bounds:(NSRect)aRect
/*"Initializes a new MiscDiagramShape instance of type aShapeType and bounds aRect."*/
{
    	id shape = nil;
            
	switch(aShapeType){
		case MiscCircleShapeType:
			shape = [[MiscCircleShape allocWithZone:[self zone]] initBounds:aRect];
			break;
		case MiscCylinderShapeType:
			shape = [[MiscCylinderShape allocWithZone:[self zone]] initBounds:aRect];
			break;
		case MiscDiamondShapeType:
			shape = [[MiscDiamondShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscHexagonShapeType:	
			shape = [[MiscHexagonShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscHorizontalArrowShapeType:
			shape = [[MiscHorizontalArrowShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscHorizontalTriangleShapeType:
			shape = [[MiscHorizontalTriangleShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscParallelLinesShapeType:
			shape = [[MiscParallelLinesShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscParallelogramShapeType:
			shape = [[MiscParallelogramShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscRectangleShapeType:
			shape = [[MiscRectangleShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscRoundedRectShapeType:
			shape = [[MiscRoundedRectShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscVerticalArrowShapeType:
			shape = [[MiscVerticalArrowShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
		case MiscVerticalTriangleShapeType:
			shape = [[MiscVerticalTriangleShape allocWithZone:[self zone]] initBounds:aRect];
                        break;
	}
	[self release];
        return shape;
}

+ shapeOfType:(MiscShapeType)aShapeType bounds:(NSRect)aRect
/*"Creates and returns a new MiscDiagramShape instance of type aShapeType and bounds aRect."*/
{
	return [[[self alloc] initWithShapeType:aShapeType bounds:aRect] autorelease];
}

// ******************************************************************
// placeholders, not very interesting

- (NSRect)bounds
/*"Returns the bounds of the receiver. See figure above for the 
difference between bounds and inner bounds."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return NSMakeRect(0,0,0,0);
}

- (NSRect)innerBounds
/*"Returns the inner bounds of the receiver. See figure above for the 
difference between bounds and inner bounds."*/

{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return NSMakeRect(0,0,0,0);
}

- (MiscShapeType)shapeType
/*"Returns the shape type of the receiver."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return MiscCircleShapeType;
}


- (void)moveTo:(NSPoint)aPos
/*"Moves the receiver to point aPos."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- (void)sizeTo:(NSSize)aSize
/*"Changes size of receiver to aSize. See figure above for the 
difference between bounds and inner bounds."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- (void)innerSizeTo:(NSSize)aSize
/*"Changes inner size of receiver to aSize. See figure above for the 
difference between bounds and inner bounds."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- (void)calcIntersection:(NSPoint *)ip angle:(float *)alpha toPoint:(NSPoint)aPoint
/*"Calculates the intersection of a line running through aPoint and the middle point of the
receiver's bounds with the receiver's outline. The resulting intersection point is placed 
in ip and the resulting intersection angle (given in degrees) in alpha. See figure above
for a definition of the intersection angle."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

+ (NSSize)calcSizeForInnerSize:(NSSize)aSize shapeType:(MiscShapeType)aShapeType
/*"Calculates the minimal size for a shape of type aShapeType such that a rectangle 
of size aSize can be inscribed in the shape."*/ 
{
    	NSSize size;
        
	switch(aShapeType){
		case MiscCircleShapeType:
			size = [MiscCircleShape calcSizeForInnerSize:aSize];
            		break;
		case MiscCylinderShapeType:
			size = [MiscCylinderShape calcSizeForInnerSize:aSize];
                        break;
		case MiscDiamondShapeType:
			size = [MiscDiamondShape calcSizeForInnerSize:aSize];
                        break;
		case MiscHexagonShapeType:	
			size = [MiscHexagonShape calcSizeForInnerSize:aSize];
                        break;
		case MiscHorizontalArrowShapeType:
			size = [MiscHorizontalArrowShape calcSizeForInnerSize:aSize];
                        break;
		case MiscHorizontalTriangleShapeType:
			size = [MiscHorizontalTriangleShape calcSizeForInnerSize:aSize];
                        break;
		case MiscParallelLinesShapeType:
			size = [MiscParallelLinesShape calcSizeForInnerSize:aSize];
                        break;
		case MiscParallelogramShapeType:
			size = [MiscParallelogramShape calcSizeForInnerSize:aSize];
                        break;
		case MiscRectangleShapeType:
			size = [MiscRectangleShape calcSizeForInnerSize:aSize];
                        break;
		case MiscRoundedRectShapeType:
			size = [MiscRoundedRectShape calcSizeForInnerSize:aSize];
                        break;
		case MiscVerticalArrowShapeType:
			size = [MiscVerticalArrowShape calcSizeForInnerSize:aSize];
                        break;
		case MiscVerticalTriangleShapeType:
			size = [MiscVerticalTriangleShape calcSizeForInnerSize:aSize];
                        break;
	}
        return size;
}

- (void)reflectHorizontal
/*"Reflects the receiver horizontally (with the vertical axis through
the horizontal middle point as the reflection axis).
This method affects only shapes which are  asymmetrical with respect to
the reflection axis."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
    	return;
}

- (void)reflectVertical
/*"Reflects the receiver vertically (with the horizontal axis through
the vertical middle point as the reflection axis).
This method affects only shapes which are  asymmetrical with respect to
the reflection axis."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
    	return;
}

- (BOOL)reflectedHorizontal
/*"Returns whether the receiver is reflected horizontally."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
    	return NO;
}

- (BOOL)reflectedVertical
/*"Returns whether the receiver is reflected vertically."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
    	return NO;
}

- (void)setReflectHorizontal:(BOOL)aBool
/*"Sets the horizontal reflection state of the receiver."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
        return;
}

- (void)setReflectVertical:(BOOL)aBool
/*"Sets the vertical reflection state of the receiver."*/
{
    	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
        return;
}

- (void)drawOutline
/*"Draws the shape outline. The PostScript focus must be 
locked on a view when this method is invoked."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- (void)drawFill
/*"Draws the shape fill. The PostScript focus must be 
locked on a view when this method is invoked."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- (void)drawShadowWithDelta:(NSPoint)aPos
/*"Draws the shape fill with the receiver displaced with delta aPos. 
The PostScript focus must be locked on a view when this method is invoked."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- (BOOL)hitOutline:(MiscHitPath *)hitPath
/*"Returns whether the hit path hitPath intersects the outline of the receiver.
The PostScript focus must be locked on a view when this method is invoked."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return NO;
}

- (BOOL)hitFill:(MiscHitPath *)hitPath
/*"Returns whether the hit path hitPath intersects the fill of the receiver.
The PostScript focus must be locked on a view when this method is invoked."*/
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return NO;
}

- initWithCoder:(NSCoder *)coder
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return nil;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return;
}

- copyWithZone:(NSZone *)aZone
{
	MiscRequiresConcreteImplementation(self, _cmd, [MiscDiagramShape class]);
	return nil;
}

- copy
{
	return [self copyWithZone:NSDefaultMallocZone()];
}
		              
@end


	
