From 4d5d1952e508cf7f5c513eaa5a9896cd1c02b827 Mon Sep 17 00:00:00 2001 From: MatthewMArnold <43590293+MatthewMArnold@users.noreply.github.com> Date: Wed, 2 Jun 2021 11:25:46 -0700 Subject: [PATCH] [menu] Add optional allocator for ui menu classes (#5) * [menu] Add optional allocator for ui menu classes, used for destroying AbstractViews * [menu] remove coupling between modm gui and modm menu view and menu This is because the gui stuff requires colored menus but the menu code should not have to have colored menus. This wouldn't be an issue if we could dynamic cast but on certain devices you can't do this. --- src/modm/ui/display/color_graphic_display.hpp | 2 - src/modm/ui/gui/view.cpp | 11 +- src/modm/ui/gui/view.hpp | 52 +++++++- src/modm/ui/gui/view_stack.cpp | 2 +- src/modm/ui/gui/view_stack.hpp | 24 +++- 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 | 8 +- src/modm/ui/menu/iabstract_view.hpp | 121 ++++++++++++++++++ src/modm/ui/menu/menu_entry_callback.hpp | 8 +- src/modm/ui/menu/module.lb | 3 +- 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 | 71 ++++++++-- 21 files changed, 392 insertions(+), 337 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/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/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..91a41f112a 100644 --- a/src/modm/ui/gui/view.hpp +++ b/src/modm/ui/gui/view.hpp @@ -41,7 +41,7 @@ class GuiViewStack; * @ingroup modm_ui_gui * @author Thorsten Lajewski */ -class View : public modm::AbstractView +class View { friend class GuiViewStack; @@ -61,6 +61,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() { @@ -75,14 +83,43 @@ class View : public modm::AbstractView virtual void draw(); + /** + * @brief shortButtonPress handle the action for the pressed button + */ + virtual void + shortButtonPress(modm::MenuButtons::Button /*button*/) + { + // nothing to be done + } + /// Add widget to view 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 +142,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..18c90e9c07 100644 --- a/src/modm/ui/gui/view_stack.hpp +++ b/src/modm/ui/gui/view_stack.hpp @@ -41,7 +41,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 +84,29 @@ class GuiViewStack : public modm::ViewStack virtual void update(); + /** + * @brief shortButtonPress pass the button press to the current top view + * @param button the pressed button + */ + + void + shortButtonPress(modm::MenuButtons::Button button) + { + modm::gui::View* top = this->get(); + top->shortButtonPress(button); + } + + /** + * @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; }; 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..78cafc0bac 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..e01eae6f30 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..a4882748c4 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..1a06a194f5 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 9f1c5cf7ed..f8d96fa1ef 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::ColorGraphicDisplay* display, xpcc::Communicator* communicator) : - ViewStack(display), + CommunicatingViewStack(modm::GraphicDisplay* display, xpcc::Communicator* communicator) : + 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..23b4d5959a 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/module.lb b/src/modm/ui/menu/module.lb index f729353585..75c4ec697e 100644 --- a/src/modm/ui/menu/module.lb +++ b/src/modm/ui/menu/module.lb @@ -39,7 +39,8 @@ def prepare(module, options): ":communication:xpcc", ":container", ":processing:timer", - ":ui:display") + ":ui:display", + ":utils") return True def build(env): 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..d92c791f05 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 188e884af8..c897c99ebe 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::ColorGraphicDisplay* 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(); } @@ -74,7 +82,7 @@ namespace modm /** * @brief getDisplay access underlying GraphicDisplay */ - inline modm::ColorGraphicDisplay& + inline modm::GraphicDisplay& getDisplay() { return *this->display; @@ -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::ColorGraphicDisplay* display; - modm::Stack< modm::AbstractView* , modm::LinkedList< modm::AbstractView* > > stack; + modm::GraphicDisplay* display; + modm::Stack< modm::AbstractView* , modm::LinkedList< modm::AbstractView* > > stack; + Allocator allocator; }; }