Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TouchScreenGUIDemo
Revision 18:d849f3ada858, committed 2016-05-28
- Comitter:
- duncanFrance
- Date:
- Sat May 28 14:50:14 2016 +0000
- Parent:
- 17:5184762fda6c
- Commit message:
- Moved the event queue into the EventDispatcher; Improved event handling across Window/Widget
Changed in this revision
--- a/Core/GUI.cpp Sun May 22 16:35:23 2016 +0000
+++ b/Core/GUI.cpp Sat May 28 14:50:14 2016 +0000
@@ -1,7 +1,9 @@
#include "GUI.h"
GUI::GUI(GraphicsContext* context) : _context(context), _rootWindow(context)
-{}
+{
+ _context->eventDispatcher()->attachListener(&_rootWindow);
+}
GraphicsContext* GUI::getGraphicsContext() {
return _context;
@@ -11,36 +13,8 @@
return &_rootWindow;
}
-void GUI::queueEvent(const Event e)
-{
- Event* qe = _mailbox.alloc();
- qe->type = e.type;
- qe->target = e.target;
- qe->screenX = e.screenX;
- qe->screenY = e.screenY;
- _mailbox.put(qe);
+void GUI::run() {
+ _context->eventDispatcher()->pumpEvents();
+ _rootWindow.draw();
+
}
-
-void GUI::pumpEvents()
-{
-
- osEvent oe = _mailbox.get(1);
-
- if(oe.status == osEventMail) {
-
- Event* qe = (Event*)oe.value.p;
- Event e;
- e.target = qe->target;
- e.type = qe->type;
- e.screenX = qe->screenX;
- e.screenY = qe->screenY;
-
- _context->eventDispatcher()->dispatchEvent(e);
- _mailbox.free(qe);
- }
-}
-
-void GUI::updateWindow()
-{
- _rootWindow.draw();
-}
\ No newline at end of file
--- a/Core/GUI.h Sun May 22 16:35:23 2016 +0000
+++ b/Core/GUI.h Sat May 28 14:50:14 2016 +0000
@@ -3,8 +3,6 @@
class GUI;
-#include "rtos.h"
-
#include "GraphicsContext.h"
#include "Window.h"
@@ -21,14 +19,12 @@
GraphicsContext* getGraphicsContext();
Window *rootWindow();
- void queueEvent(const Event e);
- void pumpEvents();
- void updateWindow();
+ void run();
private:
GraphicsContext* _context;
- Mail<Event, 64> _mailbox;
Window _rootWindow;
+
};
#endif
\ No newline at end of file
--- a/Core/LinkedList.h Sun May 22 16:35:23 2016 +0000
+++ b/Core/LinkedList.h Sat May 28 14:50:14 2016 +0000
@@ -17,6 +17,30 @@
};
template<class T>
+class LinkedListIterator {
+ public:
+ LinkedListIterator(LinkedListNode<T> *first) {
+ _current = first;
+ }
+
+ ~LinkedListIterator() {}
+
+ T* next() {
+
+ LinkedListNode<T>* p = _current;
+ if(p != NULL) {
+ _current = _current->next;
+ return p->data;
+ }
+
+ return NULL;
+ }
+
+private:
+ LinkedListNode<T>* _current;
+};
+
+template<class T>
class LinkedList
{
@@ -24,7 +48,11 @@
LinkedList() : _first(NULL), _next(NULL), _current(NULL), _size(0) {}
~LinkedList() {}
-
+
+ LinkedListIterator<T> getIterator() {
+ LinkedListIterator<T> iterator(_first);
+ return iterator;
+ }
void append(T* data) {
--- a/Events/EventDispatcher.cpp Sun May 22 16:35:23 2016 +0000
+++ b/Events/EventDispatcher.cpp Sat May 28 14:50:14 2016 +0000
@@ -15,8 +15,35 @@
EventListener* l;
_listeners.reset();
while((l=_listeners.next()) != NULL) {
- if(l->isEventTarget(e)) {
- l->handleEvent(e);
- }
+ l->handleEvent(e);
}
-}
\ No newline at end of file
+}
+
+void EventDispatcher::queueEvent(const Event e)
+{
+ Event* qe = _mailbox.alloc();
+ qe->type = e.type;
+ qe->target = e.target;
+ qe->screenX = e.screenX;
+ qe->screenY = e.screenY;
+ _mailbox.put(qe);
+}
+
+void EventDispatcher::pumpEvents()
+{
+
+ osEvent oe = _mailbox.get(1);
+
+ if(oe.status == osEventMail) {
+
+ Event* qe = (Event*)oe.value.p;
+ Event e;
+ e.target = qe->target;
+ e.type = qe->type;
+ e.screenX = qe->screenX;
+ e.screenY = qe->screenY;
+
+ dispatchEvent(e);
+ _mailbox.free(qe);
+ }
+}
--- a/Events/EventDispatcher.h Sun May 22 16:35:23 2016 +0000
+++ b/Events/EventDispatcher.h Sat May 28 14:50:14 2016 +0000
@@ -1,6 +1,8 @@
#ifndef SIMPLEGUI_EVENT_DISPATCHER_H
#define SIMPLEGUI_EVENT_DISPATCHER_H
+#include "rtos.h"
+
#include "EventListener.h"
#include "LinkedList.h"
@@ -15,10 +17,21 @@
void attachListener(EventListener* l);
void detachListener(EventListener* l);
void dispatchEvent(Event e);
+
+ /**
+ * Normally called from a separate thread to queue an event for later processing by the main thread
+ **/
+ void queueEvent(const Event e);
+
+ /**
+ * Should be called on the main thread
+ **/
+ void pumpEvents();
private:
LinkedList<EventListener> _listeners;
+ Mail<Event, 64> _mailbox;
};
--- a/Events/EventListener.cpp Sun May 22 16:35:23 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#include "EventListener.h"
-
-EventListener::EventListener() {
-}
-
-bool EventListener::isEventTarget(Event e) {
- return false;
-}
-
-void EventListener::setEventHandler(EventHandler* handler) {
- _handlers.appendOnce(handler);
-}
-
-void EventListener::unsetEventHandler(EventHandler* handler) {
-
- _handlers.remove(handler);
-}
-
-void EventListener::handleEvent(Event e) {
-
- EventHandler* h;
- _handlers.reset();
-
- while((h = _handlers.next()) != NULL) {
- if(h->type == e.type) {
- e.target = this;
- h->handle(e);
- }
- }
-}
\ No newline at end of file
--- a/Events/EventListener.h Sun May 22 16:35:23 2016 +0000
+++ b/Events/EventListener.h Sat May 28 14:50:14 2016 +0000
@@ -5,23 +5,16 @@
class EventListener;
#include "EventHandler.h"
-#include "LinkedList.h"
class EventListener
{
public:
- EventListener();
+ virtual void handleEvent(Event e) =0;
+ virtual void setEventHandler(EventHandler *handler) =0;
+ virtual void unsetEventHandler(EventHandler* handler) =0;
- virtual bool isEventTarget(Event e);
- void handleEvent(Event e);
- void setEventHandler(EventHandler *handler);
- void unsetEventHandler(EventHandler* handler);
-
-protected:
-
- LinkedList<EventHandler> _handlers;
};
#endif
\ No newline at end of file
--- a/Events/EventSource.h Sun May 22 16:35:23 2016 +0000
+++ b/Events/EventSource.h Sat May 28 14:50:14 2016 +0000
@@ -1,7 +1,7 @@
#ifndef SIMPLEGUI_EVENT_SOURCE_H
#define SIMPLEGUI_EVENT_SOURCE_H
-#include "GUI.h"
+#include "EventDispatcher.h"
/**
* Interface defining a class which sources events
@@ -10,11 +10,11 @@
public:
- EventSource(GUI* gui) : _gui(gui) {}
+ EventSource(EventDispatcher* dispatcher) : _eventDispatcher(dispatcher) {}
protected:
- GUI* _gui;
+ EventDispatcher* _eventDispatcher;
};
--- a/Events/EventType.h Sun May 22 16:35:23 2016 +0000
+++ b/Events/EventType.h Sat May 28 14:50:14 2016 +0000
@@ -5,18 +5,18 @@
enum EventType {
- TOUCH_START,
- TOUCH_END,
- TOUCH_MOVE,
- TOUCH_TAP,
- TOUCH_DOUBLE_TAP,
+ TOUCH_START = 1 << 0,
+ TOUCH_END = 1 << 1,
+ TOUCH_MOVE = 1 << 2,
+ TOUCH_TAP = 1 << 3,
+ TOUCH_DOUBLE_TAP = 1 << 4,
- MOUSE_DOWN,
- MOUSE_UP,
- MOUSE_MOVE,
- MOUSE_DRAG,
- MOUSE_CLICK,
- MOUSE_DOUBLE_CLICK
+ MOUSE_DOWN = 1 << 5,
+ MOUSE_UP = 1 << 6,
+ MOUSE_MOVE = 1 << 7,
+ MOUSE_DRAG = 1 << 8,
+ MOUSE_CLICK = 1 << 9,
+ MOUSE_DOUBLE_CLICK = 1 << 10
};
#endif
\ No newline at end of file
--- a/Widgets/TextWidget.cpp Sun May 22 16:35:23 2016 +0000
+++ b/Widgets/TextWidget.cpp Sat May 28 14:50:14 2016 +0000
@@ -87,19 +87,24 @@
* VALIGN=MIDDLE : (0, inner.height/2 - numLines * font.height/2)
* VALIGN=BOTTOM : (0, inner.height - numLines * font.height)
**/
- int t=0;
+ int offset=0;
switch(_valign) {
- case TOP: t = 0; break;
- case MIDDLE: t = (_inner.height - (numLines * _font->zoomedHeight()))/2; break;
- case BOTTOM: t = (_inner.height - (numLines * _font->zoomedHeight())); break;
+ case TOP: offset = 0; break;
+ case MIDDLE: offset = (_inner.height - (numLines * _font->zoomedHeight()))/2; break;
+ case BOTTOM: offset = (_inner.height - (numLines * _font->zoomedHeight())); break;
+ }
+
+ _renderer->setForeground(_fg);
+ _renderer->setBackground(_bg);
+
+ // Renderer window is only high enough for the number of lines to draw.
+ int h = _font->zoomedHeight() * numLines;
+ // Clip to fit within the TextWidget inner
+ if((h + offset) > _inner.height) {
+ h = _inner.height - offset;
}
- _renderer->window(_inner.x, _inner.y + t, _inner.width, _font->zoomedHeight(), false);
- _renderer->setForeground(_fg);
- _renderer->setBackground(_bg);
- display()->fillrect(_inner.x, _inner.y, _inner.x+_inner.width, _inner.y+_inner.height, _bg);
- display()->rect(_inner.x, _inner.y, _inner.x+_inner.width, _inner.y+_inner.height, Red);
-
+ _renderer->window(_inner.x, _inner.y + offset, _inner.width, h, false);
_renderer->puts(_text, display(), _font);
display()->copy_to_lcd();
}
\ No newline at end of file
--- a/Widgets/Widget.cpp Sun May 22 16:35:23 2016 +0000
+++ b/Widgets/Widget.cpp Sat May 28 14:50:14 2016 +0000
@@ -8,31 +8,19 @@
_padding(0), _borderWidth(0), _borderColour(Black),
_adjusting(false),
_dirtied(true), _dirtying(false),
- _damaged(true), _damaging(false)
+ _damaged(true), _damaging(false),
+ _handledEvents(0)
{
}
void Widget::setParent(Widget* parent) {
_parent = parent;
- if(_parent != NULL && _handlers.size() != 0) {
- _context->eventDispatcher()->attachListener(this);
- } else if(_parent == NULL && _handlers.size() == 0) {
- _context->eventDispatcher()->detachListener(this);
- }
}
Widget *Widget::getParent() {
return _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);
-}
// Location is referred to the offset
void Widget::setLocation(int x, int y)
{
@@ -187,18 +175,58 @@
void Widget::setEventHandler(EventHandler* handler)
{
- EventListener::setEventHandler(handler);
- _context->eventDispatcher()->attachListener(this);
+ _handlers.appendOnce(handler);
+ _reenumerateEvents();
}
void Widget::unsetEventHandler(EventHandler *handler)
{
- EventListener::unsetEventHandler(handler);
- if(_handlers.size() == 0) {
- _context->eventDispatcher()->detachListener(this);
- }
+ _handlers.remove(handler);
+ _reenumerateEvents();
+}
+
+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::handleEvent(Event e) {
+ e.target = this;
+ if(_isEventTarget(e)) {
+ _handlers.reset();
+ EventHandler *h;
+ while((h = _handlers.next()) != NULL) {
+ if(h->type == e.type) {
+ h->handle(e);
+ }
+ }
+ }
+}
+
+void Widget::_reenumerateEvents() {
+ _reenumerateHandledEvents();
+ if(_parent != NULL) {
+ _parent->_reenumerateEvents();
+ }
+}
+
+void Widget::_reenumerateHandledEvents() {
+ _handledEvents = 0;
+ EventHandler *h;
+ LinkedListIterator<EventHandler> eit = _handlers.getIterator();
+ while((h = eit.next()) != NULL) {
+ _handledEvents |= h->type;
+ }
+}
+
+uint16_t Widget::_getHandledEvents() {
+ return _handledEvents;
+}
+
bool Widget::intersects(Widget *w)
{
return _outer.intersects(w->_outer);
@@ -253,6 +281,7 @@
**********************************************************/
void Widget::_draw() {
GraphicsDisplay *d = display();
+ //_clear();
// Draw the border
// Top
d->fillrect(_outer.x, _outer.y, _outer.x+_outer.width, _outer.y+_borderWidth, _borderColour);
--- a/Widgets/Widget.h Sun May 22 16:35:23 2016 +0000
+++ b/Widgets/Widget.h Sat May 28 14:50:14 2016 +0000
@@ -32,9 +32,7 @@
/********************************************************
* Common Widget methods
- ********************************************************/
- virtual bool isEventTarget(Event e);
-
+ ********************************************************/
virtual void setLocation(int x, int y);
virtual void setSize(int width, int height);
virtual void setWidth(int width);
@@ -64,8 +62,12 @@
void hide();
bool isHidden();
- void setEventHandler(EventHandler *handler);
- void unsetEventHandler(EventHandler *handler);
+ /**
+ * Implementation of EventListener
+ **/
+ virtual void handleEvent(Event e);
+ virtual void setEventHandler(EventHandler *handler);
+ virtual void unsetEventHandler(EventHandler *handler);
bool intersects(Widget *widget);
@@ -91,6 +93,9 @@
* Convenience method
**/
GraphicsDisplay *display();
+ virtual void _reenumerateEvents();
+ virtual void _reenumerateHandledEvents();
+ virtual uint16_t _getHandledEvents();
protected:
@@ -101,6 +106,12 @@
virtual void _damage();
virtual void _adjust();
+ /**
+ * Methods to help with event handling
+ **/
+ bool _isEventTarget(Event e);
+
+ uint16_t _handledEvents;
Widget* _parent;
GraphicsContext* _context;
@@ -122,6 +133,8 @@
bool _damaged;
bool _damaging;
+
+ LinkedList<EventHandler> _handlers;
};
#endif
\ No newline at end of file
--- a/Widgets/Window.cpp Sun May 22 16:35:23 2016 +0000
+++ b/Widgets/Window.cpp Sat May 28 14:50:14 2016 +0000
@@ -1,6 +1,6 @@
#include "Window.h"
-Window::Window(GraphicsContext* context) : Widget(context)
+Window::Window(GraphicsContext* context) : Widget(context), _childHandledEvents(0)
{
setSize(context->display()->width(), context->display()->height());
}
@@ -9,6 +9,7 @@
{
_widgets.append(widget);
widget->setParent(this);
+ _reenumerateEvents();
widget->show();
dirtyAll();
damage();
@@ -20,6 +21,7 @@
widget->hide();
_widgets.remove(widget);
widget->setParent(NULL);
+ _reenumerateEvents();
dirty();
}
@@ -74,11 +76,41 @@
void Window::_dirtyIntersected(Widget *w)
{
Widget *o;
- _widgets.reset();
- while((o = _widgets.next()) != NULL) {
+ 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;
+}
--- a/Widgets/Window.h Sun May 22 16:35:23 2016 +0000
+++ b/Widgets/Window.h Sat May 28 14:50:14 2016 +0000
@@ -24,6 +24,10 @@
virtual void detach(Widget *widget);
virtual void dirtyAll();
+ virtual void handleEvent(Event e);
+ virtual void _reenumerateHandledEvents();
+ virtual uint16_t _getHandledEvents();
+
protected:
/**
@@ -32,6 +36,7 @@
virtual void _draw();
LinkedList<Widget> _widgets;
+ uint16_t _childHandledEvents;
void _dirtyIntersected(Widget *w);
};