From fa7d248c42fea8b20667958912254213090a8e14 Mon Sep 17 00:00:00 2001 From: Matthew Arnold Date: Sun, 5 Feb 2023 21:02:33 +0100 Subject: [PATCH 1/4] [ui] Fix clearPixel in GraphicDisplay --- src/modm/ui/display/color_graphic_display.hpp | 2 -- src/modm/ui/display/graphic_display.hpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/modm/ui/display/color_graphic_display.hpp b/src/modm/ui/display/color_graphic_display.hpp index 5e9d1e4d2d..2647f1b01b 100644 --- a/src/modm/ui/display/color_graphic_display.hpp +++ b/src/modm/ui/display/color_graphic_display.hpp @@ -5,8 +5,6 @@ #include "graphic_display.hpp" -using namespace modm::platform; - namespace modm { diff --git a/src/modm/ui/display/graphic_display.hpp b/src/modm/ui/display/graphic_display.hpp index 2a4baec66e..4faf23aadc 100644 --- a/src/modm/ui/display/graphic_display.hpp +++ b/src/modm/ui/display/graphic_display.hpp @@ -127,7 +127,7 @@ class GraphicDisplay : public IOStream inline void clearPixel(glcd::Point p) { - this->setPixel(p.x, p.y); + this->clearPixel(p.x, p.y); } /** From ee88ac7dca3fe5c7f23c9c56efa63f66aff5753d Mon Sep 17 00:00:00 2001 From: Matthew Arnold Date: Sun, 5 Feb 2023 21:02:20 +0100 Subject: [PATCH 2/4] [ui] Refactor view stack to take a GraphicDisplay This way it can be specialized with a monochrome or color display later. --- src/modm/ui/menu/communicating_view_stack.hpp | 2 +- src/modm/ui/menu/view_stack.hpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modm/ui/menu/communicating_view_stack.hpp b/src/modm/ui/menu/communicating_view_stack.hpp index 9f1c5cf7ed..77a6933266 100644 --- a/src/modm/ui/menu/communicating_view_stack.hpp +++ b/src/modm/ui/menu/communicating_view_stack.hpp @@ -29,7 +29,7 @@ namespace modm class CommunicatingViewStack : public ViewStack { public: - CommunicatingViewStack(modm::ColorGraphicDisplay* display, xpcc::Communicator* communicator) : + CommunicatingViewStack(modm::GraphicDisplay* display, xpcc::Communicator* communicator) : ViewStack(display), communicator(communicator) { diff --git a/src/modm/ui/menu/view_stack.hpp b/src/modm/ui/menu/view_stack.hpp index 188e884af8..0ed1f04ad4 100644 --- a/src/modm/ui/menu/view_stack.hpp +++ b/src/modm/ui/menu/view_stack.hpp @@ -39,7 +39,7 @@ namespace modm class ViewStack { public: - ViewStack(modm::ColorGraphicDisplay* display); + ViewStack(modm::GraphicDisplay* display); virtual ~ViewStack(); @@ -74,7 +74,7 @@ namespace modm /** * @brief getDisplay access underlying GraphicDisplay */ - inline modm::ColorGraphicDisplay& + inline modm::GraphicDisplay& getDisplay() { return *this->display; @@ -100,7 +100,7 @@ namespace modm shortButtonPress(modm::MenuButtons::Button button); protected: - modm::ColorGraphicDisplay* display; + modm::GraphicDisplay* display; modm::Stack< modm::AbstractView* , modm::LinkedList< modm::AbstractView* > > stack; }; } From cd4d2230bec1acd24db56e67ef0301e9fd0393f4 Mon Sep 17 00:00:00 2001 From: Matthew Arnold Date: Sun, 5 Feb 2023 20:50:28 +0100 Subject: [PATCH 3/4] [ui] Add support for a custom allocator to modm::ViewStack Allowing a custom allocator allows users to control how modm::AbstractView elements stored by the view stack are allocated. This, for example, allows the user to statically allocate all views and removes the memory and processing overhead of dynamically allocating views. For an example, see aruw-mcb's MainMenu class: https://github.com/uw-advanced-robotics/aruw-mcb/blob/develop/aruw-mcb-project/src/aruwsrc/display/main_menu.cpp By default, a dynamic allocator used, so default behavior remains unchanged. --- src/modm/ui/menu/abstract_menu.cpp | 21 --- src/modm/ui/menu/abstract_menu.hpp | 9 +- src/modm/ui/menu/abstract_view.cpp | 68 ---------- src/modm/ui/menu/abstract_view.hpp | 90 +++---------- src/modm/ui/menu/choice_menu.hpp | 10 +- .../{choice_menu.cpp => choice_menu_impl.hpp} | 50 ++++---- src/modm/ui/menu/communicating_view.hpp | 10 +- src/modm/ui/menu/communicating_view_stack.hpp | 6 +- src/modm/ui/menu/iabstract_view.hpp | 121 ++++++++++++++++++ src/modm/ui/menu/menu_entry_callback.hpp | 8 +- src/modm/ui/menu/scrollable_text.cpp | 3 +- src/modm/ui/menu/standard_menu.hpp | 25 ++-- ...andard_menu.cpp => standard_menu_impl.hpp} | 62 ++++----- src/modm/ui/menu/view_stack.cpp | 79 ------------ src/modm/ui/menu/view_stack.hpp | 67 ++++++++-- 15 files changed, 303 insertions(+), 326 deletions(-) delete mode 100644 src/modm/ui/menu/abstract_menu.cpp delete mode 100644 src/modm/ui/menu/abstract_view.cpp rename src/modm/ui/menu/{choice_menu.cpp => choice_menu_impl.hpp} (72%) create mode 100644 src/modm/ui/menu/iabstract_view.hpp rename src/modm/ui/menu/{standard_menu.cpp => standard_menu_impl.hpp} (61%) delete mode 100644 src/modm/ui/menu/view_stack.cpp diff --git a/src/modm/ui/menu/abstract_menu.cpp b/src/modm/ui/menu/abstract_menu.cpp deleted file mode 100644 index 146cf54108..0000000000 --- a/src/modm/ui/menu/abstract_menu.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2011, Fabian Greif - * Copyright (c) 2012, Niklas Hauser - * Copyright (c) 2013, Kevin Läufer - * Copyright (c) 2013, Thorsten Lajewski - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "abstract_menu.hpp" - -modm::AbstractMenu::AbstractMenu(modm::ViewStack* stack, uint8_t identifier): - modm::AbstractView(stack, identifier) -{ -} diff --git a/src/modm/ui/menu/abstract_menu.hpp b/src/modm/ui/menu/abstract_menu.hpp index 346744e3e8..efd82c441f 100644 --- a/src/modm/ui/menu/abstract_menu.hpp +++ b/src/modm/ui/menu/abstract_menu.hpp @@ -30,12 +30,17 @@ namespace modm{ * \author Thorsten Lajewski * \ingroup modm_ui_menu */ - class AbstractMenu: public AbstractView + template > + class AbstractMenu : public AbstractView { public: - AbstractMenu(modm::ViewStack* stack, uint8_t identifier); + AbstractMenu(modm::ViewStack* stack, uint8_t identifier) : + modm::AbstractView(stack, identifier) + { + } + virtual ~AbstractMenu() {} virtual void shortButtonPress(modm::MenuButtons::Button button) = 0; diff --git a/src/modm/ui/menu/abstract_view.cpp b/src/modm/ui/menu/abstract_view.cpp deleted file mode 100644 index 96b5ba6e05..0000000000 --- a/src/modm/ui/menu/abstract_view.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2011, Fabian Greif - * Copyright (c) 2010-2011, 2013, Georgi Grinshpun - * Copyright (c) 2013, Kevin Läufer - * Copyright (c) 2013, Thorsten Lajewski - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "view_stack.hpp" -#include "abstract_view.hpp" - -// ---------------------------------------------------------------------------- -modm::AbstractView::AbstractView(modm::ViewStack* stack, uint8_t identifier) : - stack(stack), identifier(identifier), alive(true) -{ -} - -modm::AbstractView::~AbstractView() -{ -} - -// ---------------------------------------------------------------------------- -void -modm::AbstractView::update() -{ - //nothing to be done -} - -// ---------------------------------------------------------------------------- -void -modm::AbstractView::shortButtonPress(modm::MenuButtons::Button /*button*/) -{ - //nothing to be done -} - -// ---------------------------------------------------------------------------- -bool -modm::AbstractView::isAlive() const -{ - return this->alive; -} - -void -modm::AbstractView::remove() -{ - this->alive = false; -} - -void -modm::AbstractView::onRemove() -{ - //nothing to be done here -} - -// ---------------------------------------------------------------------------- - -modm::ColorGraphicDisplay& -modm::AbstractView::display() -{ - return stack->getDisplay(); -} diff --git a/src/modm/ui/menu/abstract_view.hpp b/src/modm/ui/menu/abstract_view.hpp index 42a141d5ec..d08c8d4d72 100644 --- a/src/modm/ui/menu/abstract_view.hpp +++ b/src/modm/ui/menu/abstract_view.hpp @@ -5,6 +5,7 @@ * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski * Copyright (c) 2014, Sascha Schade + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -17,13 +18,14 @@ #ifndef MODM_ABSTRACT_VIEW_HPP #define MODM_ABSTRACT_VIEW_HPP -#include +#include -#include "menu_buttons.hpp" +#include "iabstract_view.hpp" namespace modm { // forward declaration + template class ViewStack; /** @@ -34,8 +36,10 @@ namespace modm *\ingroup modm_ui_menu */ - class AbstractView + template > + class AbstractView : public IAbstractView { + template friend class ViewStack; public: @@ -44,83 +48,27 @@ namespace modm * @param identifier can be used to determine which screen is the currently * displayed on the graphicDisplay */ - AbstractView(modm::ViewStack* stack, uint8_t identifier); - - virtual ~AbstractView() = 0; - - /** - * @brief update The update function of the top most display gets called - * as often as possible. Only the update of the top view in each - * ViewStack gets called. - */ - virtual void - update(); - - /** - * @brief hasChanged indicates the current displayed view has changed. - * This function prevents unnecessary drawing of the display - * @return if true the display has to be redrawn. - */ - virtual bool - hasChanged() = 0; - - /** - * @brief draw determine the output on the Graphic Display - */ - virtual void - draw() = 0; - - - /** - * @brief shortButtonPress handle the action for the pressed button - */ - virtual void - shortButtonPress(modm::MenuButtons::Button button); - - /** - * @brief isAlive tells the ViewStack if it should remove this screen. - * @return - */ - bool - isAlive() const; - - /** - * @brief remove the view from the screen. The viewStack handles the deletion. - */ - void - remove(); - - /** - * @brief getIdentifier of the view. - */ - inline uint8_t getIdentifier(){ - return this->identifier; + AbstractView(modm::ViewStack* stack, uint8_t identifier) : + IAbstractView(identifier), stack(stack) + { } - public: - - modm::ColorGraphicDisplay& - display(); + virtual ~AbstractView() = default; - /** - * @brief onRemove will be called right before the view gets deleted, - * can be reimplemented to reset external data. - */ - virtual void - onRemove(); - - inline modm::ViewStack* + inline modm::ViewStack* getViewStack() { return stack; } - private: - modm::ViewStack* stack; + modm::GraphicDisplay& + display() + { + return stack->getDisplay(); + } - public: - const uint8_t identifier; - bool alive; + private: + modm::ViewStack* stack; }; } diff --git a/src/modm/ui/menu/choice_menu.hpp b/src/modm/ui/menu/choice_menu.hpp index b1ab6e73f5..20c3d5ff13 100644 --- a/src/modm/ui/menu/choice_menu.hpp +++ b/src/modm/ui/menu/choice_menu.hpp @@ -2,6 +2,7 @@ * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski * Copyright (c) 2015, Niklas Hauser + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -37,13 +38,14 @@ namespace modm{ * \ingroup modm_ui_menu * */ - class ChoiceMenu: public AbstractMenu + template > + class ChoiceMenu : public AbstractMenu { public: - ChoiceMenu(modm::ViewStack* stack, uint8_t identifier); + ChoiceMenu(modm::ViewStack* stack, uint8_t identifier); - ChoiceMenu(modm::ViewStack* stack, uint8_t identifier, const char* title); + ChoiceMenu(modm::ViewStack* stack, uint8_t identifier, const char* title); /** * @brief addEntry a new entry to the ChoiceMenu @@ -112,4 +114,6 @@ namespace modm{ }; } +#include "choice_menu_impl.hpp" + #endif /* CHOICE_MENU_HPP*/ diff --git a/src/modm/ui/menu/choice_menu.cpp b/src/modm/ui/menu/choice_menu_impl.hpp similarity index 72% rename from src/modm/ui/menu/choice_menu.cpp rename to src/modm/ui/menu/choice_menu_impl.hpp index d8cb4a192c..31e886d604 100644 --- a/src/modm/ui/menu/choice_menu.cpp +++ b/src/modm/ui/menu/choice_menu_impl.hpp @@ -2,6 +2,7 @@ * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski * Copyright (c) 2015, Niklas Hauser + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -11,11 +12,15 @@ */ // ---------------------------------------------------------------------------- -#include "choice_menu.hpp" +#ifndef CHOICE_MENU_HPP +# error "Don't include this file directly, use choice_menu.hpp instead!" +#endif +#include "abstract_view.hpp" -modm::ChoiceMenu::ChoiceMenu(modm::ViewStack* stack, uint8_t identifier) : - modm::AbstractMenu(stack, identifier), +template +modm::ChoiceMenu::ChoiceMenu(modm::ViewStack* stack, uint8_t identifier) : + modm::AbstractMenu(stack, identifier), display_update_time(500), timer(display_update_time), buttonAction(false), @@ -23,11 +28,12 @@ modm::ChoiceMenu::ChoiceMenu(modm::ViewStack* stack, uint8_t identifier) : homePosition(0), position(0) { - this->maximalDrawnEntrys = (getViewStack()->getDisplay().getHeight()- 16) / 8 ; + this->maximalDrawnEntrys = (this->getViewStack()->getDisplay().getHeight()- 16) / 8 ; } -modm::ChoiceMenu::ChoiceMenu(modm::ViewStack* stack, uint8_t identifier, const char* title) : - modm::AbstractMenu(stack, identifier), +template +modm::ChoiceMenu::ChoiceMenu(modm::ViewStack* stack, uint8_t identifier, const char* title) : + modm::AbstractMenu(stack, identifier), display_update_time(500), timer(display_update_time), buttonAction(false), @@ -35,19 +41,19 @@ modm::ChoiceMenu::ChoiceMenu(modm::ViewStack* stack, uint8_t identifier, const c homePosition(0), position(0) { - this->maximalDrawnEntrys = (getViewStack()->getDisplay().getHeight()- 16) / 8 ; + this->maximalDrawnEntrys = (this->getViewStack()->getDisplay().getHeight()- 16) / 8 ; } -void -modm::ChoiceMenu::addEntry(const char* text, bool *valuePtr, bool defaultValue) +template void +modm::ChoiceMenu::addEntry(const char* text, bool *valuePtr, bool defaultValue) { - static uint16_t availableSpace = (getViewStack()->getDisplay().getWidth()-16)/6-6; + static uint16_t availableSpace = (this->getViewStack()->getDisplay().getWidth()-16)/6-6; modm::ChoiceMenuEntry entry(text, availableSpace, valuePtr, defaultValue); this->entries.append(entry); } -void -modm::ChoiceMenu::initialise() +template void +modm::ChoiceMenu::initialise() { EntryList::iterator iter = this->entries.begin(); for(; iter!= this->entries.end(); ++iter){ @@ -62,17 +68,16 @@ modm::ChoiceMenu::initialise() } } -void -modm::ChoiceMenu::setTitle(const char* text) +template void +modm::ChoiceMenu::setTitle(const char* text) { this->title = text; } - -void -modm::ChoiceMenu::draw() +template void +modm::ChoiceMenu::draw() { - modm::ColorGraphicDisplay* display = &getViewStack()->getDisplay(); + modm::GraphicDisplay* display = &this->getViewStack()->getDisplay(); display->clear(); display->setCursor(0,2); (*display) << this->title; @@ -115,8 +120,8 @@ modm::ChoiceMenu::draw() // TODO wenn möglich pfeil nach oben und nach unten einfügen } -bool -modm::ChoiceMenu::hasChanged() +template bool +modm::ChoiceMenu::hasChanged() { if (timer.execute() || this->buttonAction) { @@ -130,9 +135,8 @@ modm::ChoiceMenu::hasChanged() } } - -void -modm::ChoiceMenu::shortButtonPress(modm::MenuButtons::Button button) +template void +modm::ChoiceMenu::shortButtonPress(modm::MenuButtons::Button button) { switch(button) { diff --git a/src/modm/ui/menu/communicating_view.hpp b/src/modm/ui/menu/communicating_view.hpp index 4201321b7f..ad88a61217 100644 --- a/src/modm/ui/menu/communicating_view.hpp +++ b/src/modm/ui/menu/communicating_view.hpp @@ -5,6 +5,7 @@ * Copyright (c) 2012-2013, 2017-2018, Niklas Hauser * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -24,18 +25,19 @@ namespace modm { /// @ingroup modm_ui_menu + template > class CommunicatingView : public xpcc::Communicatable { public: - CommunicatingView(modm::CommunicatingViewStack* /*stack*/) + CommunicatingView(modm::CommunicatingViewStack* /*stack*/) { } protected: - inline modm::CommunicatingViewStack* - getCommunicatingViewStack(modm::ViewStack* viewStack) + inline modm::CommunicatingViewStack* + getCommunicatingViewStack(modm::ViewStack* viewStack) { - return static_cast(viewStack); + return static_cast*>(viewStack); } }; } diff --git a/src/modm/ui/menu/communicating_view_stack.hpp b/src/modm/ui/menu/communicating_view_stack.hpp index 77a6933266..dd4507ca76 100644 --- a/src/modm/ui/menu/communicating_view_stack.hpp +++ b/src/modm/ui/menu/communicating_view_stack.hpp @@ -6,6 +6,7 @@ * Copyright (c) 2012-2013, 2017-2018, Niklas Hauser * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -26,11 +27,12 @@ namespace modm { /// @ingroup modm_ui_menu - class CommunicatingViewStack : public ViewStack + template > + class CommunicatingViewStack : public ViewStack { public: CommunicatingViewStack(modm::GraphicDisplay* display, xpcc::Communicator* communicator) : - ViewStack(display), + ViewStack(display), communicator(communicator) { } diff --git a/src/modm/ui/menu/iabstract_view.hpp b/src/modm/ui/menu/iabstract_view.hpp new file mode 100644 index 0000000000..dccaf210ca --- /dev/null +++ b/src/modm/ui/menu/iabstract_view.hpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020, Matthew Arnold + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#ifndef MODM_IABSTRACT_VIEW_HPP +#define MODM_IABSTRACT_VIEW_HPP + +#include + +#include "menu_buttons.hpp" + +namespace modm +{ + // forward declaration + template + class ViewStack; + + class IAbstractView + { + public: + template + friend class ViewStack; + + /** + * @param identifier can be used to determine which screen is the currently + * displayed on the graphicDisplay + */ + IAbstractView(uint8_t identifier) : + identifier(identifier), alive(true) + { + } + + virtual ~IAbstractView() = default; + + /** + * @brief update The update function of the top most display gets called + * as often as possible. Only the update of the top view in each + * ViewStack gets called. + */ + virtual void + update() + { + // nothing to be done + } + + /** + * @brief hasChanged indicates the current displayed view has changed. + * This function prevents unnecessary drawing of the display + * @return if true the display has to be redrawn. + */ + virtual bool + hasChanged() = 0; + + /** + * @brief draw determine the output on the Graphic Display + */ + virtual void + draw() = 0; + + + /** + * @brief shortButtonPress handle the action for the pressed button + */ + virtual void + shortButtonPress(modm::MenuButtons::Button /*button*/) + { + // nothing to be done + } + + /** + * @brief isAlive tells the ViewStack if it should remove this screen. + * @return + */ + bool + isAlive() const + { + return this->alive; + } + + /** + * @brief remove the view from the screen. The viewStack handles the deletion. + */ + void + remove() + { + this->alive = false; + } + + /** + * @brief getIdentifier of the view. + */ + inline uint8_t getIdentifier(){ + return this->identifier; + } + + public: + + /** + * @brief onRemove will be called right before the view gets deleted, + * can be reimplemented to reset external data. + */ + virtual void + onRemove() + { + // nothing to be done here + } + + private: + const uint8_t identifier; + bool alive; + }; +} + +#endif // MODM_IABSTRACT_VIEW_HPP diff --git a/src/modm/ui/menu/menu_entry_callback.hpp b/src/modm/ui/menu/menu_entry_callback.hpp index e5592aa961..c2307b5b1b 100644 --- a/src/modm/ui/menu/menu_entry_callback.hpp +++ b/src/modm/ui/menu/menu_entry_callback.hpp @@ -5,6 +5,7 @@ * Copyright (c) 2012, Sascha Schade * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -22,14 +23,15 @@ namespace modm { /// @ingroup modm_ui_menu + template > class MenuEntryCallback { public: - typedef void (modm::AbstractMenu::*Function)(); + typedef void (modm::AbstractMenu::*Function)(); template MenuEntryCallback(M *menu, void (M::*function)()) : - menu(reinterpret_cast(menu)), + menu(reinterpret_cast *>(menu)), function(reinterpret_cast(function)) { } @@ -41,7 +43,7 @@ namespace modm } protected: - modm::AbstractMenu * const menu; + modm::AbstractMenu * const menu; Function const function; }; } diff --git a/src/modm/ui/menu/scrollable_text.cpp b/src/modm/ui/menu/scrollable_text.cpp index 72b35221ee..ded7621196 100644 --- a/src/modm/ui/menu/scrollable_text.cpp +++ b/src/modm/ui/menu/scrollable_text.cpp @@ -84,7 +84,7 @@ modm::ScrollableText::getText() if(this->needsScrolling()) { if(!this->isPaused()) - { + { for(uint16_t i = 0; ispace; ++i) { if( (i+this->startPosition) < this->length) @@ -126,5 +126,4 @@ modm::ScrollableText::setToStart() } this->print[space]='\0'; } - } diff --git a/src/modm/ui/menu/standard_menu.hpp b/src/modm/ui/menu/standard_menu.hpp index c7c9e92e40..5a8d426904 100644 --- a/src/modm/ui/menu/standard_menu.hpp +++ b/src/modm/ui/menu/standard_menu.hpp @@ -6,6 +6,7 @@ * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski * Copyright (c) 2015, Niklas Hauser + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -34,6 +35,7 @@ namespace modm * \ingroup modm_ui_menu * \author Thorsten Lajewski */ + template > struct MenuEntry { /** @@ -42,10 +44,10 @@ namespace modm * @param space, available to display menu entry in number of letters * @param func callback, which is called when entry is chosen */ - MenuEntry(const char* text, uint16_t space, MenuEntryCallback func); + MenuEntry(const char* text, uint16_t space, MenuEntryCallback func); ScrollableText text; - MenuEntryCallback callback; + MenuEntryCallback callback; }; /** @@ -61,21 +63,22 @@ namespace modm * \author Thorsten Lajewski */ - class StandardMenu : public AbstractMenu + template > + class StandardMenu : public AbstractMenu { public: - StandardMenu(modm::ViewStack* stack, uint8_t identifier); + StandardMenu(modm::ViewStack* stack, uint8_t identifier); - virtual ~StandardMenu() = 0; + virtual ~StandardMenu() {} - StandardMenu(modm::ViewStack* stack, uint8_t identifier, const char* title); + StandardMenu(modm::ViewStack* stack, uint8_t identifier, const char* title); /** * @brief addEntry adds a new option to the displayed list */ void - addEntry(const char* text, MenuEntryCallback func); + addEntry(const char* text, MenuEntryCallback func); /** * @brief setTitle set the title of the menu displayed on top of the list @@ -136,10 +139,14 @@ namespace modm protected: - typedef modm::DoublyLinkedList EntryList; - EntryList entries; + template + using EntryList = modm::DoublyLinkedList >; + + EntryList entries; }; } +#include "standard_menu_impl.hpp" + #endif // MODM_STANDARD_MENU_HPP diff --git a/src/modm/ui/menu/standard_menu.cpp b/src/modm/ui/menu/standard_menu_impl.hpp similarity index 61% rename from src/modm/ui/menu/standard_menu.cpp rename to src/modm/ui/menu/standard_menu_impl.hpp index 892f075a7b..f49bbfe10f 100644 --- a/src/modm/ui/menu/standard_menu.cpp +++ b/src/modm/ui/menu/standard_menu_impl.hpp @@ -2,6 +2,7 @@ * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski * Copyright (c) 2015, Niklas Hauser + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -11,16 +12,20 @@ */ // ---------------------------------------------------------------------------- -#include "standard_menu.hpp" +#ifndef MODM_STANDARD_MENU_HPP +# error "Don't include this file directly, use standard_menu.hpp instead!" +#endif -modm::MenuEntry::MenuEntry(const char* text, uint16_t space, MenuEntryCallback func): +template +modm::MenuEntry::MenuEntry(const char* text, uint16_t space, MenuEntryCallback func): text(text, space), callback(func) { } -modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier) : - modm::AbstractMenu(stack, identifier), +template +modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier) : + modm::AbstractMenu(stack, identifier), display_update_time(500), timer(std::chrono::milliseconds(display_update_time)), buttonAction(false), @@ -28,11 +33,12 @@ modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier) : homePosition(0), position(0) { - this->maximalDrawnEntrys = (getViewStack()->getDisplay().getHeight()- 16) / 8 ; + this->maximalDrawnEntrys = (this->getViewStack()->getDisplay().getHeight()- 16) / 8 ; } -modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier, const char* title) : - modm::AbstractMenu(stack, identifier), +template +modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier, const char* title) : + modm::AbstractMenu(stack, identifier), display_update_time(500), timer(std::chrono::milliseconds(display_update_time)), buttonAction(false), @@ -40,38 +46,34 @@ modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier, con homePosition(0), position(0) { - this->maximalDrawnEntrys = (getViewStack()->getDisplay().getHeight()- 16) / 8 ; + this->maximalDrawnEntrys = (this->getViewStack()->getDisplay().getHeight()- 16) / 8 ; } -modm::StandardMenu::~StandardMenu() +template void +modm::StandardMenu::addEntry(const char* text, MenuEntryCallback func) { -} - -void -modm::StandardMenu::addEntry(const char* text, MenuEntryCallback func) -{ - modm::MenuEntry entry(text, (getViewStack()->getDisplay().getWidth()-16)/6, func); + modm::MenuEntry entry(text, (this->getViewStack()->getDisplay().getWidth()-16)/6, func); this->entries.append(entry); } -void -modm::StandardMenu::setTitle(const char* text) +template void +modm::StandardMenu::setTitle(const char* text) { this->title = text; } -void -modm::StandardMenu::draw() +template void +modm::StandardMenu::draw() { - modm::ColorGraphicDisplay* display = &getViewStack()->getDisplay(); + typename modm::GraphicDisplay* display = &this->getViewStack()->getDisplay(); display->clear(); display->setCursor(0,2); (*display) << this->title; display->drawLine(0, 10, display->getWidth(), 10); uint8_t i, count = this->entries.getSize(); - EntryList::iterator iter = this->entries.begin(); + typename EntryList::iterator iter = this->entries.begin(); for(uint8_t j=0; jhomePosition; ++j) { @@ -98,8 +100,8 @@ modm::StandardMenu::draw() // todo add file up and / or down if some entrys are not displayed on screen } -bool -modm::StandardMenu::hasChanged() +template bool +modm::StandardMenu::hasChanged() { if (timer.execute() || this->buttonAction) { @@ -113,14 +115,14 @@ modm::StandardMenu::hasChanged() } } -void -modm::StandardMenu::selectedEntryFunction(uint8_t /*selected*/) +template void +modm::StandardMenu::selectedEntryFunction(uint8_t /*selected*/) { } -void -modm::StandardMenu::shortButtonPress(modm::MenuButtons::Button button) +template void +modm::StandardMenu::shortButtonPress(modm::MenuButtons::Button button) { switch(button) { @@ -128,7 +130,7 @@ modm::StandardMenu::shortButtonPress(modm::MenuButtons::Button button) { if (this->position + 1U < this->entries.getSize()) { - EntryList::iterator iter = this->entries.begin(); + typename EntryList::iterator iter = this->entries.begin(); for (uint8_t j=0; jposition; ++j) { @@ -159,7 +161,7 @@ modm::StandardMenu::shortButtonPress(modm::MenuButtons::Button button) { if (this->position > 0) { - EntryList::iterator iter = this->entries.begin(); + typename EntryList::iterator iter = this->entries.begin(); for (uint8_t j = 0; j < this->position; ++j) { @@ -198,7 +200,7 @@ modm::StandardMenu::shortButtonPress(modm::MenuButtons::Button button) } case modm::MenuButtons::RIGHT: { - EntryList::iterator iter = this->entries.begin(); + typename EntryList::iterator iter = this->entries.begin(); for (uint8_t j = 0; j < this->position; ++j) { diff --git a/src/modm/ui/menu/view_stack.cpp b/src/modm/ui/menu/view_stack.cpp deleted file mode 100644 index f133ecffbe..0000000000 --- a/src/modm/ui/menu/view_stack.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2011, Fabian Greif - * Copyright (c) 2010-2011, 2013, Georgi Grinshpun - * Copyright (c) 2013, Kevin Läufer - * Copyright (c) 2013, Thorsten Lajewski - * Copyright (c) 2014, Sascha Schade - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "view_stack.hpp" - -// ---------------------------------------------------------------------------- -modm::ViewStack::ViewStack(modm::ColorGraphicDisplay* display) : - display(display) -{ -} - -// ---------------------------------------------------------------------------- -modm::ViewStack::~ViewStack() -{ -} - -// ---------------------------------------------------------------------------- -void -modm::ViewStack::pop() -{ - modm::AbstractView *topElement = this->stack.get(); - this->stack.pop(); - - delete topElement; -} - -// ---------------------------------------------------------------------------- -void -modm::ViewStack::update() -{ - modm::AbstractView* top = this->get(); - - if (top == NULL) - return; - - top->update(); - if (top->isAlive()) - { - if (top->hasChanged()) - { - top->draw(); - this->display->update(); - } - } - else - { - // Remove old view - top->onRemove(); - this->pop(); - - // Get new screen - top = this->get(); - top->update(); - this->display->clear(); - top->draw(); - this->display->update(); - } -} - -// ---------------------------------------------------------------------------- -void -modm::ViewStack::shortButtonPress(modm::MenuButtons::Button button) -{ - modm::AbstractView* top = this->get(); - top->shortButtonPress(button); -} diff --git a/src/modm/ui/menu/view_stack.hpp b/src/modm/ui/menu/view_stack.hpp index 0ed1f04ad4..4697a1f63f 100644 --- a/src/modm/ui/menu/view_stack.hpp +++ b/src/modm/ui/menu/view_stack.hpp @@ -5,6 +5,7 @@ * Copyright (c) 2013, Kevin Läufer * Copyright (c) 2013, Thorsten Lajewski * Copyright (c) 2014, Sascha Schade + * Copyright (c) 2020, Matthew Arnold * * This file is part of the modm project. * @@ -36,19 +37,26 @@ namespace modm * \author Thorsten Lajewski */ + template > class ViewStack { public: - ViewStack(modm::GraphicDisplay* display); + ViewStack(modm::GraphicDisplay* display, const Allocator allocator = Allocator()) : + display(display), + allocator(allocator) + { + } - virtual ~ViewStack(); + virtual ~ViewStack() + { + } /** * @brief get the top view from the stack * @return pointer to view from stack */ - inline modm::AbstractView* + inline modm::AbstractView* get() { return this->stack.get(); @@ -62,11 +70,11 @@ namespace modm * @param view next displayed view */ inline void - push(modm::AbstractView* view) + push(modm::AbstractView* view) { this->stack.push(view); this->getDisplay().clear(); - modm::AbstractView* top = this->get(); + modm::AbstractView* top = this->get(); top->draw(); this->display->update(); } @@ -86,10 +94,46 @@ namespace modm */ void - pop(); + pop() + { + modm::AbstractView *topElement = this->stack.get(); + this->stack.pop(); + + allocator.destroy(topElement); + allocator.deallocate(topElement); + } virtual void - update(); + update() + { + modm::AbstractView* top = this->get(); + + if (top == NULL) + return; + + top->update(); + if (top->isAlive()) + { + if (top->hasChanged()) + { + top->draw(); + this->display->update(); + } + } + else + { + // Remove old view + top->onRemove(); + this->pop(); + + // Get new screen + top = this->get(); + top->update(); + this->display->clear(); + top->draw(); + this->display->update(); + } + } /** * @brief shortButtonPress pass the button press to the current top view @@ -97,11 +141,16 @@ namespace modm */ void - shortButtonPress(modm::MenuButtons::Button button); + shortButtonPress(modm::MenuButtons::Button button) + { + modm::AbstractView* top = this->get(); + top->shortButtonPress(button); + } protected: modm::GraphicDisplay* display; - modm::Stack< modm::AbstractView* , modm::LinkedList< modm::AbstractView* > > stack; + modm::Stack< modm::AbstractView* , modm::LinkedList< modm::AbstractView* > > stack; + Allocator allocator; }; } From beb03f347d9708d75919fa7556b5ef676110d95d Mon Sep 17 00:00:00 2001 From: Matthew Arnold Date: Sun, 5 Feb 2023 21:06:27 +0100 Subject: [PATCH 4/4] [ui] Remove dependency of :ui:gui on :ui:menu --- src/modm/ui/gui/module.lb | 4 +-- src/modm/ui/gui/view.cpp | 11 +++++++-- src/modm/ui/gui/view.hpp | 45 +++++++++++++++++++++++++++++++--- src/modm/ui/gui/view_stack.cpp | 2 +- src/modm/ui/gui/view_stack.hpp | 13 ++++++++-- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/modm/ui/gui/module.lb b/src/modm/ui/gui/module.lb index 1dde1231ec..ca9c614bcf 100644 --- a/src/modm/ui/gui/module.lb +++ b/src/modm/ui/gui/module.lb @@ -23,9 +23,7 @@ def prepare(module, options): ":container", ":debug", ":processing:timer", - ":ui:display", - ":ui:gui", - ":ui:menu") + ":ui:display") return True def build(env): diff --git a/src/modm/ui/gui/view.cpp b/src/modm/ui/gui/view.cpp index 75c5389d8c..1fd4c505f1 100644 --- a/src/modm/ui/gui/view.cpp +++ b/src/modm/ui/gui/view.cpp @@ -18,9 +18,10 @@ // ---------------------------------------------------------------------------- modm::gui::View::View(modm::gui::GuiViewStack* stack, uint8_t identifier, modm::gui::Dimension dimension) : - AbstractView(stack, identifier), stack(stack), - dimension(dimension) + dimension(dimension), + identifier(identifier), + alive(true) { this->display().clear(); } @@ -161,3 +162,9 @@ void modm::gui::View::markDrawn() (*iter)->markDrawn(); } } + +modm::ColorGraphicDisplay& +modm::gui::View::display() +{ + return stack->getDisplay(); +} diff --git a/src/modm/ui/gui/view.hpp b/src/modm/ui/gui/view.hpp index 69d02fcca3..a06a3bf2cd 100644 --- a/src/modm/ui/gui/view.hpp +++ b/src/modm/ui/gui/view.hpp @@ -24,8 +24,6 @@ #include "widgets/widget.hpp" #include "colorpalette.hpp" -#include - namespace modm { @@ -41,7 +39,7 @@ class GuiViewStack; * @ingroup modm_ui_gui * @author Thorsten Lajewski */ -class View : public modm::AbstractView +class View { friend class GuiViewStack; @@ -61,6 +59,14 @@ class View : public modm::AbstractView virtual void update(); + /** + * @brief hasChanged indicates the current displayed view has changed. + * This function prevents unnecessary drawing of the display + * @return if true the display has to be redrawn. + */ + virtual bool + hasChanged() = 0; + virtual void preUpdate() { @@ -79,10 +85,30 @@ class View : public modm::AbstractView bool pack(Widget *w, const modm::glcd::Point &coord); + /** + * @brief isAlive tells the ViewStack if it should remove this screen. + * @return + */ + bool + isAlive() const + { + return this->alive; + } + /// Remove the view from the screen. The viewStack handles the deletion. void remove(); + /** + * @brief onRemove will be called right before the view gets deleted, + * can be reimplemented to reset external data. + */ + virtual void + onRemove() + { + // nothing to be done here + } + /// Set color palette for every contained widget void setColorPalette(ColorPalette& cp); @@ -105,12 +131,25 @@ class View : public modm::AbstractView return stack; } + modm::ColorGraphicDisplay& + display(); + + /** + * @brief getIdentifier of the view. + */ + inline uint8_t getIdentifier(){ + return this->identifier; + } + protected: modm::gui::GuiViewStack* stack; Dimension dimension; WidgetContainer widgets; modm::gui::ColorPalette colorpalette; + + const uint8_t identifier; + bool alive; }; } // namespace gui diff --git a/src/modm/ui/gui/view_stack.cpp b/src/modm/ui/gui/view_stack.cpp index de116a93fc..a5e1b614d3 100644 --- a/src/modm/ui/gui/view_stack.cpp +++ b/src/modm/ui/gui/view_stack.cpp @@ -20,7 +20,7 @@ // ---------------------------------------------------------------------------- modm::gui::GuiViewStack::GuiViewStack(modm::ColorGraphicDisplay* display, modm::gui::inputQueue* queue) : - ViewStack(display), + display(display), input_queue(queue) { } diff --git a/src/modm/ui/gui/view_stack.hpp b/src/modm/ui/gui/view_stack.hpp index 308ce0085d..edff70b95d 100644 --- a/src/modm/ui/gui/view_stack.hpp +++ b/src/modm/ui/gui/view_stack.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include "view.hpp" #include "types.hpp" @@ -41,7 +40,7 @@ namespace gui * @ingroup modm_ui_gui * @author Thorsten Lajewski */ -class GuiViewStack : public modm::ViewStack +class GuiViewStack { public: GuiViewStack(modm::ColorGraphicDisplay* display, modm::gui::inputQueue* queue); @@ -84,7 +83,17 @@ class GuiViewStack : public modm::ViewStack virtual void update(); + /** + * @brief getDisplay access underlying GraphicDisplay + */ + inline modm::ColorGraphicDisplay& + getDisplay() + { + return *this->display; + } + private: + modm::ColorGraphicDisplay *display; modm::Stack< modm::gui::View* , modm::LinkedList< modm::gui::View* > > stack; modm::gui::inputQueue *input_queue; };