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

Last change on this file since 440 was 440, checked in by epyon, 10 years ago
  • massive std::string removal
  • no header depends on std::string anymore (or any other STL header)
  • still some code files do (WIP)
  • massive refactoring where std::string was used
  • lua still messy (grep for string128 - used everywhere)
  • string_twine added
File size: 7.6 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        TODO: parse a lua stylesheet as per Trac wiki
14
15        IDEA: Store everything in unordered_maps, with lua_value's?
16
17        A lua_value is a variant stores strings as const char* that deletes them on destructor?
18        Question is that there might not be much gained on speed anyway, due to Lua's speed.
19        Special function field allows delayed per parse execution?
20
21        */
22
23
24nv::gui::environment::environment( renderer* r )
25        : m_renderer( r )
26{
27        r->set_environment( this );
28        m_screen   = create_element( handle(), m_renderer->get_area() );
29}
30
31void nv::gui::environment::load_style( const string_view& 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.back() );
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
197nv::string_view nv::gui::environment::get_string( shash64 h )
198{
199        return m_strings[h];
200}
201
202bool nv::gui::environment::set_selected( handle e )
203{
204        if ( e != m_selected )
205        {
206                element* eold = m_elements.get( m_selected );
207                element* el   = m_elements.get( e );
208                if ( eold )
209                {
210                        eold->m_flags[SELECTED] = false;
211                        m_renderer->on_select_change( eold, false );
212                }
213                if ( el )
214                {
215                        el->m_flags[SELECTED] = true;
216                        m_renderer->on_select_change( el, true );
217                }
218                m_selected = e;
219                return true;
220        }
221        return false;
222}
223
224bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
225{
226        element* el = m_elements.get( e );
227        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
228}
229
230nv::gui::handle nv::gui::environment::get_element( const position& p )
231{
232        return get_deepest_child( m_screen, p );
233}
234
235nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
236{
237        element* el = m_elements.get(e);
238        if ( !el && !el->m_flags[VISIBLE] ) return handle();
239
240        handle result;
241        auto it = el->m_children.rbegin();
242
243        while ( it != el->m_children.rend() )
244        {
245                result = get_deepest_child( *it, p );
246                if ( result.is_valid() ) return result;
247                ++it;
248        }
249
250        if ( el->m_absolute.contains(p) ) return e;
251        return handle();
252}
253
254void nv::gui::environment::move_to_top( handle child )
255{
256        element* e      = m_elements.get( child );
257        element* parent = m_elements.get( e->m_parent );
258        if ( e && parent )
259        {
260                auto it = find( parent->m_children.begin(), parent->m_children.end(), child );
261                if ( it != parent->m_children.end() )
262                {
263                        parent->m_children.erase( it );
264                        parent->m_children.push_back( child );
265                        parent->m_flags[DIRTY] = true;
266                }       
267        }
268}
269
270void nv::gui::environment::set_relative( handle e, const rectangle& r )
271{
272        element* el = m_elements.get(e);
273        if ( el )
274        {
275                el->m_flags[DIRTY] = true;
276                el->m_relative     = r;
277                recalculate_absolute( e );
278        }
279}
280
281void nv::gui::environment::set_relative( handle e, const position& p )
282{
283        element* el = m_elements.get(e);
284        if ( el )
285        {
286                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
287        }
288}
289
290void nv::gui::environment::recalculate_absolute( handle e )
291{
292        element* el = m_elements.get(e);
293        rectangle pabsolute = m_elements.get( el->m_parent )->m_absolute;
294        el->m_absolute = el->m_relative + pabsolute.ul;
295
296        for ( handle o : el->m_children )
297        {
298                recalculate_absolute( o );
299        }
300}
301
302void nv::gui::environment::set_class( handle e, const string_view& text )
303{
304        element* ep = m_elements.get(e);
305        if ( ep != nullptr )
306        {
307                ep->m_class        = m_strings.insert( text );
308                ep->m_flags[DIRTY] = true;
309        }
310}
311
312void nv::gui::environment::set_text( handle e, const string_twine& text )
313{
314        element* ep = m_elements.get(e);
315        if ( ep != nullptr )
316        {
317                ep->m_text.assign( text );
318                ep->m_flags[DIRTY] = true;
319        }
320}
321
322void nv::gui::environment::remove_child( handle parent, handle child )
323{
324        element* p = m_elements.get( parent );
325        if ( p )
326        {
327                auto it = find( p->m_children.begin(), p->m_children.end(), child );
328                if ( it != p->m_children.end() )
329                {
330                        element* e = m_elements.get( *it );
331                        e->m_parent = handle();
332                        p->m_children.erase( it );
333                }
334        }
335}
336
Note: See TracBrowser for help on using the repository browser.