Foundation classes for a basic GUI implementing simple widgets and events

Dependents:   TouchScreenGUIDemo

Widgets/Window.cpp

Committer:
duncanFrance
Date:
2016-05-28
Revision:
18:d849f3ada858
Parent:
17:5184762fda6c

File content as of revision 18:d849f3ada858:

#include "Window.h"

Window::Window(GraphicsContext* context) : Widget(context), _childHandledEvents(0) 
{
    setSize(context->display()->width(), context->display()->height());
}

void Window::attach(Widget *widget)
{
    _widgets.append(widget);
    widget->setParent(this);
    _reenumerateEvents();
    widget->show();
    dirtyAll();
    damage();
}


void Window::detach(Widget *widget)
{
    widget->hide();
    _widgets.remove(widget);
    widget->setParent(NULL);
    _reenumerateEvents();
    dirty();
}

void Window::dirtyAll() {
    if(!_dirtying) {
        
        _dirtying = true;
        
        _dirty();
        
        Widget *w;
        _widgets.reset();
        
        while((w = _widgets.next()) != NULL) {
            w->dirtyAll();
        }
        
        _dirtying = false;
    }
}

void Window::_draw()
{
    Widget::_draw();
    
    Widget* w;

    // Draw only the damaged widgets first
    LinkedList<Widget> _damaged;
    
    _widgets.reset();
    while((w = _widgets.next()) != NULL) {
        if(w->isDamaged()) {
            _damaged.appendOnce(w);
            w->adjust();
            w->draw();
        }
    }
    
    _damaged.reset();
    while((w = _damaged.next()) != NULL) {
            _dirtyIntersected(w);
    }
    _damaged.clear();
    
    _widgets.reset();
    while((w = _widgets.next()) != NULL) {
        w->draw();
    }
}

void Window::_dirtyIntersected(Widget *w)
{
    Widget *o;
    LinkedListIterator<Widget> it = _widgets.getIterator();
    while((o = it.next()) != NULL) {
        if((o != w) && o->intersects(w)) {
            o->dirtyAll();
        }
    }
}

void Window::handleEvent(Event e) {
    Widget::handleEvent(e);
    // At this point we can do bubbling, cancelling etc. One day
    if(_childHandledEvents & e.type) {
        LinkedListIterator<Widget> it = _widgets.getIterator();
        Widget *w;
        while((w = it.next()) != NULL) {
            w->handleEvent(e);
        }
    }
}

void Window::_reenumerateHandledEvents() {
        
    Widget::_reenumerateHandledEvents();
    
    _childHandledEvents = 0;
    Widget *w;
    LinkedListIterator<Widget> wit = _widgets.getIterator();
    while((w = wit.next()) != NULL) {
        _childHandledEvents |= w->_getHandledEvents();
        w = _widgets.next();
    }
}

uint16_t Window::_getHandledEvents() {
    uint16_t m = Widget::_getHandledEvents();
    m |= _childHandledEvents;
    return m;
}