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

Last change on this file since 401 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
RevLine 
[395]1// Copyright (C) 2012-2015 ChaosForge Ltd
[69]2// http://chaosforge.org/
3//
[395]4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
[69]6
7#include "nv/gui/gui_environment.hh"
8
[126]9#include "nv/gui/gui_renderer.hh"
10
[401]11#include <algorithm> // std::find on std::list
[126]12
13        /*
14
15        TODO: parse a lua stylesheet as per Trac wiki
16
[392]17        IDEA: Store everything in unordered_maps, with lua_value's?
[126]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
[354]26nv::gui::environment::environment( renderer* r )
27        : m_renderer( r )
[126]28{
[354]29        m_screen   = create_element( handle(), m_renderer->get_area() );
[126]30}
31
32void nv::gui::environment::load_style( const std::string& filename )
33{
34        m_renderer->load_style( filename );
35}
36
[269]37nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
[257]38{
[269]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;
[351]45
[354]46        handle result  = m_elements.create();
47        element* e     = m_elements.get( result );
48        rectangle ar   = r;
49        rectangle full = m_renderer->get_area();
[344]50
[354]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; }
[344]53
[351]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;
[344]59        e->m_absolute = ar;
60        e->m_relative = ar;
[351]61
62        if ( !parent.is_nil() ) // screen creation
63                add_child( parent, result );
[257]64        return result;
65}
66
[269]67void nv::gui::environment::destroy_element( handle e )
68{
[271]69        element* dead_element = m_elements.get( e );
[269]70        if ( dead_element == nullptr ) return;
[264]71        destroy_children( e );
[269]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
[271]78        m_elements.destroy( e );
[264]79}
80
[269]81void nv::gui::environment::update( handle e, uint32 elapsed )
[126]82{
[271]83        element* el = m_elements.get( e );
[269]84        if ( !el ) return;
85        //      el->on_update( elapsed );
[351]86        if ( el->m_flags[ENABLED] )
[257]87        {
[351]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;
[356]93                        // gain lose hover event
[351]94                        m_renderer->on_hover_change( el, hover );
95                }
96        }
97
98        if ( el->m_flags[VISIBLE] )
99        {
[269]100                for ( handle i : el->m_children )
[257]101                {
[268]102                        update( i, elapsed );
[257]103                }
104        }
[351]105        if ( el->m_flags[DIRTY] || el->m_render_data == nullptr )
[126]106        {
[269]107                m_renderer->redraw( el, elapsed );
[351]108                el->m_flags[DIRTY] = false;
[126]109        }
110}
111
[269]112void nv::gui::environment::draw( handle e )
[69]113{
[271]114        element* el = m_elements.get( e );
[269]115        if ( !el ) return;
[351]116        if ( el->m_flags[VISIBLE] )
[257]117        {
[269]118//              el->on_draw();
119                m_renderer->draw( el );
120                for ( handle i : el->m_children )
[257]121                {
[268]122                        draw(i);
[257]123                }
124        }
[69]125}
[126]126
[267]127void nv::gui::environment::update()
[126]128{
[257]129        update( m_screen, 0 );
[126]130}
131
[267]132void nv::gui::environment::draw()
[126]133{
[257]134        draw( m_screen );
[126]135        m_renderer->draw();
136}
137
[269]138void nv::gui::environment::add_child( handle child )
[126]139{
[268]140        add_child( m_screen, child );
[126]141}
142
[269]143void nv::gui::environment::add_child( handle parent, handle child )
[268]144{
[271]145        element* e = m_elements.get( child );
146        element* p = m_elements.get( parent );
[269]147        if ( e && p )
[268]148        {
[269]149                remove_child( e->m_parent, child );
150                e->m_parent = parent;
151                p->m_children.push_back( child );
152                p->m_child_count++;
[268]153        }
154}
155
[269]156void nv::gui::environment::destroy_children( handle e )
[264]157{
[271]158        element* parent = m_elements.get(e);
[269]159        if ( parent )
[264]160        {
[269]161                while ( !parent->m_children.empty() )
162                {
163                        destroy_element( parent->m_children.front() );
164                }
[264]165        }
166}
167
168
[267]169nv::gui::environment::~environment()
[126]170{
[269]171        destroy_children( handle() );
[126]172        delete m_renderer;
173}
174
[351]175bool nv::gui::environment::process_io_event( const io_event& ev )
[267]176{
[351]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        }
[267]195        return false;
196}
197
[351]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
[269]220bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
[267]221{
[271]222        element* el = m_elements.get( e );
[270]223        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
[267]224}
225
[269]226nv::gui::handle nv::gui::environment::get_element( const position& p )
[267]227{
228        return get_deepest_child( m_screen, p );
229}
230
[269]231nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
232{
[271]233        element* el = m_elements.get(e);
[351]234        if ( !el && !el->m_flags[VISIBLE] ) return handle();
[267]235
[269]236        handle result;
237        element::list::reverse_iterator it = el->m_children.rbegin();
238
239        while ( it != el->m_children.rend() )
[267]240        {
[268]241                result = get_deepest_child( *it, p );
[270]242                if ( result.is_valid() ) return result;
[267]243                ++it;
244        }
245
[269]246        if ( el->m_absolute.contains(p) ) return e;
247        return handle();
[267]248}
249
[269]250void nv::gui::environment::move_to_top( handle child )
[267]251{
[271]252        element* e      = m_elements.get( child );
253        element* parent = m_elements.get( e->m_parent );
[269]254        if ( e && parent )
[267]255        {
[268]256                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
[267]257                if ( it != parent->m_children.end() )
258                {
259                        parent->m_children.erase( it );
260                        parent->m_children.push_back( child );
[351]261                        parent->m_flags[DIRTY] = true;
[267]262                }       
263        }
264}
265
[269]266void nv::gui::environment::move_to_bottom( handle child )
[267]267{
[271]268        element* e      = m_elements.get( child );
269        element* parent = m_elements.get( e->m_parent );
[269]270        if ( e && parent )
[267]271        {
[268]272                auto it = std::find( parent->m_children.begin(), parent->m_children.end(), child );
[267]273                if ( it != parent->m_children.end() )
274                {
275                        parent->m_children.erase( it );
276                        parent->m_children.push_front( child );
[351]277                        parent->m_flags[DIRTY] = true;
[267]278                }
279        }
280}
281
[269]282void nv::gui::environment::set_relative( handle e, const rectangle& r )
[267]283{
[271]284        element* el = m_elements.get(e);
[269]285        if ( el )
286        {
[351]287                el->m_flags[DIRTY] = true;
288                el->m_relative     = r;
[269]289                recalculate_absolute( e );
290        }
[267]291}
292
[269]293void nv::gui::environment::set_relative( handle e, const position& p )
[267]294{
[271]295        element* el = m_elements.get(e);
[269]296        if ( el )
297        {
298                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
299        }
[267]300}
301
[269]302void nv::gui::environment::recalculate_absolute( handle e )
[267]303{
[271]304        element* el = m_elements.get(e);
305        rectangle pabsolute = m_elements.get( el->m_parent )->m_absolute;
[269]306        el->m_absolute = el->m_relative + pabsolute.ul;
[267]307
[269]308        for ( handle o : el->m_children )
[267]309        {
[268]310                recalculate_absolute( o );
[267]311        }
312}
313
[380]314void nv::gui::environment::set_class( handle e, const std::string& text )
[268]315{
[271]316        element* ep = m_elements.get(e);
[269]317        if ( ep != nullptr )
318        {
[351]319                ep->m_class        = text;
320                ep->m_flags[DIRTY] = true;
[269]321        }
[268]322}
323
[380]324void nv::gui::environment::set_text( handle e, const std::string& text )
[268]325{
[271]326        element* ep = m_elements.get(e);
[269]327        if ( ep != nullptr )
328        {
[351]329                ep->m_text         = text;
330                ep->m_flags[DIRTY] = true;
[269]331        }
[268]332}
333
[269]334void nv::gui::environment::remove_child( handle parent, handle child )
[268]335{
[271]336        element* p = m_elements.get( parent );
[269]337        if ( p )
[268]338        {
[269]339                auto it = std::find( p->m_children.begin(), p->m_children.end(), child );
340                if ( it != p->m_children.end() )
341                {
[271]342                        element* e = m_elements.get( *it );
[269]343                        e->m_parent = handle();
344                        p->m_children.erase(it);
345                }       
[268]346        }
347}
348
Note: See TracBrowser for help on using the repository browser.