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

Last change on this file since 350 was 344, checked in by epyon, 11 years ago
  • negative coordinate in element creation is an offset from screen size
File size: 6.8 KB
Line 
1// Copyright (C) 2012-2014 ChaosForge Ltd
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 )
28        : m_renderer( nullptr ), m_window( w )
29{
30        m_area.dim( dimension( w->get_width(), w->get_height() ) );
31       
32        m_screen           = m_elements.create();
33        element* screen    = m_elements.get( m_screen );
34        screen->m_absolute = m_area;
35        screen->m_relative = m_area;
36
37        m_renderer = new renderer( w );
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 = m_elements.create();
54        element* e    = m_elements.get( result );
55        rectangle ar  = r;
56
57        if ( ar.ul.x < 0 ) { ar.ul.x += m_area.lr.x; ar.lr.x += m_area.lr.x; }
58        if ( ar.ul.y < 0 ) { ar.ul.y += m_area.lr.y; ar.lr.y += m_area.lr.y; }
59
60        e->m_absolute = ar;
61        e->m_relative = ar;
62        add_child( parent, result );
63        return result;
64}
65
66void nv::gui::environment::destroy_element( handle e )
67{
68        element* dead_element = m_elements.get( e );
69        if ( dead_element == nullptr ) return;
70        destroy_children( e );
71        remove_child( dead_element->m_parent, e );
72
73        delete dead_element->m_render_data;
74        dead_element->m_render_data = nullptr;
75        dead_element->m_parent = handle();
76
77        m_elements.destroy( e );
78}
79
80void nv::gui::environment::update( handle e, uint32 elapsed )
81{
82        element* el = m_elements.get( e );
83        if ( !el ) return;
84        //      el->on_update( elapsed );
85        if ( el->m_visible )
86        {
87                for ( handle i : el->m_children )
88                {
89                        update( i, elapsed );
90                }
91        }
92        if ( el->m_dirty || el->m_render_data == nullptr )
93        {
94                m_renderer->redraw( el, elapsed );
95                el->m_dirty = false;
96        }
97}
98
99void nv::gui::environment::draw( handle e )
100{
101        element* el = m_elements.get( e );
102        if ( !el ) return;
103        if ( el->m_visible )
104        {
105//              el->on_draw();
106                m_renderer->draw( el );
107                for ( handle i : el->m_children )
108                {
109                        draw(i);
110                }
111        }
112}
113
114void nv::gui::environment::update()
115{
116        update( m_screen, 0 );
117}
118
119void nv::gui::environment::draw()
120{
121        draw( m_screen );
122        m_renderer->draw();
123}
124
125void nv::gui::environment::add_child( handle child )
126{
127        add_child( m_screen, child );
128}
129
130void nv::gui::environment::add_child( handle parent, handle child )
131{
132        element* e = m_elements.get( child );
133        element* p = m_elements.get( parent );
134        if ( e && p )
135        {
136                remove_child( e->m_parent, child );
137                e->m_parent = parent;
138                p->m_children.push_back( child );
139                p->m_child_count++;
140        }
141}
142
143void nv::gui::environment::destroy_children( handle e )
144{
145        element* parent = m_elements.get(e);
146        if ( parent )
147        {
148                while ( !parent->m_children.empty() )
149                {
150                        destroy_element( parent->m_children.front() );
151                }
152        }
153}
154
155
156nv::gui::environment::~environment()
157{
158        destroy_children( handle() );
159        delete m_renderer;
160}
161
162bool nv::gui::environment::process_io_event( const io_event& )
163{
164        return false;
165}
166
167bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
168{
169        element* el = m_elements.get( e );
170        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
171}
172
173nv::gui::handle nv::gui::environment::get_element( const position& p )
174{
175        return get_deepest_child( m_screen, p );
176}
177
178nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
179{
180        element* el = m_elements.get(e);
181        if ( !el && !el->m_visible ) return handle();
182
183        handle result;
184        element::list::reverse_iterator it = el->m_children.rbegin();
185
186        while ( it != el->m_children.rend() )
187        {
188                result = get_deepest_child( *it, p );
189                if ( result.is_valid() ) return result;
190                ++it;
191        }
192
193        if ( el->m_absolute.contains(p) ) return e;
194        return handle();
195}
196
197void nv::gui::environment::move_to_top( handle child )
198{
199        element* e      = m_elements.get( child );
200        element* parent = m_elements.get( e->m_parent );
201        if ( e && parent )
202        {
203                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
204                if ( it != parent->m_children.end() )
205                {
206                        parent->m_children.erase( it );
207                        parent->m_children.push_back( child );
208                        parent->m_dirty = true;
209                }       
210        }
211}
212
213void nv::gui::environment::move_to_bottom( handle child )
214{
215        element* e      = m_elements.get( child );
216        element* parent = m_elements.get( e->m_parent );
217        if ( e && parent )
218        {
219                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
220                if ( it != parent->m_children.end() )
221                {
222                        parent->m_children.erase( it );
223                        parent->m_children.push_front( child );
224                        parent->m_dirty = true;
225                }
226        }
227}
228
229void nv::gui::environment::set_relative( handle e, const rectangle& r )
230{
231        element* el = m_elements.get(e);
232        if ( el )
233        {
234                el->m_dirty    = true;
235                el->m_relative = r;
236                recalculate_absolute( e );
237        }
238}
239
240void nv::gui::environment::set_relative( handle e, const position& p )
241{
242        element* el = m_elements.get(e);
243        if ( el )
244        {
245                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
246        }
247}
248
249void nv::gui::environment::recalculate_absolute( handle e )
250{
251        element* el = m_elements.get(e);
252        rectangle pabsolute = m_elements.get( el->m_parent )->m_absolute;
253        el->m_absolute = el->m_relative + pabsolute.ul;
254
255        for ( handle o : el->m_children )
256        {
257                recalculate_absolute( o );
258        }
259}
260
261void nv::gui::environment::set_class( handle e, const string& text )
262{
263        element* ep = m_elements.get(e);
264        if ( ep != nullptr )
265        {
266                ep->m_class = text;
267                ep->m_dirty = true;
268        }
269}
270
271void nv::gui::environment::set_text( handle e, const string& text )
272{
273        element* ep = m_elements.get(e);
274        if ( ep != nullptr )
275        {
276                ep->m_text = text;
277                ep->m_dirty = true;
278        }
279}
280
281void nv::gui::environment::remove_child( handle parent, handle child )
282{
283        element* p = m_elements.get( parent );
284        if ( p )
285        {
286                auto it = std::find( p->m_children.begin(), p->m_children.end(), child );
287                if ( it != p->m_children.end() )
288                {
289                        element* e = m_elements.get( *it );
290                        e->m_parent = handle();
291                        p->m_children.erase(it);
292                }       
293        }
294}
295
Note: See TracBrowser for help on using the repository browser.