/* BBMolecule.m				 
 *
 * This is where all the atoms, bonds an molecule infos are collected and
 * controlled. It just stores the basic data and has nothing to do with the
 * way a molecule is drawn! The actual drawing is perfromed by different
 * shapes.
 *
 * For interface-info see the header file. The comments in this file mostly
 * cover only the real implementation details.
 *
 * Written by: 		Thomas Engel
 * Created:    		15.11.1993 (Copyleft)
 * Last modified: 	17.05.1994
 */

#import "BBMolecule.h"
#import "BBAtom.h"
#import "BBMoleculeShape.h"
#import "BBRenderingStyle.h"

@implementation BBMolecule

- init
{
	BBRenderingStyle *	aStyle;
	N3DShader		 *	aShader;
	
	self = [super init];
	if( !self ) return self;

	// OK. We really are an object...here we go with our init.
	// By default we are the only visible group. This causes settings to be
	// global to the whole molecule. Defaults for color, style etc.
	// And the shapes should be colored as they are by their own nature.

	visibleRegions = [BBSuitcase new];
	[visibleRegions setName:"Default Regions"];
	[visibleRegions setImage:[NXImage findImageNamed:"RegionListIcon"]];

	regionList = [BBSuitcase new];
	[regionList setName:"Custom Regions"];
	[regionList setImage:[NXImage findImageNamed:"RegionListIcon"]];

	[self setName:"Untitled Molecule"];
	[self setImage:[NXImage findImageNamed:"MoleculeIcon"]];
	[self addObject:visibleRegions];
	[self addObject:regionList];
			
	// Here we will set the drawing and rotation style.
	// See the BUGS section for details.
		
	aStyle = [BBRenderingStyle new];
	[aStyle setSurfaceType:N3D_SmoothSolids];
	[aStyle setGeometryType:BB_RenderedShape];
	aShader = [N3DShader new];
	[aShader setShader:"matte"];
	[aStyle setShader:aShader];
	[aStyle setShadingQuality:BB_GoodQuality];
	[aStyle setGeometryQuality:BB_GoodQuality];
	[self setDrawingStyle:aStyle];

	aStyle = [BBRenderingStyle new];
	[aStyle setSurfaceType:N3D_ShadedWireFrame];
	[aStyle setGeometryType:BB_RenderedShape];
	aShader = [N3DShader new];
	[aShader setShader:"matte"];
	[aStyle setShader:aShader];
	[aStyle setShadingQuality:BB_PoorQuality];
	[aStyle setGeometryQuality:BB_PoorQuality];
	[self setRotationStyle:aStyle];

	return self;
}

- free
{
	// Let's free what we created. The list cause the bonds, atoms, groups
	// and shapes to free themselves.
	// Atom- and BondList are freeed by our superclass. But their contents
	// would be not. Remember: Regions (=super) only handle references to
	// certain objects!
	
	[atomList freeObjects];
	[bondList freeObjects];
	[[regionList freeObjects] free];
	[visibleRegions free];
	
	return [super free];
}

- setBeaker:aBeaker
{
	beaker = aBeaker;

	// At the time set beaker is being called all the atoms are loaded and it
	// is save to create a region that does show every bond and atom.
	// I should creat a class that does always match the exact molecule data.
	// This should be easy by using the same suitcases inside the region as I
	// do inside the molecule.
	// I can use the molecule itself because if would end in a infinite tree!!
	
	[self visibleRegions];
	return self;
}

- beaker
{
	return beaker;
}

- addAtom:anAtom
{
	// Befroe we will add a new atom we will set the reference to ourself.
	
	[anAtom setMolecule:self];
	return [super addAtom:anAtom];
}

- addRegion:aRegion
{
	[regionList addObject:aRegion];
	return self;
}

- regionList
{
	return regionList;
}

- addVisibleRegion:aRegion
{
	// Here we set the visible regions. This object is a list object that
	// has references to every region that should be drawn.

	[visibleRegions addObject:aRegion];
	return self;
}

- visibleRegions
{
	// If we don't have any visible regions we will create a default.
	// The default is the whole molecule.

	int	i;
		
	if( [visibleRegions count] == 0 )
	{
		if( defaultRegion ) [defaultRegion free];
		
		defaultRegion = [BBRegion new];
		[defaultRegion setName:"Whole Molecule"];
		
		for( i=0; i<[atomList count]; i++ )
			[defaultRegion addAtom:[atomList objectAt:i]];
		for( i=0; i<[bondList count]; i++ )
			[defaultRegion addBond:[bondList objectAt:i]];
		[visibleRegions addObject:defaultRegion];
	}

	return visibleRegions;
}

- defaultRegion
{
	return defaultRegion;
}
- shapeClass
{
	return [BBMoleculeShape class];
}

- shape
{
	id	ourShape;
	
	ourShape = [[[self shapeClass] alloc] initFrom:[self visibleRegions]
										  asPartOf:self];
	return ourShape;
}

@end

/*
 * History: 17.05.94 Added flexible shape creation.
 *
 *			02.05.94 Made it a BBSuitcase.
 *
 *			27.03.94 Init take care of defineing the draw/roteStyles.
 *
 *			10.03.94 Added a simple region addition to the visibleRegions
 *
 *			09.03.94 Made it a subclass of BBMoleculeGroup and changed the
 *					 name to BBRegion. And switched groups to regions.
 *
 *			15.01.94 Added the color support and visible groups.
 *
 *			12.01.94 Changed the naming stuff
 *
 *			10.01.94 Changed some methods to work properly with our
 *					 new objectWell.
 *
 *			28.12.93 Added the objectImage stuff to the old simple atom/bond
 *					 handling molecule methods.
 *					 Added the groupList.
 *
 *
 * Bugs: - Setting the name during init should support localization!
 *
 *		 - I'm not sure about freeing the visibleGroup objects..but I hope
 *		   it doesn't matter in future versions.
 *
 *		 - Init styles does not ask the prefs for the right settings. Hm.
 *		   Instead of definit some styles at startup I should connect to the
 *		   prefs StyleObjects and return them instead. This will allow updating
 *		   when they are changed...But doesHaveDrawingSetting should return NO
 *		   as long as we don't have one of our own!.
 *		   Maybe the BBRegion is a better place for those changes.
 *
 *		- Creating the default region inside setBeaker is somewhat stupid but
 *		  currently a good quick hack :-)
 *
 *		- I could set the name of the default molecule to something that 
 *		  reflects the molecules name too.
 */