Foundation classes for a basic GUI implementing simple widgets and events

Dependents:   TouchScreenGUIDemo

Revision:
12:63db16fea709
Child:
13:6714534e7974
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Widgets/Widget.cpp	Sun May 08 14:42:08 2016 +0000
@@ -0,0 +1,260 @@
+#include "Widget.h"
+#include <algorithm>
+Widget::Widget(GraphicsContext* context) 
+:   _context(context), 
+    _fg(White), _bg(Black), 
+    _inner(0,0,0,0), _outer(0,0,0,0),
+    _hidden(false), 
+    _padding(0), _borderWidth(1), _borderColour(White),
+    _adjusting(false), 
+    _dirtied(true), _dirtying(false), 
+    _damaged(true), _damaging(false)
+{
+}
+
+void Widget::setParent(Widget* parent) {
+    _parent = parent;
+}
+
+bool Widget::isEventTarget(Event e)
+{
+    return !_hidden 
+        && e.screenX >= _outer.x 
+        && e.screenX <= (_outer.x+_outer.width) 
+        && e.screenY >= _outer.y 
+        && e.screenY <= (_outer.y+_outer.height);
+}
+
+void Widget::setLocation(int x, int y)
+{
+    if(_outer.x != x || _outer.y != y) {
+        _outer.x = x;
+        _outer.y = y;
+        damage();
+        adjust();
+    }
+}
+
+void Widget::setSize(int width, int height)
+{
+    if(_outer.width != width || _outer.height != height) {
+        _outer.width = width;
+        _outer.height = height;
+        damage();
+        adjust();
+    }
+}
+
+void Widget::setWidth(int width) {
+    if(_outer.width != width) {
+        _outer.width = width;
+        damage();
+        adjust();
+    }
+}
+
+void Widget::setHeight(int height) {
+    if(_outer.height != height) {
+        _outer.height = height;
+        damage();
+        adjust();
+    }
+}
+
+int Widget::x()
+{
+    return _outer.x;
+}
+
+int Widget::y()
+{
+    return _outer.y;
+}
+
+int Widget::height()
+{
+    return _outer.height;
+}
+
+int Widget::width()
+{
+    return _outer.width;
+}
+
+const Rectangle &Widget::outer() {
+    return _outer;
+}
+
+const Rectangle &Widget::inner() {
+    return _inner;
+}
+
+void Widget::setForeground(uint16_t color)
+{
+    if(_fg != color) {
+        _fg = color;
+        dirty();
+    }
+}
+
+void Widget::setBackground(uint16_t color)
+{
+    if(_bg != color) {
+        _bg = color;
+        dirty();
+    }
+}
+
+
+/**
+* Set the amount of padding between the border and a widget edge
+**/
+void Widget::setPadding(int pixels)
+{
+    if(_padding != pixels) {
+        _padding = pixels;
+        dirty();
+    }
+}
+
+void Widget::setBorder(int width, uint16_t colour)
+{
+    if(_borderWidth != width || _borderColour != colour) {
+        _borderColour = colour;
+        _borderWidth = width;
+        dirty();
+    }
+}
+
+void Widget::draw()
+{
+    if(!_hidden && (_dirtied | _damaged)) {
+        _draw();
+        _dirtied = false;
+        _damaged = false;
+    }
+}
+
+void Widget::clear()
+{
+    if(!_hidden) _clear();
+}
+
+void Widget::show()
+{
+    _hidden = false;
+    draw();
+}
+
+void Widget::hide()
+{
+    clear();
+    _hidden = true;
+}
+
+bool Widget::isHidden()
+{
+    return _hidden;
+}
+
+void Widget::setEventHandler(EventHandler* handler)
+{
+    EventListener::setEventHandler(handler);
+    _context->eventDispatcher()->detachListener(this);
+    _context->eventDispatcher()->attachListener(this);
+}
+
+void Widget::unsetEventHandler(EventHandler *handler)
+{
+    EventListener::unsetEventHandler(handler);
+}
+
+bool Widget::intersects(Widget *w)
+{
+    return _outer.intersects(w->outer());
+}
+
+void Widget::dirty()
+{
+    if(!_dirtying) {
+        _dirtying = true;
+        _dirty();
+        _dirtying = false;
+    }
+}
+
+bool Widget::isDirty() {
+    return _dirtied;
+}
+
+void Widget::dirtyAll()
+{
+    _dirtied = true;
+}
+
+void Widget::damage() {
+    if(!_damaging) {
+        _damaging = true;
+        _damage();
+        _damaging = false;
+    }
+}
+
+bool Widget::isDamaged() {
+    return _damaged;
+}
+
+void Widget::adjust()
+{
+    if(!_adjusting) {
+        _adjusting = true;
+        _adjust();
+        _adjusting = false;
+    }
+}
+
+GraphicsDisplay* Widget::display()
+{
+    return _context->display();
+}
+
+/**********************************************************
+* Protected methods
+**********************************************************/
+void Widget::_draw() {
+    GraphicsDisplay *d = display();
+    // Draw the border
+    // Top
+    d->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_borderWidth, _borderColour);
+    // Bottom
+    d->fillrect(_outer.x, _outer.y + _outer.height - _borderWidth, _outer.x + _outer.width, _outer.y+_outer.height, _borderColour);
+    // Left
+    d->fillrect(_outer.x, _outer.y, _outer.x+_borderWidth, _outer.y+_outer.height, _borderColour);
+    // Right
+    d->fillrect(_outer.x+_outer.width-_borderWidth, _outer.y, _outer.x+_outer.width, _outer.y+_outer.height, _borderColour);
+}
+
+void Widget::_clear() {
+    display()->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_outer.height, display()->getBackground());
+}
+
+void Widget::_dirty()
+{
+    _dirtied = true;
+    if(_parent != NULL) {
+        _parent->dirty();
+    }
+}
+
+void Widget::_damage()
+{
+    _damaged = true;
+    if(_parent != NULL) {
+        _parent->dirty();
+    }
+}
+
+void Widget::_adjust() {
+    // Recalculate size of inner Rect
+    _inner.resize(_outer, _borderWidth + _padding);
+}