Index: /trunk/nv/common.hh
===================================================================
--- /trunk/nv/common.hh	(revision 269)
+++ /trunk/nv/common.hh	(revision 270)
@@ -191,4 +191,5 @@
 	};
 
+
 } // namespace nv
 
Index: /trunk/nv/gui/gui_common.hh
===================================================================
--- /trunk/nv/gui/gui_common.hh	(revision 269)
+++ /trunk/nv/gui/gui_common.hh	(revision 270)
@@ -15,4 +15,5 @@
 
 #include <nv/common.hh>
+#include <nv/handle.hh>
 
 namespace nv
@@ -40,4 +41,7 @@
 		class renderer;
 
+		typedef nv::handle<> handle;
+		typedef nv::index_store<handle> index_store;
+
 	} // namespace gui
 
Index: /trunk/nv/gui/gui_element.hh
===================================================================
--- /trunk/nv/gui/gui_element.hh	(revision 269)
+++ /trunk/nv/gui/gui_element.hh	(revision 270)
@@ -24,24 +24,4 @@
 	{
 
-		class handle
-		{
-		public:
-			handle() : m_index(0), m_counter(0) {}
-
-			inline bool operator==(const handle& rhs){return m_index == rhs.m_index && m_counter == rhs.m_counter; }
-			inline bool operator!=(const handle& rhs){return !(*this == rhs);}
-
-			bool is_nil() { return m_index == 0 && m_counter == 0; }
-			bool is_valid() { return !is_nil(); }
-		private:
-			friend class environment;
-
-			explicit handle( uint16 a_index, uint16 a_counter ) : m_index( a_index ), m_counter(a_counter) {}
-
-			uint16 m_index;
-			uint16 m_counter;
-		};
-
-
 		class element
 		{
@@ -53,19 +33,10 @@
 			element()
 				: m_id( "" )
-				, m_this()
-				, m_parent()
-				, m_children()
 				, m_child_count(0)
 				, m_class("")
-				, m_relative()
-				, m_absolute()
 				, m_enabled( true )
 				, m_visible( true )
 				, m_dirty( true )
 				, m_render_data( nullptr ) {}
-
-			friend class environment;
-			friend class renderer;
-			friend class style;
 
 			string    m_id;              ///< id type of the object
Index: /trunk/nv/gui/gui_environment.hh
===================================================================
--- /trunk/nv/gui/gui_environment.hh	(revision 269)
+++ /trunk/nv/gui/gui_environment.hh	(revision 270)
@@ -26,4 +26,5 @@
 	namespace gui
 	{
+
 		class environment
 		{
@@ -43,5 +44,4 @@
 		protected:
 			handle create_handle();
-			handle create_index( sint16 element_id );
 			element* get_element( handle h );
 			handle get_element( const position& p );
@@ -60,21 +60,7 @@
 			void recalculate_absolute( handle e );
 			
-			struct index
-			{
-				sint16 element_id;
-				uint16 counter;
-				sint32 next_free;
+			std::vector< element > m_elements;
 
-				index() : element_id(0), counter(0), next_free(-1) {}
-			};
-			uint16 get_free_index();
-			void free_index( uint16 idx_index );
-
-			sint32 m_first_free;
-			sint32 m_last_free;
-
-			std::vector< element > m_elements;
-			std::vector< index >   m_indices;
-
+			index_store      m_indexes;
 			renderer*    m_renderer;
 			window*      m_window;
Index: /trunk/nv/handle.hh
===================================================================
--- /trunk/nv/handle.hh	(revision 270)
+++ /trunk/nv/handle.hh	(revision 270)
@@ -0,0 +1,125 @@
+// Copyright (C) 2014 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+/**
+ * @file handle.hh
+ * @author Kornel Kisielewicz
+ */
+
+#ifndef NV_HANDLE_HH
+#define NV_HANDLE_HH
+
+#include <nv/common.hh>
+#include <nv/array.hh>
+
+namespace nv
+{
+
+	template < 
+		typename T = uint32, 
+		unsigned IBITS = 16,
+		unsigned CBITS = 16,
+		typename TAG = void 
+	>
+	class handle
+	{
+	public:
+		typedef T value_type;
+		static const int INDEX_BITS   = IBITS;
+		static const int COUNTER_BITS = IBITS;
+		static const T MAX_INDEX   = (1 << IBITS) - 1;
+		static const T MAX_COUNTER = (1 << CBITS) - 1;
+
+		handle() : m_index(0), m_counter(0) {}
+
+		inline bool operator==(const handle& rhs){return m_index == rhs.m_index && m_counter == rhs.m_counter; }
+		inline bool operator!=(const handle& rhs){return !(*this == rhs);}
+
+		bool is_nil() const { return m_index == 0 && m_counter == 0; }
+		bool is_valid() const { return !is_nil(); }
+
+	protected:
+		T m_index   : IBITS;
+		T m_counter : CBITS;
+
+		handle( T a_index, T a_counter ) : m_index( a_index ), m_counter( a_counter ) {}
+		template < typename H, typename I >
+		friend class index_store;
+	};
+
+	template < typename HANDLE, typename TINDEX = sint32 >
+	class index_store
+	{
+	public:
+		typedef HANDLE handle;
+		typedef TINDEX index_type;
+		typedef typename HANDLE::value_type value_type;
+
+		index_store() : m_first_free(-1), m_last_free(-1) {}
+
+		handle create_handle( index_type index )
+		{
+			value_type i       = get_free_entry();
+			m_entries[i].index = index;
+			m_entries[i].counter++;
+			return handle( i, m_entries[i].counter );
+		}
+
+		void free_handle( handle h )
+		{
+			m_entries[ h.m_index ].index     = -1;
+			m_entries[ h.m_index ].next_free = -1;
+			if ( m_last_free == -1 )
+			{
+				m_first_free = m_last_free = h.m_index;
+				return;
+			}
+			m_entries[ m_last_free ].next_free = h.m_index;
+			m_last_free = h.m_index;
+		}
+
+		void swap_indices( handle h1, handle h2 )
+		{
+			std::swap( m_entries[ h1.m_index ].index, m_entries[ h2.m_index ].index );
+		}
+
+		sint32 get_index( handle h ) const
+		{
+			return m_entries[ h.m_index ].counter == h.m_counter ? m_entries[ h.m_index ].index : -1;
+		}
+	private:
+		struct index_entry
+		{
+			index_type index;
+			value_type counter;
+			index_type next_free;
+
+			index_entry() : index(0), counter(0), next_free(-1) {}
+		};
+
+		value_type get_free_entry()
+		{
+			if ( m_first_free != -1 )
+			{
+				value_type result = (value_type)m_first_free;
+				m_first_free = m_entries[result].next_free;
+				m_entries[result].next_free = -1;
+				if ( m_first_free == -1 ) m_last_free = -1;
+				return result;
+			}
+			m_entries.emplace_back();
+			return value_type( m_entries.size() - 1 );
+		}
+
+		index_type m_first_free;
+		index_type m_last_free;
+		std::vector< index_entry > m_entries;
+	};
+
+
+}
+
+#endif // NV_HANDLE_HH
Index: /trunk/src/gui/gui_environment.cc
===================================================================
--- /trunk/src/gui/gui_environment.cc	(revision 269)
+++ /trunk/src/gui/gui_environment.cc	(revision 270)
@@ -26,5 +26,5 @@
 
 nv::gui::environment::environment( window* w, const std::string& shader_path )
-	: m_renderer( nullptr ), m_window( w ), m_first_free(-1), m_last_free(-1)
+	: m_renderer( nullptr ), m_window( w )
 {
 	m_area.dim( dimension( w->get_width(), w->get_height() ) );
@@ -62,46 +62,6 @@
 {
 	m_elements.emplace_back();
-	m_elements.back().m_this = create_index( uint16( m_elements.size() - 1 ) );
+	m_elements.back().m_this = m_indexes.create_handle( sint32( m_elements.size() - 1 ) );
 	return m_elements.back().m_this;
-}
-
-nv::gui::handle nv::gui::environment::create_index( sint16 element_id )
-{
-	uint16 i   = get_free_index();
-	index& idx = m_indices[i];
-	idx.element_id = element_id;
-	idx.counter++;
-	return handle( i, idx.counter );
-}
-
-nv::uint16 nv::gui::environment::get_free_index()
-{
-	if ( m_first_free != -1 )
-	{
-		uint16 result = (uint16)m_first_free;
-		m_first_free = m_indices[result].next_free;
-		m_indices[result].next_free = -1;
-		if ( m_first_free == -1 ) m_last_free = -1;
-		return result;
-	}
-	m_indices.emplace_back();
-	return uint16( m_indices.size() - 1 );
-}
-
-void nv::gui::environment::free_index( uint16 idx_index )
-{
-	// TODO: reuse
-	index& idx = m_indices[ idx_index ];
-	idx.element_id = -1;
-	idx.next_free  = -1;
-	if ( m_last_free == -1 )
-	{
-		m_first_free = m_last_free = idx_index;
-	}
-	else
-	{
-		m_indices[ m_last_free ].next_free = idx_index;
-		m_last_free = idx_index;
-	}
 }
 
@@ -117,14 +77,13 @@
 	dead_element->m_parent = handle();
 
-	uint16 dead_index    = m_indices[ e.m_index ].element_id;
-	if ( dead_index != m_elements.size()-1 )
-	{
-		m_elements[ dead_index ] = m_elements.back();
-		m_elements.pop_back();
-		m_indices[ m_elements[ dead_index ].m_this.m_index ].element_id = dead_index;
-	}
-	else
-		m_elements.pop_back();
-	free_index( e.m_index );
+	handle swap_handle    = m_elements.back().m_this;
+	sint32 dead_eindex    = m_indexes.get_index( e );
+	if ( dead_eindex != (sint32)m_elements.size()-1 )
+	{
+		m_elements[ dead_eindex ] = m_elements.back();
+	}
+	m_elements.pop_back();
+	m_indexes.swap_indices( e, swap_handle );
+	m_indexes.free_handle( e );
 }
 
@@ -219,5 +178,5 @@
 {
 	element* el = get_element( e );
-	return el && el->m_parent.m_index ? process_io_event( el->m_parent, ev ) : false;
+	return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
 }
 
@@ -230,6 +189,6 @@
 {
 	if ( h.is_nil() ) return nullptr;
-	const index& idx = m_indices[ h.m_index ];
-	return idx.counter == h.m_counter && idx.element_id >= 0 ? &m_elements[ idx.element_id ] : nullptr;
+	sint32 eindex = m_indexes.get_index( h );
+	return eindex >= 0 ? &m_elements[ eindex ] : nullptr;
 }
 
@@ -245,5 +204,5 @@
 	{
 		result = get_deepest_child( *it, p );
-		if ( result.m_index ) return result;
+		if ( result.is_valid() ) return result;
 		++it;
 	}
