Foundation classes for a basic GUI implementing simple widgets and events
Dependents: TouchScreenGUIDemo
Diff: Widgets/Widget.cpp
- 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); +}