source: trunk/src/gui/gui_environment.cc @ 270

Last change on this file since 270 was 270, checked in by epyon, 11 years ago
  • nv::handle - generic handle implementation
  • nv::index_store - index store based on handles
  • gui elements fully based on handles instead of pointers
File size: 7.3 KB
RevLine 
[69]1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/gui/gui_environment.hh"
8
[126]9#include "nv/gui/gui_renderer.hh"
10
11
12        /*
13
14        TODO: parse a lua stylesheet as per Trac wiki
15
16        IDEA: Store everything in std::unordered_maps, with lua_value's?
17
18        A lua_value is a variant stores strings as const char* that deletes them on destructor?
19        Question is that there might not be much gained on speed anyway, due to Lua's speed.
20        Special function field allows delayed per parse execution?
21
22        */
23
[152]24#include "nv/gfx/sliced_buffer.hh"
[126]25#include "nv/gfx/texture_atlas.hh"
26
[267]27nv::gui::environment::environment( window* w, const std::string& shader_path )
[270]28        : m_renderer( nullptr ), m_window( w )
[126]29{
30        m_area.dim( dimension( w->get_width(), w->get_height() ) );
[269]31       
32        m_screen           = create_handle();
33        element* screen    = get_element( m_screen );
34        screen->m_absolute = m_area;
35        screen->m_relative = m_area;
36
[234]37        m_renderer = new renderer( w, shader_path );
[126]38}
39
40void nv::gui::environment::load_style( const std::string& filename )
41{
42        m_renderer->load_style( filename );
43}
44
[269]45nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
[257]46{
[269]47        return create_element( m_screen, r );
48}
49
50nv::gui::handle nv::gui::environment::create_element( handle parent, const rectangle& r )
51{
52        if ( parent.is_nil() ) parent = m_screen;
53        handle result = create_handle();
54        element* e    = get_element( result );
55        e->m_absolute = r;
56        e->m_relative = r;
[268]57        add_child( parent, result );
[257]58        return result;
59}
60
[269]61nv::gui::handle nv::gui::environment::create_handle()
[264]62{
[269]63        m_elements.emplace_back();
[270]64        m_elements.back().m_this = m_indexes.create_handle( sint32( m_elements.size() - 1 ) );
[269]65        return m_elements.back().m_this;
66}
67
68void nv::gui::environment::destroy_element( handle e )
69{
70        element* dead_element = get_element( e );
71        if ( dead_element == nullptr ) return;
[264]72        destroy_children( e );
[269]73        remove_child( dead_element->m_parent, e );
74
75        delete dead_element->m_render_data;
76        dead_element->m_render_data = nullptr;
77        dead_element->m_parent = handle();
78
[270]79        handle swap_handle    = m_elements.back().m_this;
80        sint32 dead_eindex    = m_indexes.get_index( e );
81        if ( dead_eindex != (sint32)m_elements.size()-1 )
[268]82        {
[270]83                m_elements[ dead_eindex ] = m_elements.back();
[268]84        }
[270]85        m_elements.pop_back();
86        m_indexes.swap_indices( e, swap_handle );
87        m_indexes.free_handle( e );
[264]88}
89
[269]90void nv::gui::environment::update( handle e, uint32 elapsed )
[126]91{
[269]92        element* el = get_element( e );
93        if ( !el ) return;
94        //      el->on_update( elapsed );
95        if ( el->m_visible )
[257]96        {
[269]97                for ( handle i : el->m_children )
[257]98                {
[268]99                        update( i, elapsed );
[257]100                }
101        }
[269]102        if ( el->m_dirty || el->m_render_data == nullptr )
[126]103        {
[269]104                m_renderer->redraw( el, elapsed );
105                el->m_dirty = false;
[126]106        }
107}
108
[269]109void nv::gui::environment::draw( handle e )
[69]110{
[269]111        element* el = get_element( e );
112        if ( !el ) return;
113        if ( el->m_visible )
[257]114        {
[269]115//              el->on_draw();
116                m_renderer->draw( el );
117                for ( handle i : el->m_children )
[257]118                {
[268]119                        draw(i);
[257]120                }
121        }
[69]122}
[126]123
[267]124void nv::gui::environment::update()
[126]125{
[257]126        update( m_screen, 0 );
[126]127}
128
[267]129void nv::gui::environment::draw()
[126]130{
[257]131        draw( m_screen );
[126]132        m_renderer->draw();
133}
134
[269]135void nv::gui::environment::add_child( handle child )
[126]136{
[268]137        add_child( m_screen, child );
[126]138}
139
[269]140void nv::gui::environment::add_child( handle parent, handle child )
[268]141{
[269]142        element* e = get_element( child );
143        element* p = get_element( parent );
144        if ( e && p )
[268]145        {
[269]146                remove_child( e->m_parent, child );
147                e->m_parent = parent;
148                p->m_children.push_back( child );
149                p->m_child_count++;
[268]150        }
151}
152
[269]153void nv::gui::environment::destroy_children( handle e )
[264]154{
[269]155        element* parent = get_element(e);
156        if ( parent )
[264]157        {
[269]158                while ( !parent->m_children.empty() )
159                {
160                        destroy_element( parent->m_children.front() );
161                }
[264]162        }
163}
164
165
[267]166nv::gui::environment::~environment()
[126]167{
[269]168        destroy_children( handle() );
[126]169        delete m_renderer;
170}
171
[267]172bool nv::gui::environment::process_io_event( const io_event& )
173{
174        return false;
175}
176
[269]177bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
[267]178{
[269]179        element* el = get_element( e );
[270]180        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
[267]181}
182
[269]183nv::gui::handle nv::gui::environment::get_element( const position& p )
[267]184{
185        return get_deepest_child( m_screen, p );
186}
187
[269]188nv::gui::element* nv::gui::environment::get_element( handle h )
[267]189{
[269]190        if ( h.is_nil() ) return nullptr;
[270]191        sint32 eindex = m_indexes.get_index( h );
192        return eindex >= 0 ? &m_elements[ eindex ] : nullptr;
[269]193}
[267]194
[269]195nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
196{
197        element* el = get_element(e);
198        if ( !el && !el->m_visible ) return handle();
[267]199
[269]200        handle result;
201        element::list::reverse_iterator it = el->m_children.rbegin();
202
203        while ( it != el->m_children.rend() )
[267]204        {
[268]205                result = get_deepest_child( *it, p );
[270]206                if ( result.is_valid() ) return result;
[267]207                ++it;
208        }
209
[269]210        if ( el->m_absolute.contains(p) ) return e;
211        return handle();
[267]212}
213
[269]214void nv::gui::environment::move_to_top( handle child )
[267]215{
[269]216        element* e      = get_element( child );
217        element* parent = get_element( e->m_parent );
218        if ( e && parent )
[267]219        {
[268]220                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
[267]221                if ( it != parent->m_children.end() )
222                {
223                        parent->m_children.erase( it );
224                        parent->m_children.push_back( child );
225                        parent->m_dirty = true;
226                }       
227        }
228}
229
[269]230void nv::gui::environment::move_to_bottom( handle child )
[267]231{
[269]232        element* e      = get_element( child );
233        element* parent = get_element( e->m_parent );
234        if ( e && parent )
[267]235        {
[268]236                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
[267]237                if ( it != parent->m_children.end() )
238                {
239                        parent->m_children.erase( it );
240                        parent->m_children.push_front( child );
241                        parent->m_dirty = true;
242                }
243        }
244}
245
[269]246void nv::gui::environment::set_relative( handle e, const rectangle& r )
[267]247{
[269]248        element* el = get_element(e);
249        if ( el )
250        {
251                el->m_dirty    = true;
252                el->m_relative = r;
253                recalculate_absolute( e );
254        }
[267]255}
256
[269]257void nv::gui::environment::set_relative( handle e, const position& p )
[267]258{
[269]259        element* el = get_element(e);
260        if ( el )
261        {
262                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
263        }
[267]264}
265
[269]266void nv::gui::environment::recalculate_absolute( handle e )
[267]267{
[269]268        element* el = get_element(e);
269        rectangle pabsolute = get_element( el->m_parent )->m_absolute;
270        el->m_absolute = el->m_relative + pabsolute.ul;
[267]271
[269]272        for ( handle o : el->m_children )
[267]273        {
[268]274                recalculate_absolute( o );
[267]275        }
276}
277
[269]278void nv::gui::environment::set_class( handle e, const string& text )
[268]279{
[269]280        element* ep = get_element(e);
281        if ( ep != nullptr )
282        {
283                ep->m_class = text;
284                ep->m_dirty = true;
285        }
[268]286}
287
[269]288void nv::gui::environment::set_text( handle e, const string& text )
[268]289{
[269]290        element* ep = get_element(e);
291        if ( ep != nullptr )
292        {
293                ep->m_text = text;
294                ep->m_dirty = true;
295        }
[268]296}
297
[269]298void nv::gui::environment::remove_child( handle parent, handle child )
[268]299{
[269]300        element* p = get_element( parent );
301        if ( p )
[268]302        {
[269]303                auto it = std::find( p->m_children.begin(), p->m_children.end(), child );
304                if ( it != p->m_children.end() )
305                {
306                        element* e = get_element( *it );
307                        e->m_parent = handle();
308                        p->m_children.erase(it);
309                }       
[268]310        }
311}
312
Note: See TracBrowser for help on using the repository browser.