Index: trunk/nv/gui/gui_element.hh
===================================================================
--- trunk/nv/gui/gui_element.hh	(revision 268)
+++ trunk/nv/gui/gui_element.hh	(revision 269)
@@ -23,19 +23,41 @@
 	namespace gui
 	{
+
+		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
 		{
-		protected:
+		public:
 			/// List type
-			typedef std::list<element*> list;
+			typedef std::list<handle> list;
 
 
-			explicit element( const rectangle& r )
+			element()
 				: m_id( "" )
-				, m_parent( nullptr )
+				, m_this()
+				, m_parent()
 				, m_children()
 				, m_child_count(0)
 				, m_class("")
-				, m_relative( r )
-				, m_absolute( r )
+				, m_relative()
+				, m_absolute()
 				, m_enabled( true )
 				, m_visible( true )
@@ -43,7 +65,4 @@
 				, m_render_data( nullptr ) {}
 
-		protected:
-			virtual ~element() { delete m_render_data; }
-		protected:
 			friend class environment;
 			friend class renderer;
@@ -51,5 +70,6 @@
 
 			string    m_id;              ///< id type of the object
-			element*  m_parent;          ///< pointer to parent
+			handle    m_this;            ///< pointer to parent
+			handle    m_parent;          ///< pointer to parent
 			list      m_children;        ///< children objects
 			size_t    m_child_count;     ///< number of children
Index: trunk/nv/gui/gui_environment.hh
===================================================================
--- trunk/nv/gui/gui_environment.hh	(revision 268)
+++ trunk/nv/gui/gui_environment.hh	(revision 269)
@@ -26,9 +26,4 @@
 	namespace gui
 	{
-		class handle
-		{
-
-		};
-
 		class environment
 		{
@@ -37,31 +32,52 @@
 			// temporary
 			void load_style( const std::string& filename );
-			element* create_element( element* parent, const rectangle& r );
-			void set_text( element* e, const string& text );
-			void set_class( element* e, const string& text );
+			handle create_element( const rectangle& r );
+			handle create_element( handle parent, const rectangle& r );
+			void set_text( handle e, const string& text );
+			void set_class( handle  e, const string& text );
 			void update();
 			void draw();
-			void destroy_element( element* e );
+			void destroy_element( handle e );
 			bool process_io_event( const io_event& ev );
 			virtual ~environment();
 		protected:
-			element* get_element( const position& p );
-			void add_child( element* child );
-			void add_child( element* parent, element* child );
-			void remove_child( element* parent, element* child );
-			void destroy_children( element* e );
-			void update( element* e, uint32 elapsed );
-			void draw( element* e );
-			bool process_io_event( element* e, const io_event& ev );
-			element* get_deepest_child( element* e, const position& p );
-			void move_to_top( element* child );
-			void move_to_bottom( element* child );
-			void set_relative( element* e, const rectangle& r );
-			void set_relative( element* e, const position& p );
-			void recalculate_absolute( element* e );
+			handle create_handle();
+			handle create_index( sint16 element_id );
+			element* get_element( handle h );
+			handle get_element( const position& p );
+			void add_child( handle child );
+			void add_child( handle parent, handle child );
+			void remove_child( handle parent, handle child );
+			void destroy_children( handle e );
+			void update( handle e, uint32 elapsed );
+			void draw( handle e );
+			bool process_io_event( handle e, const io_event& ev );
+			handle get_deepest_child( handle e, const position& p );
+			void move_to_top( handle child );
+			void move_to_bottom( handle child );
+			void set_relative( handle e, const rectangle& r );
+			void set_relative( handle e, const position& p );
+			void recalculate_absolute( handle e );
 			
+			struct index
+			{
+				sint16 element_id;
+				uint16 counter;
+				sint32 next_free;
+
+				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;
+
 			renderer*    m_renderer;
 			window*      m_window;
-			element*     m_screen;
+			handle       m_screen;
 			rectangle    m_area;
 		};
Index: trunk/src/gui/gui_environment.cc
===================================================================
--- trunk/src/gui/gui_environment.cc	(revision 268)
+++ trunk/src/gui/gui_environment.cc	(revision 269)
@@ -26,8 +26,13 @@
 
 nv::gui::environment::environment( window* w, const std::string& shader_path )
-	: m_renderer( nullptr ), m_window( w ), m_screen( nullptr )
+	: m_renderer( nullptr ), m_window( w ), m_first_free(-1), m_last_free(-1)
 {
 	m_area.dim( dimension( w->get_width(), w->get_height() ) );
-	m_screen = new element( m_area );
+	
+	m_screen           = create_handle();
+	element* screen    = get_element( m_screen );
+	screen->m_absolute = m_area;
+	screen->m_relative = m_area;
+
 	m_renderer = new renderer( w, shader_path );
 }
@@ -38,46 +43,118 @@
 }
 
-nv::gui::element* nv::gui::environment::create_element( element* parent, const rectangle& r )
-{
-	element* result = new element( r );
-	if ( parent == nullptr ) parent = m_screen;
+nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
+{
+	return create_element( m_screen, r );
+}
+
+nv::gui::handle nv::gui::environment::create_element( handle parent, const rectangle& r )
+{
+	if ( parent.is_nil() ) parent = m_screen;
+	handle result = create_handle();
+	element* e    = get_element( result );
+	e->m_absolute = r;
+	e->m_relative = r;
 	add_child( parent, result );
 	return result;
 }
 
-void nv::gui::environment::destroy_element( element* e )
-{
+nv::gui::handle nv::gui::environment::create_handle()
+{
+	m_elements.emplace_back();
+	m_elements.back().m_this = create_index( uint16( 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;
+	}
+}
+
+void nv::gui::environment::destroy_element( handle e )
+{
+	element* dead_element = get_element( e );
+	if ( dead_element == nullptr ) return;
 	destroy_children( e );
-	if ( e->m_parent ) 
-	{
-		remove_child( e->m_parent, e );
-	}
-	delete e;
-}
-
-void nv::gui::environment::update( element* e, uint32 elapsed )
-{
-//	e->on_update( elapsed );
-	if ( e->m_visible )
-	{
-		for ( element* i : e->m_children )
+	remove_child( dead_element->m_parent, e );
+
+	delete dead_element->m_render_data; 
+	dead_element->m_render_data = nullptr;
+	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 );
+}
+
+void nv::gui::environment::update( handle e, uint32 elapsed )
+{
+	element* el = get_element( e );
+	if ( !el ) return;
+	//	el->on_update( elapsed );
+	if ( el->m_visible )
+	{
+		for ( handle i : el->m_children )
 		{
 			update( i, elapsed );
 		}
 	}
-	if ( e->m_dirty || e->m_render_data == nullptr )
-	{
-		m_renderer->redraw( e, elapsed );
-		e->m_dirty = false;
-	}
-}
-
-void nv::gui::environment::draw( element* e )
-{
-	if ( e->m_visible )
-	{
-//		e->on_draw();
-		m_renderer->draw( e );
-		for ( element* i : e->m_children )
+	if ( el->m_dirty || el->m_render_data == nullptr )
+	{
+		m_renderer->redraw( el, elapsed );
+		el->m_dirty = false;
+	}
+}
+
+void nv::gui::environment::draw( handle e )
+{
+	element* el = get_element( e );
+	if ( !el ) return;
+	if ( el->m_visible )
+	{
+//		el->on_draw();
+		m_renderer->draw( el );
+		for ( handle i : el->m_children )
 		{
 			draw(i);
@@ -97,28 +174,31 @@
 }
 
-void nv::gui::environment::add_child( element* child )
+void nv::gui::environment::add_child( handle child )
 {
 	add_child( m_screen, child );
 }
 
-void nv::gui::environment::add_child( element* parent, element* child )
-{
-	if ( child )
-	{
-		if ( child->m_parent )
-		{
-			remove_child( child->m_parent, child );
+void nv::gui::environment::add_child( handle parent, handle child )
+{
+	element* e = get_element( child );
+	element* p = get_element( parent );
+	if ( e && p )
+	{
+		remove_child( e->m_parent, child );
+		e->m_parent = parent;
+		p->m_children.push_back( child );
+		p->m_child_count++;
+	}
+}
+
+void nv::gui::environment::destroy_children( handle e )
+{
+	element* parent = get_element(e);
+	if ( parent )
+	{
+		while ( !parent->m_children.empty() )
+		{
+			destroy_element( parent->m_children.front() );
 		}
-		child->m_parent = parent;
-		parent->m_children.push_back( child );
-		parent->m_child_count++;
-	}
-}
-
-void nv::gui::environment::destroy_children( element* e )
-{
-	while ( !e->m_children.empty() )
-	{
-		destroy_element( e->m_children.front() );
 	}
 }
@@ -127,5 +207,5 @@
 nv::gui::environment::~environment()
 {
-	destroy_element( m_screen );
+	destroy_children( handle() );
 	delete m_renderer;
 }
@@ -136,36 +216,46 @@
 }
 
-bool nv::gui::environment::process_io_event( element* e, const io_event& ev )
-{
-	return e->m_parent ? process_io_event( e->m_parent, ev ) : false;
-}
-
-nv::gui::element* nv::gui::environment::get_element( const position& p )
+bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
+{
+	element* el = get_element( e );
+	return el && el->m_parent.m_index ? process_io_event( el->m_parent, ev ) : false;
+}
+
+nv::gui::handle nv::gui::environment::get_element( const position& p )
 {
 	return get_deepest_child( m_screen, p );
 }
 
-nv::gui::element* nv::gui::environment::get_deepest_child( element* e, const position& p )
-{
-	if ( !e->m_visible ) return nullptr;
-
-	element* result = nullptr;
-	element::list::reverse_iterator it = e->m_children.rbegin();
-
-	while ( it != e->m_children.rend() )
+nv::gui::element* nv::gui::environment::get_element( handle h )
+{
+	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;
+}
+
+nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
+{
+	element* el = get_element(e);
+	if ( !el && !el->m_visible ) return handle();
+
+	handle result;
+	element::list::reverse_iterator it = el->m_children.rbegin();
+
+	while ( it != el->m_children.rend() )
 	{
 		result = get_deepest_child( *it, p );
-		if ( result ) return result;
+		if ( result.m_index ) return result;
 		++it;
 	}
 
-	if ( e->m_absolute.contains(p) ) return e;
-	return nullptr;
-}
-
-void nv::gui::environment::move_to_top( element* child )
-{
-	element* parent = child->m_parent;
-	if ( parent )
+	if ( el->m_absolute.contains(p) ) return e;
+	return handle();
+}
+
+void nv::gui::environment::move_to_top( handle child )
+{
+	element* e      = get_element( child );
+	element* parent = get_element( e->m_parent );
+	if ( e && parent )
 	{
 		auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
@@ -179,8 +269,9 @@
 }
 
-void nv::gui::environment::move_to_bottom( element* child )
-{
-	element* parent = child->m_parent;
-	if ( parent )
+void nv::gui::environment::move_to_bottom( handle child )
+{
+	element* e      = get_element( child );
+	element* parent = get_element( e->m_parent );
+	if ( e && parent )
 	{
 		auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
@@ -194,28 +285,31 @@
 }
 
-void nv::gui::environment::set_relative( element* e, const rectangle& r )
-{
-	e->m_dirty    = true;
-	e->m_relative = r;
-	recalculate_absolute( e );
-}
-
-void nv::gui::environment::set_relative( element* e, const position& p )
-{
-	set_relative( e, rectangle( p, p + e->m_relative.get_size() ) );
-}
-
-void nv::gui::environment::recalculate_absolute( element* e )
-{
-	rectangle pabsolute;
-
-	if ( e->m_parent )
-	{
-		pabsolute = e->m_parent->m_absolute;
-	}
-
-	e->m_absolute = e->m_relative + pabsolute.ul;
-
-	for ( element* o : e->m_children )
+void nv::gui::environment::set_relative( handle e, const rectangle& r )
+{
+	element* el = get_element(e);
+	if ( el )
+	{
+		el->m_dirty    = true;
+		el->m_relative = r;
+		recalculate_absolute( e );
+	}
+}
+
+void nv::gui::environment::set_relative( handle e, const position& p )
+{
+	element* el = get_element(e);
+	if ( el )
+	{
+		set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
+	}
+}
+
+void nv::gui::environment::recalculate_absolute( handle e )
+{
+	element* el = get_element(e);
+	rectangle pabsolute = get_element( el->m_parent )->m_absolute;
+	el->m_absolute = el->m_relative + pabsolute.ul;
+
+	for ( handle o : el->m_children )
 	{
 		recalculate_absolute( o );
@@ -223,29 +317,37 @@
 }
 
-void nv::gui::environment::set_class( element* e, const string& text )
-{
-	e->m_class = text;
-	e->m_dirty = true;
-}
-
-void nv::gui::environment::set_text( element* e, const string& text )
-{
-	e->m_text = text;
-	e->m_dirty = true;
-}
-
-void nv::gui::environment::remove_child( element* parent, element* child )
-{
-	if ( child->m_parent != parent )
-	{
-		return; // signal error?
-	}
-	auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
-	if ( it != parent->m_children.end() )
-	{
-		(*it)->m_parent = nullptr;
-		parent->m_children.erase(it);
-	}	
-
-}
-
+void nv::gui::environment::set_class( handle e, const string& text )
+{
+	element* ep = get_element(e);
+	if ( ep != nullptr )
+	{
+		ep->m_class = text;
+		ep->m_dirty = true;
+	}
+}
+
+void nv::gui::environment::set_text( handle e, const string& text )
+{
+	element* ep = get_element(e);
+	if ( ep != nullptr )
+	{
+		ep->m_text = text;
+		ep->m_dirty = true;
+	}
+}
+
+void nv::gui::environment::remove_child( handle parent, handle child )
+{
+	element* p = get_element( parent );
+	if ( p )
+	{
+		auto it = std::find( p->m_children.begin(), p->m_children.end(), child );
+		if ( it != p->m_children.end() )
+		{
+			element* e = get_element( *it );
+			e->m_parent = handle();
+			p->m_children.erase(it);
+		}	
+	}
+}
+
Index: trunk/tests/gui_test/nv_gui_test.cc
===================================================================
--- trunk/tests/gui_test/nv_gui_test.cc	(revision 268)
+++ trunk/tests/gui_test/nv_gui_test.cc	(revision 269)
@@ -23,5 +23,5 @@
 	nv::clear_state m_clear_state;
 	nv::gui::environment* m_guienv;
-	std::vector<nv::gui::element*>   m_windows;
+	std::vector<nv::gui::handle>   m_windows;
 };
 
@@ -86,5 +86,5 @@
 	glm::ivec2 a( std::rand() % 600, std::rand() % 400 );
 	glm::ivec2 b( std::rand() % 200 + 40, std::rand() % 200 + 40 );
-	nv::gui::element* e = m_guienv->create_element( nullptr, nv::rectangle(a).dim(b) );
+	nv::gui::handle e = m_guienv->create_element( nv::rectangle(a).dim(b) );
 	m_guienv->set_class( e, "window" );
 	m_guienv->set_text( e, "Window "+nv::to_string(m_windows.size()+1) );
