Index: trunk/nv/position.hh
===================================================================
--- trunk/nv/position.hh	(revision 65)
+++ trunk/nv/position.hh	(revision 65)
@@ -0,0 +1,99 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+/**
+ * @file gui_element.hh
+ * @author Kornel Kisielewicz
+ * @brief UI 2D positioning classes
+ */
+
+#ifndef NV_POSITION_HH
+#define NV_POSITION_HH
+
+#include <glm/glm.hpp>
+#include <nv/common.hh>
+#include <utility>
+
+namespace nv
+{
+	typedef glm::ivec2 position;
+	typedef glm::ivec2 dimension;
+
+	struct rectangle
+	{
+		typedef position::value_type value_type;
+		typedef std::size_t size_type;
+		typedef rectangle type;
+		
+		union 
+		{
+			struct { position upper_left; position lower_right; };
+			struct { position ul;         position lr; };
+			struct { value_type x1,y1,x2,y2; };
+		};
+
+		rectangle() : ul(), lr() {}
+		rectangle( position p ) : ul(p), lr(p) {}
+		rectangle( position ul, position lr ) : ul(ul), lr(lr) {}
+		rectangle( position ul, value_type width, value_type height ) : ul(ul), lr(ul + position(width,height)) {}
+		rectangle& dim( dimension d ) { lr = ul + d; return *this; }
+		rectangle& pos( position p )  { lr = p + (lr - ul); lr = p; return *this; }
+
+		void set_dimension( dimension d ) { lr = ul + d; }
+		void set_position( position p ) { lr = p + (lr - ul); ul = p; }
+
+		dimension get_dimension() const { return lr - ul; }
+		position  get_position() const { return ul; }
+		dimension get_size() const { return lr - ul; }
+		position get_center() const { return ( lr + ul ) / 2; }
+		value_type get_width() const { return x2 - x1; }
+		value_type get_height() const { return y2 - y1; }
+		value_type get_area() const { return (y2 - y1) * (x2 - x1); }
+		bool is_valid() const {	return x2 >= x1 && y2 >= y1; }
+		
+		rectangle& operator+=( const position& pos ) { ul += pos; lr += pos; return (*this); }
+		rectangle operator+( const position& pos ) const {	rectangle r(*this); return r += pos; }
+		rectangle& operator-=( const position& pos ) { ul -= pos; lr -= pos; return (*this); }
+		rectangle operator-( const position& pos ) const {	rectangle r(*this); return r -= pos; }
+		bool operator==( const rectangle& r ) { return r.ul == ul && r.lr == lr; }
+		bool operator!=( const rectangle& r ) { return r.ul != ul || r.lr != lr; }
+
+		bool contains( const position& r ) const{ return y2 >= r.y && y1 <= r.y && x2 >= r.x && x1 <= r.x; }
+		bool contains( const rectangle& r ) const { return contains( r.ul ) && contains( r.lr ); }
+		bool collides( const rectangle& r ) const { return y2 > r.y1 && y1 < r.y2 && x2 > r.x1 && x1 < r.x2; }
+
+		bool clamp_to( const rectangle& r )
+		{
+			ul = glm::max( ul, r.ul );
+			lr = glm::min( lr, r.lr );
+			ul = glm::min( ul, lr );
+		}
+
+		bool constrain_to( const rectangle& r )
+		{
+			if ( r.get_width() < get_width() || r.get_height() < get_height() ) return false;
+			(*this) += glm::min( r.ul - ul, position() );
+			(*this) -= glm::min( lr - r.lr, position() );
+			return true;
+		}
+
+		void repair() 
+		{
+			if (x1 > x2) std::swap( x1, x2 );
+			if (y1 > y2) std::swap( y1, y2 );
+		}
+
+		void include_point( position p )
+		{
+			lr = glm::max( lr, p );
+			ul = glm::min( lr, p );
+		}
+
+	};
+
+}
+
+#endif NV_POSITION_HH
