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