/*********************************************************************
 * This file is part of the PRAPI library.
 *
 * Copyright (C) 2002 Topi Mäenpää
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.2 $
 *********************************************************************/

#include "Point.h"

namespace prapi { namespace graphics {

	/**
	 * Dimension is used to express, well, dimensions in 2D. The x
	 * coordinate of a Point is used as the width of a Dimension, and
	 * the y coordinate as the height. Additionally, public member
	 * variables "width" and "height" are provided as references to x
	 * and y.
	 **/
	template <class T> class Dimension : public Point<T>
	{
	public:
		/**
		 * Create a new Dimension with the given width and height.
		 **/
		Dimension(T width=0, T height=0) : Point<T>(width,height), width(x), height(y) {}
		/**
		 * Copy a dimension.
		 **/
		Dimension(const Dimension<T>& other) : Point<T>(other), width(x), height(y) {}
		/**
		 * Copy a point to a dimension.
		 **/
		Dimension(const Point<T>& other) : Point<T>(other), width(x), height(y) {}

		/**
		 * Set width and height according to the given Point object.
		 **/
		Dimension& operator= (const Point<T>& other) { Point<T>::operator=(other); }
		/**
		 * Set width and height according to the given Dimension object.
		 **/
		Dimension& operator= (const Dimension& other) { Point<T>::operator=(other); }
		
		/**
		 * The width of the dimension.
		 **/
		T& width;
		/**
		 * The height of the dimension.
		 **/
		T& height;		
	};

	template <class T> std::ostream& operator<< (std::ostream& sout, const Dimension<T>& dim)
	{
		sout << "<dimension width='" << dim.x << "' height='" << dim.y << "'/>";
		return sout;
	}

	template <class T> std::istream& operator>> (std::istream& sin, Dimension<T>& dim)
	{
		using namespace util;
		using namespace util::xml;
		
		XMLParser parser;
		sin >> ws;
		
		SmartPtr<Node> node(parser.readFragment(sin));
		if (node.get() && node->getNodeType() == Node::ELEMENT_NODE)
			{
				Element* element = (Element*)node.get();
				const Node *child = element->getChildNode("dimension.width");
				if (child && child->getNodeType() == Node::ATTRIBUTE_NODE)
					dim.width = String::parse<T>(((Attr*)child)->value);
				else
					throw io::IOException("operator>>(istream&,Dimension&): Input stream does not contain a properly formatted Dimension object.");
				child = element->getChildNode("dimension.height");
				if (child && child->getNodeType() == Node::ATTRIBUTE_NODE)
					dim.height = String::parse<T>(((Attr*)child)->value);
				else
					throw io::IOException("operator>>(istream&,Dimension&): Input stream does not contain a properly formatted Dimension object.");
			}
		return sin;
	}
}}
