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

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