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
Line 
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
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
24#include "nv/gfx/sliced_buffer.hh"
25#include "nv/gfx/texture_atlas.hh"
26
27nv::gui::environment::environment( window* w, const std::string& shader_path )
28        : m_renderer( nullptr ), m_window( w )
29{
30        m_area.dim( dimension( w->get_width(), w->get_height() ) );
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
37        m_renderer = new renderer( w, shader_path );
38}
39
40void nv::gui::environment::load_style( const std::string& filename )
41{
42        m_renderer->load_style( filename );
43}
44
45nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
46{
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;
57        add_child( parent, result );
58        return result;
59}
60
61nv::gui::handle nv::gui::environment::create_handle()
62{
63        m_elements.emplace_back();
64        m_elements.back().m_this = m_indexes.create_handle( sint32( m_elements.size() - 1 ) );
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;
72        destroy_children( e );
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
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 )
82        {
83                m_elements[ dead_eindex ] = m_elements.back();
84        }
85        m_elements.pop_back();
86        m_indexes.swap_indices( e, swap_handle );
87        m_indexes.free_handle( e );
88}
89
90void nv::gui::environment::update( handle e, uint32 elapsed )
91{
92        element* el = get_element( e );
93        if ( !el ) return;
94        //      el->on_update( elapsed );
95        if ( el->m_visible )
96        {
97                for ( handle i : el->m_children )
98                {
99                        update( i, elapsed );
100                }
101        }
102        if ( el->m_dirty || el->m_render_data == nullptr )
103        {
104                m_renderer->redraw( el, elapsed );
105                el->m_dirty = false;
106        }
107}
108
109void nv::gui::environment::draw( handle e )
110{
111        element* el = get_element( e );
112        if ( !el ) return;
113        if ( el->m_visible )
114        {
115//              el->on_draw();
116                m_renderer->draw( el );
117                for ( handle i : el->m_children )
118                {
119                        draw(i);
120                }
121        }
122}
123
124void nv::gui::environment::update()
125{
126        update( m_screen, 0 );
127}
128
129void nv::gui::environment::draw()
130{
131        draw( m_screen );
132        m_renderer->draw();
133}
134
135void nv::gui::environment::add_child( handle child )
136{
137        add_child( m_screen, child );
138}
139
140void nv::gui::environment::add_child( handle parent, handle child )
141{
142        element* e = get_element( child );
143        element* p = get_element( parent );
144        if ( e && p )
145        {
146                remove_child( e->m_parent, child );
147                e->m_parent = parent;
148                p->m_children.push_back( child );
149                p->m_child_count++;
150        }
151}
152
153void nv::gui::environment::destroy_children( handle e )
154{
155        element* parent = get_element(e);
156        if ( parent )
157        {
158                while ( !parent->m_children.empty() )
159                {
160                        destroy_element( parent->m_children.front() );
161                }
162        }
163}
164
165
166nv::gui::environment::~environment()
167{
168        destroy_children( handle() );
169        delete m_renderer;
170}
171
172bool nv::gui::environment::process_io_event( const io_event& )
173{
174        return false;
175}
176
177bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
178{
179        element* el = get_element( e );
180        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
181}
182
183nv::gui::handle nv::gui::environment::get_element( const position& p )
184{
185        return get_deepest_child( m_screen, p );
186}
187
188nv::gui::element* nv::gui::environment::get_element( handle h )
189{
190        if ( h.is_nil() ) return nullptr;
191        sint32 eindex = m_indexes.get_index( h );
192        return eindex >= 0 ? &m_elements[ eindex ] : nullptr;
193}
194
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();
199
200        handle result;
201        element::list::reverse_iterator it = el->m_children.rbegin();
202
203        while ( it != el->m_children.rend() )
204        {
205                result = get_deepest_child( *it, p );
206                if ( result.is_valid() ) return result;
207                ++it;
208        }
209
210        if ( el->m_absolute.contains(p) ) return e;
211        return handle();
212}
213
214void nv::gui::environment::move_to_top( handle child )
215{
216        element* e      = get_element( child );
217        element* parent = get_element( e->m_parent );
218        if ( e && parent )
219        {
220                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
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
230void nv::gui::environment::move_to_bottom( handle child )
231{
232        element* e      = get_element( child );
233        element* parent = get_element( e->m_parent );
234        if ( e && parent )
235        {
236                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
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
246void nv::gui::environment::set_relative( handle e, const rectangle& r )
247{
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        }
255}
256
257void nv::gui::environment::set_relative( handle e, const position& p )
258{
259        element* el = get_element(e);
260        if ( el )
261        {
262                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
263        }
264}
265
266void nv::gui::environment::recalculate_absolute( handle e )
267{
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;
271
272        for ( handle o : el->m_children )
273        {
274                recalculate_absolute( o );
275        }
276}
277
278void nv::gui::environment::set_class( handle e, const string& text )
279{
280        element* ep = get_element(e);
281        if ( ep != nullptr )
282        {
283                ep->m_class = text;
284                ep->m_dirty = true;
285        }
286}
287
288void nv::gui::environment::set_text( handle e, const string& text )
289{
290        element* ep = get_element(e);
291        if ( ep != nullptr )
292        {
293                ep->m_text = text;
294                ep->m_dirty = true;
295        }
296}
297
298void nv::gui::environment::remove_child( handle parent, handle child )
299{
300        element* p = get_element( parent );
301        if ( p )
302        {
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                }       
310        }
311}
312
Note: See TracBrowser for help on using the repository browser.