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

Last change on this file since 428 was 401, checked in by epyon, 10 years ago
  • clang/gcc fixes
  • removed aligned array, usage of alignas should work now
File size: 8.0 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#include <algorithm> // std::find on std::list
12
13        /*
14
15        TODO: parse a lua stylesheet as per Trac wiki
16
17        IDEA: Store everything in unordered_maps, with lua_value's?
18
19        A lua_value is a variant stores strings as const char* that deletes them on destructor?
20        Question is that there might not be much gained on speed anyway, due to Lua's speed.
21        Special function field allows delayed per parse execution?
22
23        */
24
25
26nv::gui::environment::environment( renderer* r )
27        : m_renderer( r )
28{
29        m_screen   = create_element( handle(), m_renderer->get_area() );
30}
31
32void nv::gui::environment::load_style( const std::string& filename )
33{
34        m_renderer->load_style( filename );
35}
36
37nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
38{
39        return create_element( m_screen, r );
40}
41
42nv::gui::handle nv::gui::environment::create_element( handle parent, const rectangle& r )
43{
44        if ( parent.is_nil() ) parent = m_screen;
45
46        handle result  = m_elements.create();
47        element* e     = m_elements.get( result );
48        rectangle ar   = r;
49        rectangle full = m_renderer->get_area();
50
51        if ( ar.ul.x < 0 ) { ar.ul.x += full.lr.x; ar.lr.x += full.lr.x; }
52        if ( ar.ul.y < 0 ) { ar.ul.y += full.lr.y; ar.lr.y += full.lr.y; }
53
54        e->m_child_count = 0;
55        e->m_flags[ENABLED] = true;
56        e->m_flags[VISIBLE] = true;
57        e->m_flags[DIRTY]   = true;
58        e->m_render_data    = nullptr;
59        e->m_absolute = ar;
60        e->m_relative = ar;
61
62        if ( !parent.is_nil() ) // screen creation
63                add_child( parent, result );
64        return result;
65}
66
67void nv::gui::environment::destroy_element( handle e )
68{
69        element* dead_element = m_elements.get( e );
70        if ( dead_element == nullptr ) return;
71        destroy_children( e );
72        remove_child( dead_element->m_parent, e );
73
74        delete dead_element->m_render_data;
75        dead_element->m_render_data = nullptr;
76        dead_element->m_parent = handle();
77
78        m_elements.destroy( e );
79}
80
81void nv::gui::environment::update( handle e, uint32 elapsed )
82{
83        element* el = m_elements.get( e );
84        if ( !el ) return;
85        //      el->on_update( elapsed );
86        if ( el->m_flags[ENABLED] )
87        {
88                bool hover     = el->m_flags[HOVER];
89                bool new_hover = el->m_absolute.contains( m_mouse_position );
90                if ( hover != new_hover )
91                {
92                        el->m_flags[HOVER] = new_hover;
93                        // gain lose hover event
94                        m_renderer->on_hover_change( el, hover );
95                }
96        }
97
98        if ( el->m_flags[VISIBLE] )
99        {
100                for ( handle i : el->m_children )
101                {
102                        update( i, elapsed );
103                }
104        }
105        if ( el->m_flags[DIRTY] || el->m_render_data == nullptr )
106        {
107                m_renderer->redraw( el, elapsed );
108                el->m_flags[DIRTY] = false;
109        }
110}
111
112void nv::gui::environment::draw( handle e )
113{
114        element* el = m_elements.get( e );
115        if ( !el ) return;
116        if ( el->m_flags[VISIBLE] )
117        {
118//              el->on_draw();
119                m_renderer->draw( el );
120                for ( handle i : el->m_children )
121                {
122                        draw(i);
123                }
124        }
125}
126
127void nv::gui::environment::update()
128{
129        update( m_screen, 0 );
130}
131
132void nv::gui::environment::draw()
133{
134        draw( m_screen );
135        m_renderer->draw();
136}
137
138void nv::gui::environment::add_child( handle child )
139{
140        add_child( m_screen, child );
141}
142
143void nv::gui::environment::add_child( handle parent, handle child )
144{
145        element* e = m_elements.get( child );
146        element* p = m_elements.get( parent );
147        if ( e && p )
148        {
149                remove_child( e->m_parent, child );
150                e->m_parent = parent;
151                p->m_children.push_back( child );
152                p->m_child_count++;
153        }
154}
155
156void nv::gui::environment::destroy_children( handle e )
157{
158        element* parent = m_elements.get(e);
159        if ( parent )
160        {
161                while ( !parent->m_children.empty() )
162                {
163                        destroy_element( parent->m_children.front() );
164                }
165        }
166}
167
168
169nv::gui::environment::~environment()
170{
171        destroy_children( handle() );
172        delete m_renderer;
173}
174
175bool nv::gui::environment::process_io_event( const io_event& ev )
176{
177        switch ( ev.type )
178        {
179//      case EV_KEY          :
180        case EV_MOUSE_BUTTON :
181                if ( ev.mbutton.pressed && ev.mbutton.button == MOUSE_LEFT )
182                {
183                        handle h = get_element( position( ev.mbutton.x, ev.mbutton.y ) );
184                        set_selected( h );
185                        return true;
186                }
187                return false;
188        case EV_MOUSE_MOVE:
189                m_mouse_position = position( ev.mmove.x, ev.mmove.y );
190                return false;
191//      case EV_MOUSE_WHEEL  :
192        default:
193                break;
194        }
195        return false;
196}
197
198bool nv::gui::environment::set_selected( handle e )
199{
200        if ( e != m_selected )
201        {
202                element* eold = m_elements.get( m_selected );
203                element* el   = m_elements.get( e );
204                if ( eold )
205                {
206                        eold->m_flags[SELECTED] = false;
207                        m_renderer->on_select_change( eold, false );
208                }
209                if ( el )
210                {
211                        el->m_flags[SELECTED] = true;
212                        m_renderer->on_select_change( el, true );
213                }
214                m_selected = e;
215                return true;
216        }
217        return false;
218}
219
220bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
221{
222        element* el = m_elements.get( e );
223        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
224}
225
226nv::gui::handle nv::gui::environment::get_element( const position& p )
227{
228        return get_deepest_child( m_screen, p );
229}
230
231nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
232{
233        element* el = m_elements.get(e);
234        if ( !el && !el->m_flags[VISIBLE] ) return handle();
235
236        handle result;
237        element::list::reverse_iterator it = el->m_children.rbegin();
238
239        while ( it != el->m_children.rend() )
240        {
241                result = get_deepest_child( *it, p );
242                if ( result.is_valid() ) return result;
243                ++it;
244        }
245
246        if ( el->m_absolute.contains(p) ) return e;
247        return handle();
248}
249
250void nv::gui::environment::move_to_top( handle child )
251{
252        element* e      = m_elements.get( child );
253        element* parent = m_elements.get( e->m_parent );
254        if ( e && parent )
255        {
256                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
257                if ( it != parent->m_children.end() )
258                {
259                        parent->m_children.erase( it );
260                        parent->m_children.push_back( child );
261                        parent->m_flags[DIRTY] = true;
262                }       
263        }
264}
265
266void nv::gui::environment::move_to_bottom( handle child )
267{
268        element* e      = m_elements.get( child );
269        element* parent = m_elements.get( e->m_parent );
270        if ( e && parent )
271        {
272                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
273                if ( it != parent->m_children.end() )
274                {
275                        parent->m_children.erase( it );
276                        parent->m_children.push_front( child );
277                        parent->m_flags[DIRTY] = true;
278                }
279        }
280}
281
282void nv::gui::environment::set_relative( handle e, const rectangle& r )
283{
284        element* el = m_elements.get(e);
285        if ( el )
286        {
287                el->m_flags[DIRTY] = true;
288                el->m_relative     = r;
289                recalculate_absolute( e );
290        }
291}
292
293void nv::gui::environment::set_relative( handle e, const position& p )
294{
295        element* el = m_elements.get(e);
296        if ( el )
297        {
298                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
299        }
300}
301
302void nv::gui::environment::recalculate_absolute( handle e )
303{
304        element* el = m_elements.get(e);
305        rectangle pabsolute = m_elements.get( el->m_parent )->m_absolute;
306        el->m_absolute = el->m_relative + pabsolute.ul;
307
308        for ( handle o : el->m_children )
309        {
310                recalculate_absolute( o );
311        }
312}
313
314void nv::gui::environment::set_class( handle e, const std::string& text )
315{
316        element* ep = m_elements.get(e);
317        if ( ep != nullptr )
318        {
319                ep->m_class        = text;
320                ep->m_flags[DIRTY] = true;
321        }
322}
323
324void nv::gui::environment::set_text( handle e, const std::string& text )
325{
326        element* ep = m_elements.get(e);
327        if ( ep != nullptr )
328        {
329                ep->m_text         = text;
330                ep->m_flags[DIRTY] = true;
331        }
332}
333
334void nv::gui::environment::remove_child( handle parent, handle child )
335{
336        element* p = m_elements.get( parent );
337        if ( p )
338        {
339                auto it = std::find( p->m_children.begin(), p->m_children.end(), child );
340                if ( it != p->m_children.end() )
341                {
342                        element* e = m_elements.get( *it );
343                        e->m_parent = handle();
344                        p->m_children.erase(it);
345                }       
346        }
347}
348
Note: See TracBrowser for help on using the repository browser.