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
|