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

Last change on this file since 395 was 395, checked in by epyon, 10 years ago
  • bulk update copyright update include guards cleanup core/common.hh -> common.hh minor cleanups
File size: 7.9 KB
Line 
1// Copyright (C) 2012-2015 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
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 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
25nv::gui::environment::environment( renderer* r )
26        : m_renderer( r )
27{
28        m_screen   = create_element( handle(), m_renderer->get_area() );
29}
30
31void nv::gui::environment::load_style( const std::string& filename )
32{
33        m_renderer->load_style( filename );
34}
35
36nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
37{
38        return create_element( m_screen, r );
39}
40
41nv::gui::handle nv::gui::environment::create_element( handle parent, const rectangle& r )
42{
43        if ( parent.is_nil() ) parent = m_screen;
44
45        handle result  = m_elements.create();
46        element* e     = m_elements.get( result );
47        rectangle ar   = r;
48        rectangle full = m_renderer->get_area();
49
50        if ( ar.ul.x < 0 ) { ar.ul.x += full.lr.x; ar.lr.x += full.lr.x; }
51        if ( ar.ul.y < 0 ) { ar.ul.y += full.lr.y; ar.lr.y += full.lr.y; }
52
53        e->m_child_count = 0;
54        e->m_flags[ENABLED] = true;
55        e->m_flags[VISIBLE] = true;
56        e->m_flags[DIRTY]   = true;
57        e->m_render_data    = nullptr;
58        e->m_absolute = ar;
59        e->m_relative = ar;
60
61        if ( !parent.is_nil() ) // screen creation
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_flags[ENABLED] )
86        {
87                bool hover     = el->m_flags[HOVER];
88                bool new_hover = el->m_absolute.contains( m_mouse_position );
89                if ( hover != new_hover )
90                {
91                        el->m_flags[HOVER] = new_hover;
92                        // gain lose hover event
93                        m_renderer->on_hover_change( el, hover );
94                }
95        }
96
97        if ( el->m_flags[VISIBLE] )
98        {
99                for ( handle i : el->m_children )
100                {
101                        update( i, elapsed );
102                }
103        }
104        if ( el->m_flags[DIRTY] || el->m_render_data == nullptr )
105        {
106                m_renderer->redraw( el, elapsed );
107                el->m_flags[DIRTY] = false;
108        }
109}
110
111void nv::gui::environment::draw( handle e )
112{
113        element* el = m_elements.get( e );
114        if ( !el ) return;
115        if ( el->m_flags[VISIBLE] )
116        {
117//              el->on_draw();
118                m_renderer->draw( el );
119                for ( handle i : el->m_children )
120                {
121                        draw(i);
122                }
123        }
124}
125
126void nv::gui::environment::update()
127{
128        update( m_screen, 0 );
129}
130
131void nv::gui::environment::draw()
132{
133        draw( m_screen );
134        m_renderer->draw();
135}
136
137void nv::gui::environment::add_child( handle child )
138{
139        add_child( m_screen, child );
140}
141
142void nv::gui::environment::add_child( handle parent, handle child )
143{
144        element* e = m_elements.get( child );
145        element* p = m_elements.get( parent );
146        if ( e && p )
147        {
148                remove_child( e->m_parent, child );
149                e->m_parent = parent;
150                p->m_children.push_back( child );
151                p->m_child_count++;
152        }
153}
154
155void nv::gui::environment::destroy_children( handle e )
156{
157        element* parent = m_elements.get(e);
158        if ( parent )
159        {
160                while ( !parent->m_children.empty() )
161                {
162                        destroy_element( parent->m_children.front() );
163                }
164        }
165}
166
167
168nv::gui::environment::~environment()
169{
170        destroy_children( handle() );
171        delete m_renderer;
172}
173
174bool nv::gui::environment::process_io_event( const io_event& ev )
175{
176        switch ( ev.type )
177        {
178//      case EV_KEY          :
179        case EV_MOUSE_BUTTON :
180                if ( ev.mbutton.pressed && ev.mbutton.button == MOUSE_LEFT )
181                {
182                        handle h = get_element( position( ev.mbutton.x, ev.mbutton.y ) );
183                        set_selected( h );
184                        return true;
185                }
186                return false;
187        case EV_MOUSE_MOVE:
188                m_mouse_position = position( ev.mmove.x, ev.mmove.y );
189                return false;
190//      case EV_MOUSE_WHEEL  :
191        default:
192                break;
193        }
194        return false;
195}
196
197bool nv::gui::environment::set_selected( handle e )
198{
199        if ( e != m_selected )
200        {
201                element* eold = m_elements.get( m_selected );
202                element* el   = m_elements.get( e );
203                if ( eold )
204                {
205                        eold->m_flags[SELECTED] = false;
206                        m_renderer->on_select_change( eold, false );
207                }
208                if ( el )
209                {
210                        el->m_flags[SELECTED] = true;
211                        m_renderer->on_select_change( el, true );
212                }
213                m_selected = e;
214                return true;
215        }
216        return false;
217}
218
219bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
220{
221        element* el = m_elements.get( e );
222        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
223}
224
225nv::gui::handle nv::gui::environment::get_element( const position& p )
226{
227        return get_deepest_child( m_screen, p );
228}
229
230nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
231{
232        element* el = m_elements.get(e);
233        if ( !el && !el->m_flags[VISIBLE] ) return handle();
234
235        handle result;
236        element::list::reverse_iterator it = el->m_children.rbegin();
237
238        while ( it != el->m_children.rend() )
239        {
240                result = get_deepest_child( *it, p );
241                if ( result.is_valid() ) return result;
242                ++it;
243        }
244
245        if ( el->m_absolute.contains(p) ) return e;
246        return handle();
247}
248
249void nv::gui::environment::move_to_top( handle child )
250{
251        element* e      = m_elements.get( child );
252        element* parent = m_elements.get( e->m_parent );
253        if ( e && parent )
254        {
255                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
256                if ( it != parent->m_children.end() )
257                {
258                        parent->m_children.erase( it );
259                        parent->m_children.push_back( child );
260                        parent->m_flags[DIRTY] = true;
261                }       
262        }
263}
264
265void nv::gui::environment::move_to_bottom( handle child )
266{
267        element* e      = m_elements.get( child );
268        element* parent = m_elements.get( e->m_parent );
269        if ( e && parent )
270        {
271                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
272                if ( it != parent->m_children.end() )
273                {
274                        parent->m_children.erase( it );
275                        parent->m_children.push_front( child );
276                        parent->m_flags[DIRTY] = true;
277                }
278        }
279}
280
281void nv::gui::environment::set_relative( handle e, const rectangle& r )
282{
283        element* el = m_elements.get(e);
284        if ( el )
285        {
286                el->m_flags[DIRTY] = true;
287                el->m_relative     = r;
288                recalculate_absolute( e );
289        }
290}
291
292void nv::gui::environment::set_relative( handle e, const position& p )
293{
294        element* el = m_elements.get(e);
295        if ( el )
296        {
297                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
298        }
299}
300
301void nv::gui::environment::recalculate_absolute( handle e )
302{
303        element* el = m_elements.get(e);
304        rectangle pabsolute = m_elements.get( el->m_parent )->m_absolute;
305        el->m_absolute = el->m_relative + pabsolute.ul;
306
307        for ( handle o : el->m_children )
308        {
309                recalculate_absolute( o );
310        }
311}
312
313void nv::gui::environment::set_class( handle e, const std::string& text )
314{
315        element* ep = m_elements.get(e);
316        if ( ep != nullptr )
317        {
318                ep->m_class        = text;
319                ep->m_flags[DIRTY] = true;
320        }
321}
322
323void nv::gui::environment::set_text( handle e, const std::string& text )
324{
325        element* ep = m_elements.get(e);
326        if ( ep != nullptr )
327        {
328                ep->m_text         = text;
329                ep->m_flags[DIRTY] = true;
330        }
331}
332
333void nv::gui::environment::remove_child( handle parent, handle child )
334{
335        element* p = m_elements.get( parent );
336        if ( p )
337        {
338                auto it = std::find( p->m_children.begin(), p->m_children.end(), child );
339                if ( it != p->m_children.end() )
340                {
341                        element* e = m_elements.get( *it );
342                        e->m_parent = handle();
343                        p->m_children.erase(it);
344                }       
345        }
346}
347
Note: See TracBrowser for help on using the repository browser.