Line data Source code
1 : #pragma once 2 : 3 : #include <AH/Containers/LinkedList.hpp> 4 : #include <Display/DisplayInterface.hpp> 5 : 6 : BEGIN_CS_NAMESPACE 7 : 8 : /** 9 : * @brief An interface for elements that draw to a display. 10 : * @ingroup DisplayElements 11 : */ 12 : class DisplayElement : public DoublyLinkable<DisplayElement> { 13 : protected: 14 : /// @brief Create a new DisplayElement. 15 : /// 16 : /// @param display 17 : /// The display that this display element draws to. 18 2 : DisplayElement(DisplayInterface &display) : display(display) { 19 : // The elements are sorted by the address of their displays. 20 : // This way, all display elements that draw to the same display are next 21 : // to each other. This means that the display buffer can be reused, and 22 : // makes it easier to iterate over the displays and draw to them. 23 2 : elements.insertSorted( 24 1 : this, [](const DisplayElement &lhs, const DisplayElement &rhs) { 25 1 : return reinterpret_cast<uintptr_t>(&lhs.getDisplay()) < 26 1 : reinterpret_cast<uintptr_t>(&rhs.getDisplay()); 27 : }); 28 2 : } 29 : 30 : /// @name Enabling and disabling display elements 31 : /// @{ 32 : 33 : /// Enable this display element: insert it into the linked list of 34 : /// instances, so it gets drawn to the display 35 : void enable() { 36 : if (isEnabled()) { 37 : ERROR(F("Error: This element is already enabled."), 0x9212); 38 : return; 39 : } 40 : elements.append(this); 41 : } 42 : 43 : /// Disable this display element: remove it from the linked list of 44 : /// instances, so it no longer gets drawn to the display 45 : void disable() { 46 : if (!isEnabled()) { 47 : ERROR(F("Error: This element is already disabled."), 0x9213); 48 : return; 49 : } 50 : elements.remove(this); 51 : } 52 : 53 : /** 54 : * @brief Check if this display element is enabled. 55 : * 56 : * @note Assumes that the element is not added to a different linked 57 : * list by the user. 58 : */ 59 : bool isEnabled() const { return elements.couldContain(this); } 60 : 61 : /// @copydoc DisplayElement::enable 62 : static void enable(DisplayElement *element) { element->enable(); } 63 : /// @copydoc DisplayElement::enable 64 : static void enable(DisplayElement &element) { element.enable(); } 65 : /// @copydoc DisplayElement::enable 66 : template <class U, size_t N> 67 : static void enable(U (&array)[N]) { 68 : for (U &el : array) 69 : enable(el); 70 : } 71 : 72 : /// @copydoc DisplayElement::disable 73 : static void disable(DisplayElement *element) { element->disable(); } 74 : /// @copydoc DisplayElement::disable 75 : static void disable(DisplayElement &element) { element.disable(); } 76 : /// @copydoc DisplayElement::disable 77 : template <class U, size_t N> 78 : static void disable(U (&array)[N]) { 79 : for (U &el : array) 80 : disable(el); 81 : } 82 : 83 : /// @} 84 : 85 : public: 86 2 : virtual ~DisplayElement() { elements.remove(this); } 87 : 88 : /// Draw this DisplayElement to the display buffer. 89 : virtual void draw() = 0; 90 : 91 : /// Check if this DisplayElement has to be re-drawn. 92 : virtual bool getDirty() const = 0; 93 : 94 : /// Get a reference to the display that this element draws to. 95 0 : DisplayInterface &getDisplay() { return display; } 96 : /// Get a const reference to the display that this element draws to. 97 2 : const DisplayInterface &getDisplay() const { return display; } 98 : 99 : /// Get the list of all DisplayElement instances. 100 0 : static DoublyLinkedList<DisplayElement> &getAll() { return elements; } 101 : 102 : protected: 103 : DisplayInterface &display; 104 : 105 : static DoublyLinkedList<DisplayElement> elements; 106 : }; 107 : 108 : END_CS_NAMESPACE