Skip to content

Commit

Permalink
Feature/refactor items (#221)
Browse files Browse the repository at this point in the history
I tried to rename methods from up/down/left/right into specific for
item, something like more 'domain specific':
- `changeScreen` for `ItemBack` and `ItemSubMenu` insted of `enter`.
- `commitCharEdit` for `ItemInputCharset` instead of `enter`.


![image](https://github.com/user-attachments/assets/a91cdd94-7092-4543-88cd-a3fde4a5a19c)

Also signature of `process` simplified and instead of `Context` pass
only `LcdMenu` and char.
All required dependencies (display and current screen) can be obtained
from menu.

Also true/false result for process method is controlled inside process
method. Also simplified repeated if's

Also need somehow separate value update and draw.

---------

Co-authored-by: Thomas Forntoh <[email protected]>
  • Loading branch information
ShishkinDmitriy and forntoh authored Sep 21, 2024
1 parent 6995f6e commit 830fbf4
Show file tree
Hide file tree
Showing 15 changed files with 475 additions and 391 deletions.
120 changes: 80 additions & 40 deletions docs/classes.puml
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,97 @@
' https://www.plantuml.com/plantuml/uml/

hide empty members
left to right direction

class InputInterface {
virtual void observe()
}

class DisplayInterface {
#uint8_t maxCols
#uint8_t maxRows
#uint8_t cursorRow
#uint8_t blinkerPosition
+bool isEditModeEnabled
+virtual void begin()
+uint8_t getMaxRows() const
+uint8_t getMaxCols() const
+virtual void clear()
+virtual void setBacklight(bool enabled)
+virtual void drawItem(uint8_t row, const char* text)
+virtual void drawItem(uint8_t row, const char* text, char separator, char* value)
+virtual void clearCursor()
+virtual void drawCursor()
+virtual void moveCursor(uint8_t newCursorRow)
+void setEditModeEnabled(bool enabled)
+bool getEditModeEnabled()
+uint8_t getCursorRow() const
+virtual void clearBlinker()
+virtual void drawBlinker()
+virtual void resetBlinker(uint8_t blinkerPosition)
+uint8_t getBlinkerPosition() const
+virtual bool drawChar(char c)
+virtual void clearUpIndicator()
+virtual void drawUpIndicator()
+virtual void clearDownIndicator()
+virtual void drawDownIndicator()
+virtual void restartTimer()
}

class LcdMenu {
+virtual bool process(char c)
-bool enabled
+DisplayInterface* getDisplay()
+MenuScreen* getScreen()
+void setScreen(MenuScreen* screen)
+uint8_t getCursor()
+MenuItem* getItemAt(uint8_t position)
+void setCursor(uint8_t cursor)
+bool process(const unsigned char c)
+void reset()
+void hide()
+void show()
+void refresh()

}

class MenuScreen {
#virtual bool process(Context context)
#virtual bool up()
#virtual bool down()
#virtual bool back()
}
-uint8_t cursor
-uint8_t view
+void setParent(MenuScreen* parent)
+MenuItem* operator[](const uint8_t position)
+uint8_t getCursor()
+MenuItem* getItemAt(uint8_t position)
#void setCursor(DisplayInterface* display, uint8_t position)
#bool process(LcdMenu* menu, const unsigned char command)
#void draw(DisplayInterface* display)
#bool up(DisplayInterface* display)
#bool down(DisplayInterface* display)
#bool back(LcdMenu* menu)
#uint8_t itemsCount()

struct MenuItem::Context {
LcdMenu* menu;
DisplayInterface* display;
const unsigned char command;
}

class MenuItem {
#virtual bool process(Context context)
#const char* text
+const char* getText()
+void setText(const char* text)
#virtual bool process(LcdMenu* menu, const unsigned char command)
#const void draw(DisplayInterface* display)
#virtual void draw(DisplayInterface* display, uint8_t row)
}

class ItemCommand {
#bool process(Context context) override
#bool enter(Context context)
}
InputInterface -r-> "1" LcdMenu : menu
LcdMenu -r-> "1" DisplayInterface : display
LcdMenu -d-> "1" MenuScreen : screen
MenuScreen -d-> "1..*" MenuItem : items
MenuScreen --> "0..1" MenuScreen : parent

class ItemList {
#bool process(Context context) override
#bool up(Context context)
#bool down(Context context)
#bool enter(Context context)
#bool back(Context context)
}
LcdMenu::process .. MenuScreen::process
LcdMenu::getCursor .. MenuScreen::getCursor
LcdMenu::setCursor .. MenuScreen::setCursor
LcdMenu::getItemAt .. MenuScreen::getItemAt

class ItemInput {
#bool process(Context context) override
#bool up(Context context)
#bool down(Context context)
#bool enter(Context context)
#bool back(Context context)
#bool left(Context context)
#bool right(Context context)
#bool backspace(Context context)
#bool typeChar(Context context)
#bool clear(Context context)
}
MenuScreen::process .. MenuItem::process
MenuScreen::draw .. MenuItem::draw

LcdMenu -r-> MenuScreen
MenuScreen -r-> MenuItem
ItemCommand -u-|> MenuItem
ItemList -u-|> MenuItem
ItemInput -u-|> MenuItem
@enduml
@enduml
93 changes: 93 additions & 0 deletions docs/items.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
@startuml
' https://www.plantuml.com/plantuml/uml/

hide empty members
left to right direction

class MenuItem {
#const char* text
+const char* getText()
+void setText(const char* text)
#virtual bool process(LcdMenu* menu, const unsigned char command)
#const void draw(DisplayInterface* display)
#virtual void draw(DisplayInterface* display, uint8_t row)
}

class ItemBack {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void changeScreen(LcdMenu* menu)
}

class ItemSubMenu {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void changeScreen(LcdMenu* menu)
}

class ItemToggle {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void toggle(DisplayInterface* display)
}

class ItemCommand {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void executeCommand()
}

class ItemInput {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void up(DisplayInterface* display)
#void down(DisplayInterface* display)
#void enter(DisplayInterface* display)
#void back(DisplayInterface* display)
#void left(DisplayInterface* display)
#void right(DisplayInterface* display)
#void backspace(DisplayInterface* display)
#void typeChar(DisplayInterface* display, const unsigned char command)
#void clear(DisplayInterface* display)
}

class ItemInputCharset {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void initCharEdit()
#void abortCharEdit(DisplayInterface* display)
#void commitCharEdit(DisplayInterface* display)
#void showNextChar(DisplayInterface* display)
#void showPreviousChar(DisplayInterface* display)
}

class ItemList {
#bool process(LcdMenu* menu, const unsigned char command) override
..
#void selectPrevious(DisplayInterface* display)
#void selectNext(DisplayInterface* display)
}

class ItemProgress {
#bool process(LcdMenu* menu, const unsigned char command) override
..
+void increment()
+void decrement()
}

class EditMode as "???" {
}

note bottom of EditMode : Someone who holds edit mode

ItemBack -u-|> MenuItem
ItemSubMenu -u-|> MenuItem
ItemToggle -u-|> MenuItem
ItemCommand -u-|> MenuItem
EditMode -u-|> MenuItem
ItemList -u-|> EditMode
ItemProgress -u-|> EditMode
ItemInput -u-|> EditMode
ItemInputCharset -u-|> ItemInput

@enduml
14 changes: 10 additions & 4 deletions src/ItemBack.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,18 @@ class ItemBack : public MenuItem {
ItemBack(const char* text = "..") : MenuItem(text) {}

protected:
bool process(Context& context) override {
switch (context.command) {
case ENTER: context.menu->process(BACK); return true;
default: return false;
bool process(LcdMenu* menu, const unsigned char command) override {
switch (command) {
case ENTER:
changeScreen(menu);
return true;
default:
return false;
}
}
void changeScreen(LcdMenu* menu) {
menu->process(BACK);
}
};

#define ITEM_BACK(...) (new ItemBack(__VA_ARGS__))
Expand Down
16 changes: 9 additions & 7 deletions src/ItemCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,21 @@ class ItemCommand : public MenuItem {
void setCallBack(fptr callback) { this->callback = callback; };

protected:
bool process(Context& context) override {
switch (context.command) {
case ENTER: return enter(context);
default: return false;
bool process(LcdMenu* menu, const unsigned char command) override {
switch (command) {
case ENTER:
executeCommand();
return true;
default:
return false;
}
}
bool enter(Context& context) {
void executeCommand() {
if (callback != NULL) {
callback();
}
printLog(F("ItemCommand::enter"), text);
return true;
};
}
};

#define ITEM_COMMAND(...) (new ItemCommand(__VA_ARGS__))
Expand Down
Loading

0 comments on commit 830fbf4

Please sign in to comment.