Foundation classes for a basic GUI implementing simple widgets and events

Dependents:   TouchScreenGUIDemo

Committer:
duncanFrance
Date:
Sat May 21 14:40:09 2016 +0000
Revision:
13:6714534e7974
Parent:
12:63db16fea709
Child:
15:e69fd74d42e4
Cleaned up SpinnerWidget; Started on SpinnerDialog - will extract Dialog later

Who changed what in which revision?

UserRevisionLine numberNew contents of line
duncanFrance 12:63db16fea709 1 #include "Widget.h"
duncanFrance 12:63db16fea709 2 #include <algorithm>
duncanFrance 12:63db16fea709 3 Widget::Widget(GraphicsContext* context)
duncanFrance 12:63db16fea709 4 : _context(context),
duncanFrance 12:63db16fea709 5 _fg(White), _bg(Black),
duncanFrance 13:6714534e7974 6 _offset(0,0), _inner(0,0,0,0), _outer(0,0,0,0),
duncanFrance 12:63db16fea709 7 _hidden(false),
duncanFrance 13:6714534e7974 8 _padding(0), _borderWidth(0), _borderColour(Black),
duncanFrance 12:63db16fea709 9 _adjusting(false),
duncanFrance 12:63db16fea709 10 _dirtied(true), _dirtying(false),
duncanFrance 12:63db16fea709 11 _damaged(true), _damaging(false)
duncanFrance 12:63db16fea709 12 {
duncanFrance 12:63db16fea709 13 }
duncanFrance 12:63db16fea709 14
duncanFrance 12:63db16fea709 15 void Widget::setParent(Widget* parent) {
duncanFrance 12:63db16fea709 16 _parent = parent;
duncanFrance 12:63db16fea709 17 }
duncanFrance 12:63db16fea709 18
duncanFrance 12:63db16fea709 19 bool Widget::isEventTarget(Event e)
duncanFrance 12:63db16fea709 20 {
duncanFrance 12:63db16fea709 21 return !_hidden
duncanFrance 12:63db16fea709 22 && e.screenX >= _outer.x
duncanFrance 12:63db16fea709 23 && e.screenX <= (_outer.x+_outer.width)
duncanFrance 12:63db16fea709 24 && e.screenY >= _outer.y
duncanFrance 12:63db16fea709 25 && e.screenY <= (_outer.y+_outer.height);
duncanFrance 12:63db16fea709 26 }
duncanFrance 13:6714534e7974 27 // Location is referred to the offset
duncanFrance 12:63db16fea709 28 void Widget::setLocation(int x, int y)
duncanFrance 12:63db16fea709 29 {
duncanFrance 13:6714534e7974 30 if( (_outer.x != (x+_offset.x())) || (_outer.y != y+_offset.y()) ) {
duncanFrance 13:6714534e7974 31 _outer.x = x + _offset.x();
duncanFrance 13:6714534e7974 32 _outer.y = y + _offset.y();
duncanFrance 12:63db16fea709 33 damage();
duncanFrance 12:63db16fea709 34 adjust();
duncanFrance 12:63db16fea709 35 }
duncanFrance 12:63db16fea709 36 }
duncanFrance 12:63db16fea709 37
duncanFrance 12:63db16fea709 38 void Widget::setSize(int width, int height)
duncanFrance 12:63db16fea709 39 {
duncanFrance 12:63db16fea709 40 if(_outer.width != width || _outer.height != height) {
duncanFrance 12:63db16fea709 41 _outer.width = width;
duncanFrance 12:63db16fea709 42 _outer.height = height;
duncanFrance 12:63db16fea709 43 damage();
duncanFrance 12:63db16fea709 44 adjust();
duncanFrance 12:63db16fea709 45 }
duncanFrance 12:63db16fea709 46 }
duncanFrance 12:63db16fea709 47
duncanFrance 12:63db16fea709 48 void Widget::setWidth(int width) {
duncanFrance 12:63db16fea709 49 if(_outer.width != width) {
duncanFrance 12:63db16fea709 50 _outer.width = width;
duncanFrance 12:63db16fea709 51 damage();
duncanFrance 12:63db16fea709 52 adjust();
duncanFrance 12:63db16fea709 53 }
duncanFrance 12:63db16fea709 54 }
duncanFrance 12:63db16fea709 55
duncanFrance 12:63db16fea709 56 void Widget::setHeight(int height) {
duncanFrance 12:63db16fea709 57 if(_outer.height != height) {
duncanFrance 12:63db16fea709 58 _outer.height = height;
duncanFrance 12:63db16fea709 59 damage();
duncanFrance 12:63db16fea709 60 adjust();
duncanFrance 12:63db16fea709 61 }
duncanFrance 12:63db16fea709 62 }
duncanFrance 12:63db16fea709 63
duncanFrance 12:63db16fea709 64 int Widget::x()
duncanFrance 12:63db16fea709 65 {
duncanFrance 12:63db16fea709 66 return _outer.x;
duncanFrance 12:63db16fea709 67 }
duncanFrance 12:63db16fea709 68
duncanFrance 12:63db16fea709 69 int Widget::y()
duncanFrance 12:63db16fea709 70 {
duncanFrance 12:63db16fea709 71 return _outer.y;
duncanFrance 12:63db16fea709 72 }
duncanFrance 12:63db16fea709 73
duncanFrance 12:63db16fea709 74 int Widget::height()
duncanFrance 12:63db16fea709 75 {
duncanFrance 12:63db16fea709 76 return _outer.height;
duncanFrance 12:63db16fea709 77 }
duncanFrance 12:63db16fea709 78
duncanFrance 12:63db16fea709 79 int Widget::width()
duncanFrance 12:63db16fea709 80 {
duncanFrance 12:63db16fea709 81 return _outer.width;
duncanFrance 12:63db16fea709 82 }
duncanFrance 13:6714534e7974 83 /**
duncanFrance 12:63db16fea709 84 const Rectangle &Widget::outer() {
duncanFrance 12:63db16fea709 85 return _outer;
duncanFrance 12:63db16fea709 86 }
duncanFrance 12:63db16fea709 87
duncanFrance 12:63db16fea709 88 const Rectangle &Widget::inner() {
duncanFrance 12:63db16fea709 89 return _inner;
duncanFrance 12:63db16fea709 90 }
duncanFrance 13:6714534e7974 91 **/
duncanFrance 13:6714534e7974 92 void Widget::setOffset(int x, int y) {
duncanFrance 13:6714534e7974 93 _outer.x = _outer.x - _offset.x() + x;
duncanFrance 13:6714534e7974 94 _outer.y = _outer.y - _offset.y() + y;
duncanFrance 13:6714534e7974 95 _offset.x(x);
duncanFrance 13:6714534e7974 96 _offset.y(y);
duncanFrance 13:6714534e7974 97 damage();
duncanFrance 13:6714534e7974 98 adjust();
duncanFrance 13:6714534e7974 99 }
duncanFrance 13:6714534e7974 100
duncanFrance 13:6714534e7974 101 int Widget::offsetX() {
duncanFrance 13:6714534e7974 102 return _offset.x();
duncanFrance 13:6714534e7974 103 }
duncanFrance 13:6714534e7974 104
duncanFrance 13:6714534e7974 105 int Widget::offsetY() {
duncanFrance 13:6714534e7974 106 return _offset.y();
duncanFrance 13:6714534e7974 107 }
duncanFrance 13:6714534e7974 108
duncanFrance 12:63db16fea709 109
duncanFrance 12:63db16fea709 110 void Widget::setForeground(uint16_t color)
duncanFrance 12:63db16fea709 111 {
duncanFrance 12:63db16fea709 112 if(_fg != color) {
duncanFrance 12:63db16fea709 113 _fg = color;
duncanFrance 12:63db16fea709 114 dirty();
duncanFrance 12:63db16fea709 115 }
duncanFrance 12:63db16fea709 116 }
duncanFrance 12:63db16fea709 117
duncanFrance 12:63db16fea709 118 void Widget::setBackground(uint16_t color)
duncanFrance 12:63db16fea709 119 {
duncanFrance 12:63db16fea709 120 if(_bg != color) {
duncanFrance 12:63db16fea709 121 _bg = color;
duncanFrance 12:63db16fea709 122 dirty();
duncanFrance 12:63db16fea709 123 }
duncanFrance 12:63db16fea709 124 }
duncanFrance 12:63db16fea709 125
duncanFrance 12:63db16fea709 126
duncanFrance 12:63db16fea709 127 /**
duncanFrance 12:63db16fea709 128 * Set the amount of padding between the border and a widget edge
duncanFrance 12:63db16fea709 129 **/
duncanFrance 12:63db16fea709 130 void Widget::setPadding(int pixels)
duncanFrance 12:63db16fea709 131 {
duncanFrance 12:63db16fea709 132 if(_padding != pixels) {
duncanFrance 12:63db16fea709 133 _padding = pixels;
duncanFrance 12:63db16fea709 134 dirty();
duncanFrance 12:63db16fea709 135 }
duncanFrance 12:63db16fea709 136 }
duncanFrance 12:63db16fea709 137
duncanFrance 12:63db16fea709 138 void Widget::setBorder(int width, uint16_t colour)
duncanFrance 12:63db16fea709 139 {
duncanFrance 12:63db16fea709 140 if(_borderWidth != width || _borderColour != colour) {
duncanFrance 12:63db16fea709 141 _borderColour = colour;
duncanFrance 12:63db16fea709 142 _borderWidth = width;
duncanFrance 12:63db16fea709 143 dirty();
duncanFrance 12:63db16fea709 144 }
duncanFrance 12:63db16fea709 145 }
duncanFrance 12:63db16fea709 146
duncanFrance 12:63db16fea709 147 void Widget::draw()
duncanFrance 12:63db16fea709 148 {
duncanFrance 12:63db16fea709 149 if(!_hidden && (_dirtied | _damaged)) {
duncanFrance 12:63db16fea709 150 _draw();
duncanFrance 12:63db16fea709 151 _dirtied = false;
duncanFrance 12:63db16fea709 152 _damaged = false;
duncanFrance 12:63db16fea709 153 }
duncanFrance 12:63db16fea709 154 }
duncanFrance 12:63db16fea709 155
duncanFrance 12:63db16fea709 156 void Widget::clear()
duncanFrance 12:63db16fea709 157 {
duncanFrance 12:63db16fea709 158 if(!_hidden) _clear();
duncanFrance 12:63db16fea709 159 }
duncanFrance 12:63db16fea709 160
duncanFrance 12:63db16fea709 161 void Widget::show()
duncanFrance 12:63db16fea709 162 {
duncanFrance 12:63db16fea709 163 _hidden = false;
duncanFrance 12:63db16fea709 164 draw();
duncanFrance 12:63db16fea709 165 }
duncanFrance 12:63db16fea709 166
duncanFrance 12:63db16fea709 167 void Widget::hide()
duncanFrance 12:63db16fea709 168 {
duncanFrance 12:63db16fea709 169 clear();
duncanFrance 12:63db16fea709 170 _hidden = true;
duncanFrance 12:63db16fea709 171 }
duncanFrance 12:63db16fea709 172
duncanFrance 12:63db16fea709 173 bool Widget::isHidden()
duncanFrance 12:63db16fea709 174 {
duncanFrance 12:63db16fea709 175 return _hidden;
duncanFrance 12:63db16fea709 176 }
duncanFrance 12:63db16fea709 177
duncanFrance 12:63db16fea709 178 void Widget::setEventHandler(EventHandler* handler)
duncanFrance 12:63db16fea709 179 {
duncanFrance 12:63db16fea709 180 EventListener::setEventHandler(handler);
duncanFrance 12:63db16fea709 181 _context->eventDispatcher()->detachListener(this);
duncanFrance 12:63db16fea709 182 _context->eventDispatcher()->attachListener(this);
duncanFrance 12:63db16fea709 183 }
duncanFrance 12:63db16fea709 184
duncanFrance 12:63db16fea709 185 void Widget::unsetEventHandler(EventHandler *handler)
duncanFrance 12:63db16fea709 186 {
duncanFrance 12:63db16fea709 187 EventListener::unsetEventHandler(handler);
duncanFrance 12:63db16fea709 188 }
duncanFrance 12:63db16fea709 189
duncanFrance 12:63db16fea709 190 bool Widget::intersects(Widget *w)
duncanFrance 12:63db16fea709 191 {
duncanFrance 13:6714534e7974 192 return _outer.intersects(w->_outer);
duncanFrance 12:63db16fea709 193 }
duncanFrance 12:63db16fea709 194
duncanFrance 12:63db16fea709 195 void Widget::dirty()
duncanFrance 12:63db16fea709 196 {
duncanFrance 12:63db16fea709 197 if(!_dirtying) {
duncanFrance 12:63db16fea709 198 _dirtying = true;
duncanFrance 12:63db16fea709 199 _dirty();
duncanFrance 12:63db16fea709 200 _dirtying = false;
duncanFrance 12:63db16fea709 201 }
duncanFrance 12:63db16fea709 202 }
duncanFrance 12:63db16fea709 203
duncanFrance 12:63db16fea709 204 bool Widget::isDirty() {
duncanFrance 12:63db16fea709 205 return _dirtied;
duncanFrance 12:63db16fea709 206 }
duncanFrance 12:63db16fea709 207
duncanFrance 12:63db16fea709 208 void Widget::dirtyAll()
duncanFrance 12:63db16fea709 209 {
duncanFrance 12:63db16fea709 210 _dirtied = true;
duncanFrance 12:63db16fea709 211 }
duncanFrance 12:63db16fea709 212
duncanFrance 12:63db16fea709 213 void Widget::damage() {
duncanFrance 12:63db16fea709 214 if(!_damaging) {
duncanFrance 12:63db16fea709 215 _damaging = true;
duncanFrance 12:63db16fea709 216 _damage();
duncanFrance 12:63db16fea709 217 _damaging = false;
duncanFrance 12:63db16fea709 218 }
duncanFrance 12:63db16fea709 219 }
duncanFrance 12:63db16fea709 220
duncanFrance 12:63db16fea709 221 bool Widget::isDamaged() {
duncanFrance 12:63db16fea709 222 return _damaged;
duncanFrance 12:63db16fea709 223 }
duncanFrance 12:63db16fea709 224
duncanFrance 12:63db16fea709 225 void Widget::adjust()
duncanFrance 12:63db16fea709 226 {
duncanFrance 12:63db16fea709 227 if(!_adjusting) {
duncanFrance 12:63db16fea709 228 _adjusting = true;
duncanFrance 12:63db16fea709 229 _adjust();
duncanFrance 12:63db16fea709 230 _adjusting = false;
duncanFrance 12:63db16fea709 231 }
duncanFrance 12:63db16fea709 232 }
duncanFrance 12:63db16fea709 233
duncanFrance 12:63db16fea709 234 GraphicsDisplay* Widget::display()
duncanFrance 12:63db16fea709 235 {
duncanFrance 12:63db16fea709 236 return _context->display();
duncanFrance 12:63db16fea709 237 }
duncanFrance 12:63db16fea709 238
duncanFrance 12:63db16fea709 239 /**********************************************************
duncanFrance 12:63db16fea709 240 * Protected methods
duncanFrance 12:63db16fea709 241 **********************************************************/
duncanFrance 12:63db16fea709 242 void Widget::_draw() {
duncanFrance 12:63db16fea709 243 GraphicsDisplay *d = display();
duncanFrance 12:63db16fea709 244 // Draw the border
duncanFrance 12:63db16fea709 245 // Top
duncanFrance 12:63db16fea709 246 d->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_borderWidth, _borderColour);
duncanFrance 12:63db16fea709 247 // Bottom
duncanFrance 12:63db16fea709 248 d->fillrect(_outer.x, _outer.y + _outer.height - _borderWidth, _outer.x + _outer.width, _outer.y+_outer.height, _borderColour);
duncanFrance 12:63db16fea709 249 // Left
duncanFrance 12:63db16fea709 250 d->fillrect(_outer.x, _outer.y, _outer.x+_borderWidth, _outer.y+_outer.height, _borderColour);
duncanFrance 12:63db16fea709 251 // Right
duncanFrance 12:63db16fea709 252 d->fillrect(_outer.x+_outer.width-_borderWidth, _outer.y, _outer.x+_outer.width, _outer.y+_outer.height, _borderColour);
duncanFrance 12:63db16fea709 253 }
duncanFrance 12:63db16fea709 254
duncanFrance 12:63db16fea709 255 void Widget::_clear() {
duncanFrance 12:63db16fea709 256 display()->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_outer.height, display()->getBackground());
duncanFrance 12:63db16fea709 257 }
duncanFrance 12:63db16fea709 258
duncanFrance 12:63db16fea709 259 void Widget::_dirty()
duncanFrance 12:63db16fea709 260 {
duncanFrance 12:63db16fea709 261 _dirtied = true;
duncanFrance 12:63db16fea709 262 if(_parent != NULL) {
duncanFrance 12:63db16fea709 263 _parent->dirty();
duncanFrance 12:63db16fea709 264 }
duncanFrance 12:63db16fea709 265 }
duncanFrance 12:63db16fea709 266
duncanFrance 12:63db16fea709 267 void Widget::_damage()
duncanFrance 12:63db16fea709 268 {
duncanFrance 12:63db16fea709 269 _damaged = true;
duncanFrance 12:63db16fea709 270 if(_parent != NULL) {
duncanFrance 12:63db16fea709 271 _parent->dirty();
duncanFrance 12:63db16fea709 272 }
duncanFrance 12:63db16fea709 273 }
duncanFrance 12:63db16fea709 274
duncanFrance 12:63db16fea709 275 void Widget::_adjust() {
duncanFrance 12:63db16fea709 276 // Recalculate size of inner Rect
duncanFrance 12:63db16fea709 277 _inner.resize(_outer, _borderWidth + _padding);
duncanFrance 12:63db16fea709 278 }