/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	DrawableTree.cpp
 *
 *****************************************************************************/

// SOL++2000

#include <sol\FileStream.h>
#include <sol\StringTokenizer.h>
#include <sol\DrawableTree.h>


int DrawableTree::CONSTANT = 0;
int DrawableTree::VARIABLE = 1;
	

DrawableTree::DrawableTree()
{
	arranged    = FALSE;
	leftMargin  = 20;
	topMargin   = 20;

	horizSpacing = 20;
	vertSpacing  = 15;
	arrangementPolicy = VARIABLE;
	connectionPolicy  = DrawableNode::LINEAR;

	activeNode = null;
	width       = 0;
	height      = 0;
	font		= null;
	pen			= null; //new Pen(PS_SOLID, 1, RGB(128,128,128));	//gray
}


DrawableTree::~DrawableTree()
{
	//delete font;
	//delete pen;
}


void DrawableTree::draw(DC* dc, int x, int y)
{
	DrawableNode* root = (DrawableNode*) getRoot();
	if(root) {
	
		HGDIOBJ hfont = NULL;
		if(font) {
			hfont = dc-> select(font);
		}
		HPEN hpen = NULL;
		if(pen) {
			hpen =(HPEN) dc->select(pen);
		}

		if(arranged == FALSE) {
			char* name = root -> getName();
			SIZE size;

			dc -> getTextExtent(name, strlen(name), &size);
			int height  = size.cy;
			if(arrangementPolicy == VARIABLE) {
				root -> arrange(dc, horizSpacing, 
					height + vertSpacing,
					leftMargin, topMargin);
			}
			else {
				int maxLen = root -> nodeMaxLength(dc, 0);
				root -> arrange(maxLen+ horizSpacing,
						height + vertSpacing,
						leftMargin, topMargin);
			}
			arranged = TRUE;
		}
		root -> draw(dc, root, connectionPolicy, x, y);

		if(pen)
		 dc->select(hpen);

		if(font) {
			dc -> select(hfont);
		}
	}
}


DrawableNode* DrawableTree::search(DC* dc, int x, int y)
{
	DrawableNode* root = (DrawableNode*) getRoot();
	if(root) {
		HGDIOBJ hfont = NULL;
		if(font) {
			hfont = dc-> select(font);
		}
		DrawableNode* node = root->search(dc, x, y);
		if(font) {
			dc -> select(hfont);
		}
		return node;
	}
	else {
		return NULL;
	}
}


int DrawableTree::load(const char* fileName)
{
	int status = 0;
	char buffer[128];
	char parent[128];
	char word[128];

	FileStream stream;
	if(stream.openReadOnly(fileName) < 0) {
		return FALSE;
	}

	DrawableNode* node;
	DrawableNode* root;

    StringTokenizer analyzer;
	while(stream.getLine(buffer, 128) != FALSE) {
		if(strcmp(buffer, "") == 0) continue;

		analyzer.getToken(buffer, word, sizeof(word)-1);
		if(strcmp(word, "") == 0) continue;
		if(strcmp(word, "{") == 0) {
			status = 1;
			continue;
		}
		if(strcmp(word, "}") == 0) {
			status = 0;
			continue;
		}
		if(strcmp(word, "") !=0 && status == 0) {
			strcpy(parent, word);
			if(getRoot() == NULL)
				setRoot(new DrawableNode(parent));
			continue;
		}
		if(strcmp(word, "") != 0 && status == 1) {
			root = (DrawableNode*) getRoot();
			if (root) {
				node = root -> search(parent);
				if (node) {
					node -> add(new DrawableNode(node, word));
				}
			}
			continue;
		}
	}
	stream.close();

	root = (DrawableNode*) getRoot();
	root -> configure(0, 0);
	root -> reconfigure();
	return TRUE;
}


void DrawableTree::setActiveNode(DrawableNode* node, DC* dc, int x, int y)
{
	HGDIOBJ hfont = NULL;
	if(font) {
		hfont = dc->select(font);
	}
	SIZE size;
	if(activeNode && node) {
		activeNode->setStatus(FALSE);
		activeNode->drawSelf(dc, -x, -y, &size);
	}
	activeNode = node;
	if(activeNode) {
		activeNode->setStatus(TRUE);
		activeNode->drawSelf(dc, -x, -y, &size);
	}

	if(font) {
		dc -> select(hfont);
	}
}

void DrawableTree::setBackground(COLORREF normal, COLORREF active)
{
	DrawableNode* root = (DrawableNode*)getRoot();
	if(root) {
		root -> setBackground(normal, active);
	}
}


void DrawableTree::setTextColor(COLORREF normal, COLORREF active)
{
	DrawableNode* root = (DrawableNode*)getRoot();
	if(root) {
		root -> setTextColor(normal, active);
	}
}


void DrawableTree::computeExtent(DC* dc, int* w, int* h)
{
	width  = 0;
	height = 0;
	DrawableNode* root = (DrawableNode*)getRoot();

	HGDIOBJ hfont = NULL;
	if(font) {
		hfont = dc->select(font);
	}

	if(root) {	
		root -> getExtent(dc, &width, &height);
		width  += leftMargin;
		height += topMargin;
	}
	*w = width;
	*h = height;

	if(font) {
		dc -> select(hfont);
	}
}
