Index: trunk/nv/gui/gui_common.hh
===================================================================
--- trunk/nv/gui/gui_common.hh	(revision 350)
+++ trunk/nv/gui/gui_common.hh	(revision 351)
@@ -16,4 +16,5 @@
 #include <nv/core/common.hh>
 #include <nv/core/handle.hh>
+#include <nv/core/flags.hh>
 
 namespace nv
@@ -21,4 +22,13 @@
 	namespace gui
 	{
+		enum flag
+		{
+			ENABLED,  //!< GUI element accepts events
+			VISIBLE,  //!< GUI element visible
+			DIRTY,    //!< GUI element needs redraw
+			SELECTED, //!< GUI element selected
+			HOVER,    //!< GUI element in hover zone
+		};
+
 		enum alignment
 		{
@@ -43,4 +53,6 @@
 		typedef nv::handle<> handle;
 
+		typedef nv::flags< 32, flag > flags;
+
 	} // namespace gui
 
Index: trunk/nv/gui/gui_element.hh
===================================================================
--- trunk/nv/gui/gui_element.hh	(revision 350)
+++ trunk/nv/gui/gui_element.hh	(revision 351)
@@ -32,16 +32,7 @@
 			typedef std::list<handle> list;
 
-
-			element()
-				: m_id( "" )
-				, m_child_count(0)
-				, m_class("")
-				, m_enabled( true )
-				, m_visible( true )
-				, m_dirty( true )
-				, m_render_data( nullptr ) {}
-
 			string    m_id;              ///< id type of the object
 			handle    m_parent;          ///< pointer to parent
+			flags     m_flags;
 			list      m_children;        ///< children objects
 			size_t    m_child_count;     ///< number of children
@@ -50,7 +41,4 @@
 			rectangle m_relative; ///< Position relative to parent.
 			rectangle m_absolute; ///< Position relative to window/screen.
-			bool m_enabled; ///< Whether the element accepts events.
-			bool m_visible; ///< Whether the element is drawn.
-			bool m_dirty; ///< Whether the element needs updating.
 			render_data* m_render_data; ///<   -?-
 		};
Index: trunk/nv/gui/gui_environment.hh
===================================================================
--- trunk/nv/gui/gui_environment.hh	(revision 350)
+++ trunk/nv/gui/gui_environment.hh	(revision 351)
@@ -43,4 +43,5 @@
 			virtual ~environment();
 		protected:
+			bool set_selected( handle e );
 			handle get_element( const position& p );
 			void add_child( handle child );
@@ -57,5 +58,5 @@
 			void set_relative( handle e, const position& p );
 			void recalculate_absolute( handle e );
-			
+
 			handle_store< element, handle > m_elements;
 			renderer*     m_renderer;
@@ -63,4 +64,6 @@
 			handle        m_screen;
 			rectangle     m_area;
+			position      m_mouse_position;
+			handle        m_selected;
 		};
 
Index: trunk/nv/gui/gui_renderer.hh
===================================================================
--- trunk/nv/gui/gui_renderer.hh	(revision 350)
+++ trunk/nv/gui/gui_renderer.hh	(revision 351)
@@ -30,14 +30,4 @@
 	namespace gui
 	{
-		struct vertex
-		{
-			ivec2 position;
-			vec2  texcoord;
-			vec4  color;
-			vertex() {}
-			vertex( const nv::ivec2& cr, const nv::vec2& tc, const nv::vec4& c )
-				: position( cr ), texcoord( tc ), color( c ) {}
-		};
-
 		struct image_info
 		{
@@ -63,4 +53,6 @@
 			void draw( element* e );
 			void draw();
+			void on_hover_change( element* e, bool hover );
+			void on_select_change( element* e, bool select );
 			virtual ~renderer();
 		private:
Index: trunk/nv/gui/gui_style.hh
===================================================================
--- trunk/nv/gui/gui_style.hh	(revision 350)
+++ trunk/nv/gui/gui_style.hh	(revision 351)
@@ -28,11 +28,12 @@
 			style();
 			void load_style( const std::string& filename );
-			bool get( element* e, const char* centry, std::string& s );
-			bool get( element* e, const char* centry, vec4& vec );
-			bool get( element* e, const char* centry, int& i );
-			bool get( element* e, const char* centry, double& d );
+			bool get( element* e, const char* centry, const char* cselector, std::string& s );
+			bool get( element* e, const char* centry, const char* cselector, vec4& vec );
+			bool get( element* e, const char* centry, const char* cselector, int& i );
+			bool get( element* e, const char* centry, const char* cselector, double& d );
 			~style();
 		protected:
-			bool resolve( const char* cid, const char* cclass, const char* centry, int type );
+			bool find_entry( const char* cselector, const char* centry, int type );
+			bool resolve( const char* cid, const char* cclass, const char* cselector, const char* centry, int type );
 		protected:
 			lua::state m_lua; //!< separate lua state for style calculation
Index: trunk/nv/interface/image_data.hh
===================================================================
--- trunk/nv/interface/image_data.hh	(revision 350)
+++ trunk/nv/interface/image_data.hh	(revision 351)
@@ -28,4 +28,6 @@
 		RGB16F,
 		RGBA16F,
+		BGR,
+		BGRA,
 	};
 	
@@ -48,5 +50,5 @@
 		const ivec2 get_size() const { return m_size; }
 		// TODO : better depth check (template?)
-		size_t get_depth()    const { return m_format.format == RGB ? 3 : 4; }
+		size_t get_depth()    const { return m_format.format == RGB || m_format.format == BGR ? 3 : 4; }
 		image_format get_format() const { return m_format; }
 		~image_data() {	if (m_data) delete[] m_data; }
Index: trunk/nv/lib/detail/gl_types.inc
===================================================================
--- trunk/nv/lib/detail/gl_types.inc	(revision 350)
+++ trunk/nv/lib/detail/gl_types.inc	(revision 351)
@@ -243,4 +243,5 @@
 #define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
 #define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
 #define GL_MAX_ELEMENTS_VERTICES 0x80E8
 #define GL_MAX_ELEMENTS_INDICES 0x80E9
Index: trunk/src/gl/gl_enum.cc
===================================================================
--- trunk/src/gl/gl_enum.cc	(revision 350)
+++ trunk/src/gl/gl_enum.cc	(revision 351)
@@ -180,4 +180,6 @@
 	case RGB16F  : return GL_RGB;
 	case RGBA16F : return GL_RGBA;
+	case BGR     : return GL_BGR;
+	case BGRA    : return GL_BGRA;
 	NV_RETURN_COVERED_DEFAULT( 0 );
 	}
@@ -194,4 +196,6 @@
 	case RGB16F  : return GL_RGBA16F;
 	case RGBA16F : return GL_RGBA16F;
+	case BGR     : return GL_RGB8;
+	case BGRA    : return GL_RGBA8;
 	NV_RETURN_COVERED_DEFAULT( 0 );
 	}
Index: trunk/src/gui/gui_environment.cc
===================================================================
--- trunk/src/gui/gui_environment.cc	(revision 350)
+++ trunk/src/gui/gui_environment.cc	(revision 351)
@@ -29,11 +29,6 @@
 {
 	m_area.dim( dimension( w->get_width(), w->get_height() ) );
-	
-	m_screen           = m_elements.create();
-	element* screen    = m_elements.get( m_screen );
-	screen->m_absolute = m_area;
-	screen->m_relative = m_area;
-
 	m_renderer = new renderer( w );
+	m_screen   = create_element( handle(), m_area );
 }
 
@@ -51,4 +46,5 @@
 {
 	if ( parent.is_nil() ) parent = m_screen;
+
 	handle result = m_elements.create();
 	element* e    = m_elements.get( result );
@@ -58,7 +54,14 @@
 	if ( ar.ul.y < 0 ) { ar.ul.y += m_area.lr.y; ar.lr.y += m_area.lr.y; }
 
+	e->m_child_count = 0;
+	e->m_flags[ENABLED] = true;
+	e->m_flags[VISIBLE] = true;
+	e->m_flags[DIRTY]   = true;
+	e->m_render_data    = nullptr;
 	e->m_absolute = ar;
 	e->m_relative = ar;
-	add_child( parent, result );
+
+	if ( !parent.is_nil() ) // screen creation
+		add_child( parent, result );
 	return result;
 }
@@ -83,5 +86,17 @@
 	if ( !el ) return;
 	//	el->on_update( elapsed );
-	if ( el->m_visible )
+	if ( el->m_flags[ENABLED] )
+	{
+		bool hover     = el->m_flags[HOVER];
+		bool new_hover = el->m_absolute.contains( m_mouse_position );
+		if ( hover != new_hover )
+		{
+			el->m_flags[HOVER] = new_hover;
+			// gain loose hover event
+			m_renderer->on_hover_change( el, hover );
+		}
+	}
+
+	if ( el->m_flags[VISIBLE] )
 	{
 		for ( handle i : el->m_children )
@@ -90,8 +105,8 @@
 		}
 	}
-	if ( el->m_dirty || el->m_render_data == nullptr )
+	if ( el->m_flags[DIRTY] || el->m_render_data == nullptr )
 	{
 		m_renderer->redraw( el, elapsed );
-		el->m_dirty = false;
+		el->m_flags[DIRTY] = false;
 	}
 }
@@ -101,5 +116,5 @@
 	element* el = m_elements.get( e );
 	if ( !el ) return;
-	if ( el->m_visible )
+	if ( el->m_flags[VISIBLE] )
 	{
 //		el->on_draw();
@@ -160,6 +175,46 @@
 }
 
-bool nv::gui::environment::process_io_event( const io_event& )
-{
+bool nv::gui::environment::process_io_event( const io_event& ev )
+{
+	switch ( ev.type )
+	{
+//	case EV_KEY          :
+	case EV_MOUSE_BUTTON :
+		if ( ev.mbutton.pressed && ev.mbutton.button == MOUSE_LEFT )
+		{ 
+			handle h = get_element( position( ev.mbutton.x, ev.mbutton.y ) );
+			set_selected( h );
+			return true;
+		}
+		return false;
+	case EV_MOUSE_MOVE:
+		m_mouse_position = position( ev.mmove.x, ev.mmove.y );
+		return false;
+//	case EV_MOUSE_WHEEL  :
+	default:
+		break;
+	}
+	return false;
+}
+
+bool nv::gui::environment::set_selected( handle e )
+{
+	if ( e != m_selected )
+	{
+		element* eold = m_elements.get( m_selected );
+		element* el   = m_elements.get( e );
+		if ( eold )
+		{
+			eold->m_flags[SELECTED] = false;
+			m_renderer->on_select_change( eold, false );
+		}
+		if ( el )
+		{
+			el->m_flags[SELECTED] = true;
+			m_renderer->on_select_change( el, true );
+		}
+		m_selected = e;
+		return true;
+	}
 	return false;
 }
@@ -179,5 +234,5 @@
 {
 	element* el = m_elements.get(e);
-	if ( !el && !el->m_visible ) return handle();
+	if ( !el && !el->m_flags[VISIBLE] ) return handle();
 
 	handle result;
@@ -206,5 +261,5 @@
 			parent->m_children.erase( it );
 			parent->m_children.push_back( child );
-			parent->m_dirty = true;
+			parent->m_flags[DIRTY] = true;
 		}	
 	}
@@ -222,5 +277,5 @@
 			parent->m_children.erase( it );
 			parent->m_children.push_front( child );
-			parent->m_dirty = true;
+			parent->m_flags[DIRTY] = true;
 		}
 	}
@@ -232,6 +287,6 @@
 	if ( el )
 	{
-		el->m_dirty    = true;
-		el->m_relative = r;
+		el->m_flags[DIRTY] = true;
+		el->m_relative     = r;
 		recalculate_absolute( e );
 	}
@@ -264,6 +319,6 @@
 	if ( ep != nullptr )
 	{
-		ep->m_class = text;
-		ep->m_dirty = true;
+		ep->m_class        = text;
+		ep->m_flags[DIRTY] = true;
 	}
 }
@@ -274,6 +329,6 @@
 	if ( ep != nullptr )
 	{
-		ep->m_text = text;
-		ep->m_dirty = true;
+		ep->m_text         = text;
+		ep->m_flags[DIRTY] = true;
 	}
 }
Index: trunk/src/gui/gui_renderer.cc
===================================================================
--- trunk/src/gui/gui_renderer.cc	(revision 350)
+++ trunk/src/gui/gui_renderer.cc	(revision 351)
@@ -44,4 +44,16 @@
 using namespace nv;
 using namespace nv::gui;
+
+struct vertex
+{
+	ivec2 position;
+	vec2  texcoord;
+	vec4  color;
+	vertex() {}
+	vertex( const nv::ivec2& cr, const nv::vec2& tc, const nv::vec4& c )
+		: position( cr ), texcoord( tc ), color( c )
+	{
+	}
+};
 
 const ivec2 atlas_size = ivec2( 1024, 1024 );
@@ -239,6 +251,10 @@
 		std::string path;
 		std::string text;
-
-		if ( m_style.get( e, "skin", path ) )
+		const char* stext[] = { nullptr, "selected", "hover" };
+		const char* selector = stext[border];
+		if ( e->m_flags[HOVER] )    selector = stext[2];
+		if ( e->m_flags[SELECTED] ) selector = stext[1];
+
+		if ( m_style.get( e, "skin", selector, path ) )
 		{
 			size_t image_id = load_image( path );
@@ -286,5 +302,5 @@
 		{
 
-			if ( m_style.get( e, "border", border ) && m_style.get( e, "border_color", color ) )
+			if ( m_style.get( e, "border", selector, border ) && m_style.get( e, "border_color", selector, color ) )
 			{
 				rectangle inner = abs.shrinked( border );
@@ -296,5 +312,5 @@
 			}
 
-			if ( m_style.get( e, "background_color", color ) )
+			if ( m_style.get( e, "background_color", selector, color ) )
 			{
 				qvec.emplace_back( abs.ul, abs.lr, color );
@@ -305,5 +321,5 @@
 		if ( !text.empty() )
 		{
-			if ( m_style.get( e, "text_color", color ) && m_style.get( e, "text_font", path ) && m_style.get( e, "text_size", border ) )
+			if ( m_style.get( e, "text_color", selector, color ) && m_style.get( e, "text_font", selector, path ) && m_style.get( e, "text_size", selector, border ) )
 			{
 				size_t font_id = load_font( path, (uint16)border );
@@ -331,4 +347,19 @@
 }
 
+void renderer::on_hover_change( element* e, bool hover )
+{
+	// TODO: FIX
+	NV_LOG( nv::LOG_DEBUG, "on_hover_change" );
+	e->m_flags[DIRTY] = true;
+}
+
+void renderer::on_select_change( element* e, bool select )
+{
+	// TODO: FIX
+	NV_LOG( nv::LOG_DEBUG, "on_select_change" );
+	e->m_flags[DIRTY] = true;
+}
+
+
 void renderer::draw( element* e )
 {
Index: trunk/src/gui/gui_style.cc
===================================================================
--- trunk/src/gui/gui_style.cc	(revision 350)
+++ trunk/src/gui/gui_style.cc	(revision 351)
@@ -21,16 +21,16 @@
 }
 
-bool style::get( element* e, const char* centry, std::string& s )
+bool style::get( element* e, const char* centry, const char* cselector, std::string& s )
 {
 	lua::stack_guard guard( m_lua );
-	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), centry, LUA_TSTRING ) ) return false;
+	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), cselector, centry, LUA_TSTRING ) ) return false;
 	s = lua_tostring( m_lua, -1 );
 	return true;
 }
 
-bool style::get( element* e, const char* centry, vec4& vec )
+bool style::get( element* e, const char* centry, const char* cselector, vec4& vec )
 {
 	lua::stack_guard guard( m_lua );
-	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), centry, LUA_TTABLE ) ) return false;
+	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), cselector, centry, LUA_TTABLE ) ) return false;
 	vec = vec4();
 	for (size_t i = 0; i < 4; ++i )
@@ -44,16 +44,16 @@
 }
 
-bool style::get( element* e, const char* centry, int& i )
+bool style::get( element* e, const char* centry, const char* cselector, int& i )
 {
 	lua::stack_guard guard( m_lua );
-	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), centry, LUA_TNUMBER ) ) return false;
+	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), cselector, centry, LUA_TNUMBER ) ) return false;
 	i = static_cast< int >( lua_tointeger( m_lua, -1 ) );
 	return true;
 }
 
-bool style::get( element* e, const char* centry, double& d )
+bool style::get( element* e, const char* centry, const char* cselector, double& d )
 {
 	lua::stack_guard guard( m_lua );
-	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), centry, LUA_TNUMBER ) ) return false;
+	if ( !resolve( e->m_id.c_str(), e->m_class.c_str(), cselector, centry, LUA_TNUMBER ) ) return false;
 	d = lua_tonumber( m_lua, -1 );
 	return true;
@@ -64,5 +64,30 @@
 }
 
-bool style::resolve( const char* cid, const char* cclass, const char* centry, int type )
+bool style::find_entry( const char* cselector, const char* centry, int type )
+{
+	if ( lua_istable( m_lua, -1 ) )
+	{
+		if ( cselector )
+		{
+			lua_getfield( m_lua, -1, cselector );
+			if ( lua_istable( m_lua, -1 ) )
+			{
+				lua_getfield( m_lua, -1, centry );
+				if ( lua_type( m_lua, -1 ) == type ) 
+				{
+					return true;
+				}
+				lua_pop( m_lua, 1 );
+			}
+			lua_pop( m_lua, 1 );
+		}
+
+		lua_getfield( m_lua, -1, centry );
+		if ( lua_type( m_lua, -1 ) == type ) return true;
+	}
+	return false;
+}
+
+bool style::resolve( const char* cid, const char* cclass, const char* cselector, const char* centry, int type )
 {
 	lua_getglobal( m_lua, "default" );
@@ -71,23 +96,14 @@
 	// check id
 	lua_getfield( m_lua, -1, cid );
-	if ( lua_istable( m_lua, -1 ) )
-	{
-		lua_getfield( m_lua, -1, centry );
-		if ( lua_type( m_lua, -1 ) == type ) return true;
-	}
+	if ( find_entry( cselector, centry, type ) ) return true;
 	lua_settop( m_lua, global );
 
 	// check class
 	lua_getfield( m_lua, -1, cclass );
-	if ( lua_istable( m_lua, -1 ) )
-	{
-		lua_getfield( m_lua, -1, centry );
-		if ( lua_type( m_lua, -1 ) == type ) return true;
-	}
+	if ( find_entry( cselector, centry, type ) ) return true;
 	lua_settop( m_lua, global );
 
 	// check entry
-	lua_getfield( m_lua, -1, centry );
-	if ( lua_type( m_lua, -1 ) == type ) return true;
+	if ( find_entry( cselector, centry, type ) ) return true;
 	return false;
 }
Index: trunk/tests/gui_test/nv_gui_test.cc
===================================================================
--- trunk/tests/gui_test/nv_gui_test.cc	(revision 350)
+++ trunk/tests/gui_test/nv_gui_test.cc	(revision 351)
@@ -80,4 +80,5 @@
 				break;
 			}
+			m_guienv->process_io_event( event );
 		}
 	}
Index: trunk/tests/gui_test/premake4.lua
===================================================================
--- trunk/tests/gui_test/premake4.lua	(revision 350)
+++ trunk/tests/gui_test/premake4.lua	(revision 351)
@@ -15,4 +15,4 @@
 		objdir ("../../".._ACTION.."/release")
 
+	dofile("../../nv.lua")
 	dofile("gui_test.lua")
-	dofile("../../nv.lua")
Index: trunk/tests/gui_test/test.style.lua
===================================================================
--- trunk/tests/gui_test/test.style.lua	(revision 350)
+++ trunk/tests/gui_test/test.style.lua	(revision 351)
@@ -10,6 +10,10 @@
 		skin = "button.png",
 
-		[":hover"] = {
+		hover = {
 			text_color = { 1.0, 1.0, 1.0, 1.0 },
+		},
+
+		selected = {
+			text_color = { 1.0, 1.0, 0.0, 1.0 },
 		}
 
