from bbc microbit library
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal by
Diff: inc/core/EventModel.h
- Revision:
- 1:8aa5cdb4ab67
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/core/EventModel.h Thu Apr 07 01:33:22 2016 +0100 @@ -0,0 +1,430 @@ +/* +The MIT License (MIT) + +Copyright (c) 2016 British Broadcasting Corporation. +This software is provided by Lancaster University by arrangement with the BBC. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifndef EVENT_MODEL_H +#define EVENT_MODEL_H + +#include "mbed.h" +#include "MicroBitConfig.h" +#include "MicroBitComponent.h" +#include "MicroBitEvent.h" +#include "MicroBitListener.h" +#include "ErrorNo.h" + +/** + * Class definition for the micro:bit EventModel. + * + * It is common to need to send events from one part of a program (or system) to another. + * The way that these events are stored and delivered is known as an Event Model... + * + * The micro:bit can be programmed in a number of languages, and it not be good to + * constrain those languages to any particular event model (e.g. they may have their own already). + * + * This class defines the functionality an event model needs to have to be able to interact + * with events generated and/or used by the micro:bit runtime. Programmer may choose to implement + * such funcitonality to integrate their own event models. + * + * This is an example of a key principle in computing - ABSTRACTION. This is now part of the + * UK's Computing curriculum in schools... so ask your teacher about it. :-) + * + * An EventModel implementation is provided in the MicroBitMessageBus class. + */ +class EventModel +{ + public: + + static EventModel *defaultEventBus; + + /** + * Queues the given event to be sent to all registered recipients. + * The method of delivery will vary depending on the underlying implementation. + * + * @param The event to send. + * + * @return This default implementation simply returns MICROBIT_NOT_SUPPORTED. + */ + virtual int send(MicroBitEvent evt) + { + (void) evt; + return MICROBIT_NOT_SUPPORTED; + } + + /** + * Add the given MicroBitListener to the list of event handlers, unconditionally. + * + * @param listener The MicroBitListener to validate. + * + * @return This default implementation simply returns MICROBIT_NOT_SUPPORTED. + */ + virtual int add(MicroBitListener *listener) + { + (void) listener; + return MICROBIT_NOT_SUPPORTED; + } + + /** + * Remove the given MicroBitListener from the list of event handlers. + * + * @param listener The MicroBitListener to remove. + * + * @return This default implementation simply returns MICROBIT_NOT_SUPPORTED. + */ + virtual int remove(MicroBitListener *listener) + { + (void) listener; + return MICROBIT_NOT_SUPPORTED; + } + + /** + * Returns the MicroBitListener at the given position in the list. + * + * @param n The index of the desired MicroBitListener. + * + * @return This default implementation simply returns NULL. + */ + MicroBitListener *elementAt(int n) + { + (void) n; + return NULL; + } + + /** + * Define the default EventModel to use for events raised and consumed by the microbit-dal runtime. + * The default EventModel may be changed at any time. + * + * @param model A new instance of an EventModel to use as the default. + * + * @return MICROBIT_OK on success. + * + * Example: + * @code + * MicroBitMessageBus b(); + * EventModel:setDefaultEventModel(b); + * @endcode + */ + static int setDefaultEventModel(EventModel &model) + { + EventModel::defaultEventBus = &model; + return MICROBIT_OK; + } + + /** + * Register a listener function. + * + * An EventModel implementing this interface may optionally choose to override this method, + * if that EventModel supports asynchronous callbacks to user code, but there is no + * requirement to do so. + * + * @param id The source of messages to listen for. Events sent from any other IDs will be filtered. + * Use MICROBIT_ID_ANY to receive events from all components. + * + * @param value The value of messages to listen for. Events with any other values will be filtered. + * Use MICROBIT_EVT_ANY to receive events of any value. + * + * @param handler The function to call when an event is received. + * + * @param flags User specified, implementation specific flags, that allow behaviour of this events listener + * to be tuned. + * + * @return MICROBIT_OK on success, or any valid error code defined in "ErrNo.h". The default implementation + * simply returns MICROBIT_NOT_SUPPORTED. + * + * @code + * void onButtonBClicked(MicroBitEvent) + * { + * //do something + * } + * + * // call onButtonBClicked when ever a click event from buttonB is detected. + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); + * @endcode + */ + int listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags = EVENT_LISTENER_DEFAULT_FLAGS) + { + if (handler == NULL) + return MICROBIT_INVALID_PARAMETER; + + MicroBitListener *newListener = new MicroBitListener(id, value, handler, flags); + + if(add(newListener) == MICROBIT_OK) + return MICROBIT_OK; + + delete newListener; + + return MICROBIT_NOT_SUPPORTED; + } + + /** + * Register a listener function. + * + * An EventModel implementing this interface may optionally choose to override this method, + * if that EventModel supports asynchronous callbacks to user code, but there is no + * requirement to do so. + * + * @param id The source of messages to listen for. Events sent from any other IDs will be filtered. + * Use MICROBIT_ID_ANY to receive events from all components. + * + * @param value The value of messages to listen for. Events with any other values will be filtered. + * Use MICROBIT_EVT_ANY to receive events of any value. + * + * @param handler The function to call when an event is received. + * + * @param arg Provide the callback with in an additional argument. + * + * @param flags User specified, implementation specific flags, that allow behaviour of this events listener + * to be tuned. + * + * @return MICROBIT_OK on success, or any valid error code defined in "ErrNo.h". The default implementation + * simply returns MICROBIT_NOT_SUPPORTED. + * + * @code + * void onButtonBClicked(MicroBitEvent, void* data) + * { + * //do something + * } + * + * // call onButtonBClicked when ever a click event from buttonB is detected. + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); + * @endcode + */ + int listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags = EVENT_LISTENER_DEFAULT_FLAGS) + { + if (handler == NULL) + return MICROBIT_INVALID_PARAMETER; + + MicroBitListener *newListener = new MicroBitListener(id, value, handler, arg, flags); + + if(add(newListener) == MICROBIT_OK) + return MICROBIT_OK; + + delete newListener; + + return MICROBIT_NOT_SUPPORTED; + } + + /** + * Register a listener function. + * + * @param id The source of messages to listen for. Events sent from any other IDs will be filtered. + * Use MICROBIT_ID_ANY to receive events from all components. + * + * @param value The value of messages to listen for. Events with any other values will be filtered. + * Use MICROBIT_EVT_ANY to receive events of any value. + * + * @param hander The function to call when an event is received. + * + * @param flags User specified, implementation specific flags, that allow behaviour of this events listener + * to be tuned. + * + * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler or object + * pointers are NULL. + * + * @code + * void SomeClass::onButtonBClicked(MicroBitEvent) + * { + * //do something + * } + * + * SomeClass s = new SomeClass(); + * + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick); + * @endcode + */ + template <typename T> + int listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags = EVENT_LISTENER_DEFAULT_FLAGS); + + + /** + * Unregister a listener function. + * Listeners are identified by the Event ID, Event value and handler registered using listen(). + * + * @param id The Event ID used to register the listener. + * @param value The Event value used to register the listener. + * @param handler The function used to register the listener. + * + * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler + * given is NULL. + * + * Example: + * @code + * void onButtonBClick(MicroBitEvent) + * { + * //do something + * } + * + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); + * + * // the previously created listener is now ignored. + * uBit.messageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); + * @endcode + */ + int ignore(int id, int value, void (*handler)(MicroBitEvent)) + { + if (handler == NULL) + return MICROBIT_INVALID_PARAMETER; + + MicroBitListener listener(id, value, handler); + remove(&listener); + + return MICROBIT_OK; + } + + /** + * Unregister a listener function. + * Listeners are identified by the Event ID, Event value and handler registered using listen(). + * + * @param id The Event ID used to register the listener. + * @param value The Event value used to register the listener. + * @param handler The function used to register the listener. + * + * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler + * given is NULL. + * + * Example: + * @code + * void onButtonBClick(MicroBitEvent, void* data) + * { + * //do something + * } + * + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); + * + * // the previously created listener is now ignored. + * uBit.messageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); + * @endcode + */ + int ignore(int id, int value, void (*handler)(MicroBitEvent, void*)) + { + if (handler == NULL) + return MICROBIT_INVALID_PARAMETER; + + MicroBitListener listener(id, value, handler, NULL); + remove(&listener); + + return MICROBIT_OK; + } + + /** + * Unregister a listener function. + * Listners are identified by the Event ID, Event value and handler registered using listen(). + * + * @param id The Event ID used to register the listener. + * @param value The Event value used to register the listener. + * @param handler The function used to register the listener. + * + * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler or object + * pointers are NULL. + * + * Example: + * @code + * + * void SomeClass::onButtonBClick() + * { + * //do something + * } + * + * SomeClass s = new SomeClass(); + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick); + * + * // the previously created listener is now ignored. + * uBit.messageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick); + * @endcode + */ + template <typename T> + int ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent)); + +}; + +/** + * A registration function to allow C++ member functions (methods) to be registered as an event + * listener. + * + * @param id The source of messages to listen for. Events sent from any other IDs will be filtered. + * Use MICROBIT_ID_ANY to receive events from all components. + * + * @param value The value of messages to listen for. Events with any other values will be filtered. + * Use MICROBIT_EVT_ANY to receive events of any value. + * + * @param object The object on which the method should be invoked. + * + * @param handler The method to call when an event is received. + * + * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler or object + * pointers are NULL. + */ +template <typename T> +int EventModel::listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags) +{ + if (object == NULL || handler == NULL) + return MICROBIT_INVALID_PARAMETER; + + MicroBitListener *newListener = new MicroBitListener(id, value, object, handler, flags); + + if(add(newListener) == MICROBIT_OK) + return MICROBIT_OK; + + delete newListener; + return MICROBIT_NOT_SUPPORTED; +} + +/** + * Unregister a listener function. + * Listners are identified by the Event ID, Event value and handler registered using listen(). + * + * @param id The Event ID used to register the listener. + * @param value The Event value used to register the listener. + * @param handler The function used to register the listener. + * + * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler or object + * pointers are NULL. + * + * Example: + * @code + * + * void SomeClass::onButtonBClick() + * { + * //do something + * } + * + * SomeClass s = new SomeClass(); + * uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick); + * + * // the previously created listener is now ignored. + * uBit.messageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick); + * @endcode + */ +template <typename T> +int EventModel::ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent)) +{ + if (handler == NULL) + return MICROBIT_INVALID_PARAMETER; + + MicroBitListener listener(id, value, object, handler); + remove(&listener); + + return MICROBIT_OK; +} + +#endif