From bb76f97115aa642b60b89901cc5aa7237b2eab79 Mon Sep 17 00:00:00 2001 From: forntoh Date: Mon, 7 Oct 2024 11:07:47 +0000 Subject: [PATCH] deploy: 0700e626dafd1e4644b5ba509c11b5c35ea1be50 --- _images/custom-cursor.gif | Bin 0 -> 52802 bytes _images/no-arrows.png | Bin 0 -> 8104 bytes _images/no-cursor-no-arrows.webp | Bin 0 -> 7256 bytes _images/no-cursor.webp | Bin 0 -> 7756 bytes genindex.html | 281 +++++----- index.html | 5 + objects.inv | Bin 12589 -> 13280 bytes overview/control/button.html | 5 + overview/control/index.html | 5 + overview/control/keyboard.html | 5 + overview/control/rotary-encoder.html | 11 +- overview/getting-started.html | 53 +- overview/items/basic.html | 5 + overview/items/command.html | 5 + overview/items/index.html | 5 + overview/items/input-charset.html | 5 + overview/items/input.html | 5 + overview/items/list.html | 5 + overview/items/range.html | 5 + overview/items/submenu.html | 5 + overview/rendering/character-display.html | 427 +++++++++++++++ overview/rendering/index.html | 280 ++++++++++ reference/api/ItemBack.html | 5 + reference/api/ItemCommand.html | 5 + reference/api/ItemFloatRange.html | 5 + reference/api/ItemInput.html | 77 ++- reference/api/ItemInputCharset.html | 38 +- reference/api/ItemIntRange.html | 5 + reference/api/ItemList.html | 30 +- reference/api/ItemRangeBase.html | 18 +- reference/api/ItemSubMenu.html | 11 +- reference/api/ItemToggle.html | 24 +- reference/api/LcdMenu.html | 31 +- reference/api/MenuItem.html | 33 +- reference/api/MenuScreen.html | 65 ++- .../display/CharacterDisplayInterface.html | 316 +++++++++++ reference/api/display/DisplayInterface.html | 170 ++---- .../api/display/LiquidCrystalAdapter.html | 127 ++--- .../api/display/LiquidCrystal_I2CAdapter.html | 141 ++--- reference/api/display/index.html | 12 +- reference/api/index.html | 6 + reference/api/input/ButtonAdapter.html | 5 + reference/api/input/InputInterface.html | 5 + reference/api/input/KeyboardAdapter.html | 5 + reference/api/input/SimpleRotaryAdapter.html | 5 + reference/api/input/index.html | 5 + .../renderer/CharacterDisplayRenderer.html | 443 ++++++++++++++++ reference/api/renderer/MenuRenderer.html | 499 ++++++++++++++++++ reference/api/renderer/index.html | 266 ++++++++++ reference/changelog.html | 197 +++---- reference/faq.html | 5 + reference/migration/index.html | 72 ++- reference/migration/v3.x-v4.x.html | 5 + .../{v4.x-v5.x.html => v4.x.x-v5.0.0.html} | 21 +- reference/migration/v5.0.0-v5.1.x.html | 286 ++++++++++ reference/samples/Basic.html | 64 ++- reference/samples/ButtonAdapter.html | 95 ++-- .../samples/ButtonWithRotaryAdapter.html | 111 ++-- reference/samples/Callbacks.html | 81 +-- reference/samples/CharsetInput.html | 86 +-- reference/samples/InputRotary.html | 108 ++-- reference/samples/IntFloatValues.html | 94 ++-- reference/samples/ItemBack.html | 82 +-- reference/samples/KeyboardAdapter.html | 86 +-- reference/samples/List.html | 112 ++-- reference/samples/MenuTimeout.html | 75 +-- reference/samples/RTOS.html | 227 ++++---- reference/samples/SimpleInput.html | 80 +-- reference/samples/SimpleRotary.html | 99 ++-- reference/samples/SubMenu.html | 104 ++-- reference/samples/index.html | 11 +- reference/uml.html | 5 + search.html | 5 + searchindex.js | 2 +- 74 files changed, 4149 insertions(+), 1428 deletions(-) create mode 100644 _images/custom-cursor.gif create mode 100644 _images/no-arrows.png create mode 100644 _images/no-cursor-no-arrows.webp create mode 100644 _images/no-cursor.webp create mode 100644 overview/rendering/character-display.html create mode 100644 overview/rendering/index.html create mode 100644 reference/api/display/CharacterDisplayInterface.html create mode 100644 reference/api/renderer/CharacterDisplayRenderer.html create mode 100644 reference/api/renderer/MenuRenderer.html create mode 100644 reference/api/renderer/index.html rename reference/migration/{v4.x-v5.x.html => v4.x.x-v5.0.0.html} (95%) create mode 100644 reference/migration/v5.0.0-v5.1.x.html diff --git a/_images/custom-cursor.gif b/_images/custom-cursor.gif new file mode 100644 index 0000000000000000000000000000000000000000..820bc02eefb9abe6db71ff120f4b2598856cdffe GIT binary patch literal 52802 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 literal 0 HcmV?d00001 diff --git a/_images/no-arrows.png b/_images/no-arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..abc5b79d2917e79f909cc1517034577856bc045c GIT binary patch literal 8104 zcmd5>c|4R|-yhskDk@Ey$dW9PZIC1sMH0#qSz`u~-Pp~HHi|(gM3%}nwhYGFpfI*9 zS;tr=Bs)#k2IIX(_ubw7eBS5zynj8P_n+&`HFM^i^V`4Y_kD6*PisH>F?J9Lv|szm zB?AzM`5_3zB(R$q_~v!t3KAG(5tmI78g4EwcCH8zFkiq9?uf913-~%B?g-pLAl$vq zNlV)WI5^r%!Q5P=-P{q5?ye49ggz9i*ThYlY+8|E&~9%gj$GRw&l`7Qy$dk4CLA75a`!nq9M_8-w( zkzJOFrLI%a&Fi z`MV`9r^=2MJbJ?f0;Lt)xsL(Hr?S8ip_vDOXVX#O0byah?*f4?5P=WDzorPlfLHiF z;PL-?n!nmZ2~ zF7prNJaFJr-z}Ivnm!=hcJ~Hxy868^ZtVT)u<}z`!G{M7*r27&#>;)o9^eVb z{2Z?B7JMiGg9F1Kkp2QpYiYHIRqRxwgAfc@uc;iDU;BtL@#hp^0KWYLvh(8~5XP2G zM|TEqiSdhjIQQwT<;Go{u4dWU6+Xuf$(qnNuSCQp#$*(GexwRk2&y+XB^*%S4J}}S zm^YW5)Pp|SZ?T>fwWz2&v^jm3t%Z~BH`ht_wJxk)pX|Sh#7(wdXf>Mc7EVerU20$I zYrHiZRzpWk0+O|qR`bc6N*KS&I8iR#;`)KqB%Y*LIpfW;Y_az=+c^IaYoB26R;KA{ zpu~t@AB{#)`_Wk8HJP&gO?bB3VTAmxJ(APe_DD*kpZrBr|Fsbn zZEbB{vmG6HLZr>)UA{CisRa6bUv(YK?T@&3Z*8|?cz^iSn5;=Hj`i)&e(l`@q58bX zW0Y<>-Dp~GL)Z9zx%4C9L-Q(>?loF-zKT4sW+W<&3$grW&oSoS-_H9k41F7|Q(~<26jxBVL1sJNbv7}PbdxX;U|kW`&oGOjB;tEZhyPV#XM?7D3t4LOq3_CM{EQMbYPk zoBiCslC-0Qk?&Sw$Hr_qBpKdq(cIf3EG!or`@og3;yXWRjcij$Ij(G_>`a<>bd1ek zv`-ihDÐ2~|6^J;afO-tIKBF7`V}d&$)6i|GmP)5>Bu{64 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 literal 0 HcmV?d00001 diff --git a/_images/no-cursor-no-arrows.webp b/_images/no-cursor-no-arrows.webp new file mode 100644 index 0000000000000000000000000000000000000000..63ed2f2e5f992c77e2831489cd55b91e1d441651 GIT binary patch literal 7256 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 literal 0 HcmV?d00001 diff --git a/genindex.html b/genindex.html index c4b54c0e..25a1c794 100644 --- a/genindex.html +++ b/genindex.html @@ -148,6 +148,10 @@
  • Rotary Encoder Adapter
  • +
  • Rendering the menu +
  • Reference

    @@ -287,80 +292,82 @@

    C

  • C2_CSI_TERMINAL_MIN (C macro)
  • - - - - - -

    D

    - - + - + +
    + +

    D

    + + + @@ -677,26 +684,26 @@

    L

    +
  • +
  • Reference

    diff --git a/objects.inv b/objects.inv index e2ee4b3967185b5b5ebc640df1eb47e6e9e91ad3..57f9dabc4baae673d1792d148f07f65e65debb48 100644 GIT binary patch delta 13273 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 X_tmg@?c!&X{_SP^!216KtjY~9$0!%m delta 12577 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 Encoder Adapter +
  • +
  • Reference

    diff --git a/overview/control/index.html b/overview/control/index.html index dc204c37..8f9cc5b0 100644 --- a/overview/control/index.html +++ b/overview/control/index.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    diff --git a/overview/control/keyboard.html b/overview/control/keyboard.html index 3852335c..0c3d4bec 100644 --- a/overview/control/keyboard.html +++ b/overview/control/keyboard.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    diff --git a/overview/control/rotary-encoder.html b/overview/control/rotary-encoder.html index dab83008..8c17ac51 100644 --- a/overview/control/rotary-encoder.html +++ b/overview/control/rotary-encoder.html @@ -18,7 +18,7 @@ - + + + +
    + Skip to content +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +

    Character display renderer

    +

    The character display renderer is a simple renderer that displays the menu items on a character display. +It is a good choice if you are using a character display with your project.

    +

    The renderer supports the following features:

    +
      +
    • Displaying menu items on a character display

    • +
    • Truncating long menu items

    • +
    • Highlighting the selected menu item

    • +
    • Customizing the cursor character

    • +
    • Customizing the up and down arrow characters

    • +
    • Disabling the cursor and/arrows arrows

    • +
    +

    The renderer is easy to use and provides a number of options for customizing the display.

    +
    +

    How to use the character display renderer

    +

    To use the character display renderer, you need to create an instance of the CharacterDisplayRenderer class and pass it +to the LcdMenu class when you create it. Here is an example:

    +
    + +
    +
    #include <LcdMenu.h>
    +#include <LiquidCrystal_I2C.h>
    +#include <display/LiquidCrystal_I2CAdapter.h>
    +#include <renderer/CharacterDisplayRenderer.h>
    +
    +LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS);
    +LiquidCrystal_I2CAdapter lcdAdater(&lcd);
    +CharacterDisplayRenderer renderer(&lcdAdater, LCD_COLS, LCD_ROWS);
    +LcdMenu menu(renderer);
    +
    +
    +
    + +
    +
    #include <LcdMenu.h>
    +#include <LiquidCrystal.h>
    +#include <display/LiquidCrystalAdapter.h>
    +#include <renderer/CharacterDisplayRenderer.h>
    +
    +LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
    +LiquidCrystalAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS);
    +CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS);
    +LcdMenu menu(renderer);
    +
    +
    +
    +
    +

    Don’t forget to replace LCD_COLS and LCD_ROWS with the number of columns and rows on your display.

    +

    After you have created the renderer, you then have to call the begin() method on the renderer to initialize it.

    +
    void setup() {
    +    renderer.begin();
    +}
    +
    +
    +
    +
    +

    Customizing the character display renderer

    +

    The character display renderer provides a number of options for customizing the display. You can set the following options:

    +
      +
    • The cursor characters (normal and editing)

    • +
    • The up and down arrow characters

    • +
    • Whether to display the cursor and/or arrows

    • +
    +

    Here is an example of how to customize the renderer:

    +
    +

    Use custom cursor characters

    +

    You can set custom cursor characters to use when rendering the selected menu item.

    +
    CharacterDisplayRenderer renderer(
    +    new LiquidCrystal_I2CAdapter(&lcd),
    +    LCD_COLS,
    +    LCD_ROWS,
    +    0xA5,  // cursorChar
    +    0x5F   // editCursorChar
    +);
    +
    +
    +Custom cursor characters + +
    +

    Note

    +

    Please refer to the datasheet of your display to find the character codes for the custom cursor characters.

    +
    +
    +
    +

    Hide the arrows only

    +

    You may want to hide the up and down arrows if you don’t need them or want more space for rendering the menu items. +Set the up and down arrow characters to NULL to hide them.

    +
    CharacterDisplayRenderer renderer(
    +    &lcdAdapter,
    +    LCD_COLS,
    +    LCD_ROWS,
    +    0x7E,  // cursorChar
    +    0x7F,  // editCursorChar
    +    NULL,  // upArrow
    +    NULL   // downArrow
    +);
    +
    +
    +Hide the arrows + +
    +
    +

    Hide the cursor only

    +

    Set the cursor characters to 0 to hide the cursor.

    +
    CharacterDisplayRenderer renderer(
    +    &lcdAdapter,
    +    LCD_COLS,
    +    LCD_ROWS,
    +    0,  // cursorChar
    +    0   // editCursorChar
    +);
    +
    +
    +Hide the cursor + +
    +
    +

    Hide both the cursor and arrows

    +
    CharacterDisplayRenderer renderer(
    +    &lcdAdapter,
    +    LCD_COLS,
    +    LCD_ROWS,
    +    0,  // cursorChar
    +    0,  // editCursorChar
    +    NULL,  // upArrow
    +    NULL   // downArrow
    +);
    +
    +
    +Hide both the cursor and arrows + +

    If these options are not enough for you, you can always create your own custom renderer by subclassing the CharacterDisplayRenderer class.

    +

    Here is basic example of how to create a custom renderer:

    +
    class MyCustomRenderer : public CharacterDisplayRenderer {
    +public:
    +    MyCustomRenderer(CharacterDisplayInterface *display, uint8_t cols, uint8_t rows)
    +        : CharacterDisplayRenderer(display, cols, rows) {
    +    }
    +
    +    void drawItem(const char* text) override {
    +        // Custom rendering code here
    +        // The text parameter contains the menu item text and the value of the item if present
    +        // eg. "Item 1" or "Item 1:42"
    +        //
    +        // You can append a cursor character to the text if the item is selected etc.
    +    }
    +};
    +
    +MyCustomRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS);
    +
    +
    +

    Find more information about the character display renderer in the API reference.

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    © 2024, Thomas Forntoh 

    +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/overview/rendering/index.html b/overview/rendering/index.html new file mode 100644 index 00000000..f0b0fc6a --- /dev/null +++ b/overview/rendering/index.html @@ -0,0 +1,280 @@ + + + + + + + + + +Rendering the menu | LcdMenu + + + + + + + + + + + + + + + +
    + Skip to content +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +

    Rendering the menu

    +

    LcdMenu provides a set of built-in renderers that you can use to display the menu items on different output devices. +The renderers are responsible for drawing the menu items on the screen. They can be customized to suit your needs.

    +

    There are lots of opportunities to create your own custom renderer. You can create a renderer for any output device that you like. +For example, you could create a renderer for a TFT display, a touchscreen, or even a 3D printer 😄 (the frame rate would be atrocious)

    +
    +

    The library comes with the following built-in renderers:

    + +
    +

    Don’t see a renderer for your favorite output device? Feel free to create a new one and share it with the community!

    +

    Here are some that would be cool to have:

    +
      +
    • Serial renderer

    • +
    • Web renderer

    • +
    • TFT renderer

    • +
    • OLED renderer

    • +
    +
    +
    +
    +
    +
    +
    +
    +

    © 2024, Thomas Forntoh 

    +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/api/ItemBack.html b/reference/api/ItemBack.html index d3eb530f..7873afe1 100644 --- a/reference/api/ItemBack.html +++ b/reference/api/ItemBack.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    diff --git a/reference/api/ItemCommand.html b/reference/api/ItemCommand.html index c9ce17c3..e668b49f 100644 --- a/reference/api/ItemCommand.html +++ b/reference/api/ItemCommand.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    diff --git a/reference/api/ItemFloatRange.html b/reference/api/ItemFloatRange.html index 45adb542..2ee51344 100644 --- a/reference/api/ItemFloatRange.html +++ b/reference/api/ItemFloatRange.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    diff --git a/reference/api/ItemInput.html b/reference/api/ItemInput.html index b76f1758..024b4e3f 100644 --- a/reference/api/ItemInput.html +++ b/reference/api/ItemInput.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -301,8 +306,8 @@

    ItemInput

    Protected Functions

    -
    -inline uint8_t getViewSize(DisplayInterface *display)
    +
    +inline uint8_t getViewSize(MenuRenderer *renderer)

    The number of visible characters.

             visible area
            ┌───────────────┐
    @@ -311,22 +316,15 @@ 

    ItemInput │<── viewSize ─>│

    -

    Effectively const, but initialized lately when display is injected.

    +

    Effectively const, but initialized lately when renderer is injected.

    -
    -inline uint8_t constrainBlinkerPosition(DisplayInterface *display, uint8_t blinkerPosition)
    -
    -
    -
    -inline virtual void draw(DisplayInterface *display, uint8_t row) override
    -

    Draw this menu item on specified display on specified line.

    +
    +inline virtual void draw(MenuRenderer *renderer) override
    +

    Draw this menu item on specified display on current row.

    Parameters:
    -
      -
    • display – Pointer to the DisplayInterface object used for rendering.

    • -
    • row – the number of row to draw on

    • -
    +

    renderer – The renderer to use for drawing.

    @@ -347,44 +345,44 @@

    ItemInput -
    -inline void enter(DisplayInterface *display)
    +
    +inline void enter(MenuRenderer *renderer)
    -
    -inline void back(DisplayInterface *display)
    +
    +inline void back(MenuRenderer *renderer)
    -
    -inline void left(DisplayInterface *display)
    +
    +inline void left(MenuRenderer *renderer)
    -
    -inline void right(DisplayInterface *display)
    +
    +inline void right(MenuRenderer *renderer)

    Moves the cursor to the right within the input value.

    -
    -inline void backspace(DisplayInterface *display)
    +
    +inline void backspace(MenuRenderer *renderer)

    Handles the backspace action for the input field.

    -
    -inline void typeChar(DisplayInterface *display, const unsigned char character)
    +
    +inline void typeChar(MenuRenderer *renderer, const unsigned char character)

    Types a character into the current input value at the cursor position.

    -

    This function inserts a character into the value string at the current cursor position. If the cursor is within the current length of the string, the string is split and the character is inserted in between. If the cursor is at the end of the string, the character is appended. The cursor is then incremented, and the view is adjusted if necessary. Finally, the display is updated and the blinker position is reset.

    +

    This function inserts a character into the value string at the current cursor position. If the cursor is within the current length of the string, the string is split and the character is inserted in between. If the cursor is at the end of the string, the character is appended. The cursor is then incremented, and the view is adjusted if necessary. Finally, the renderer is updated and the blinker position is reset.

    Parameters:
      -
    • display – Pointer to the DisplayInterface object used for rendering.

    • +
    • renderer – Pointer to the MenuRenderer object used for rendering.

    • character – The character to be typed into the input value.

    -
    -inline void clear(DisplayInterface *display)
    +
    +inline void clear(MenuRenderer *renderer)

    Clear the value of the input field.

    @@ -455,17 +453,16 @@

    ItemInputItemInput::getValue()
  • ItemInput::setValue()
  • ItemInput::getCallbackStr()
  • -
  • ItemInput::getViewSize()
  • -
  • ItemInput::constrainBlinkerPosition()
  • -
  • ItemInput::draw()
  • +
  • ItemInput::getViewSize()
  • +
  • ItemInput::draw()
  • ItemInput::process()
  • -
  • ItemInput::enter()
  • -
  • ItemInput::back()
  • -
  • ItemInput::left()
  • -
  • ItemInput::right()
  • -
  • ItemInput::backspace()
  • -
  • ItemInput::typeChar()
  • -
  • ItemInput::clear()
  • +
  • ItemInput::enter()
  • +
  • ItemInput::back()
  • +
  • ItemInput::left()
  • +
  • ItemInput::right()
  • +
  • ItemInput::backspace()
  • +
  • ItemInput::typeChar()
  • +
  • ItemInput::clear()
  • ItemInput::value
  • ItemInput::view
  • ItemInput::cursor
  • diff --git a/reference/api/ItemInputCharset.html b/reference/api/ItemInputCharset.html index ee608302..c35202ca 100644 --- a/reference/api/ItemInputCharset.html +++ b/reference/api/ItemInputCharset.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -230,7 +235,7 @@

    ItemInputCharset
    Parameters:
    +
  • +
  • Reference

    diff --git a/reference/api/ItemList.html b/reference/api/ItemList.html index 091399a5..08277f94 100644 --- a/reference/api/ItemList.html +++ b/reference/api/ItemList.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -310,15 +315,12 @@

    ItemList

    Protected Functions

    -
    -inline virtual void draw(DisplayInterface *display, uint8_t row) override
    -

    Draw this menu item on specified display on specified line.

    +
    +inline virtual void draw(MenuRenderer *renderer) override
    +

    Draw this menu item on specified display on current row.

    Parameters:
    -
      -
    • display – Pointer to the DisplayInterface object used for rendering.

    • -
    • row – the number of row to draw on

    • -
    +

    renderer – The renderer to use for drawing.

    @@ -339,12 +341,12 @@

    ItemList

    -
    -inline void selectPrevious(DisplayInterface *display)
    +
    +inline void selectPrevious(MenuRenderer *renderer)
    -
    -inline void selectNext(DisplayInterface *display)
    +
    +inline void selectNext(MenuRenderer *renderer)
    @@ -396,10 +398,10 @@

    ItemList
  • ItemList::getItemCount()
  • ItemList::getItems()
  • ItemList::getValue()
  • -
  • ItemList::draw()
  • +
  • ItemList::draw()
  • ItemList::process()
  • -
  • ItemList::selectPrevious()
  • -
  • ItemList::selectNext()
  • +
  • ItemList::selectPrevious()
  • +
  • ItemList::selectNext()
  • ItemList::callback
  • ItemList::items
  • ItemList::itemCount
  • diff --git a/reference/api/ItemRangeBase.html b/reference/api/ItemRangeBase.html index 0fff3938..dff8f771 100644 --- a/reference/api/ItemRangeBase.html +++ b/reference/api/ItemRangeBase.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -295,15 +300,12 @@

    ItemRangeBase

    Protected Functions

    -
    -inline virtual void draw(DisplayInterface *display, uint8_t row) override
    -

    Draw this menu item on specified display on specified line.

    +
    +inline virtual void draw(MenuRenderer *renderer) override
    +

    Draw this menu item on specified display on current row.

    Parameters:
    -
      -
    • display – Pointer to the DisplayInterface object used for rendering.

    • -
    • row – the number of row to draw on

    • -
    +

    renderer – The renderer to use for drawing.

    @@ -384,7 +386,7 @@

    ItemRangeBaseItemRangeBase::setCurrentValue()
  • ItemRangeBase::getCurrentValue()
  • ItemRangeBase::getDisplayValue()
  • -
  • ItemRangeBase::draw()
  • +
  • ItemRangeBase::draw()
  • ItemRangeBase::process()
  • ItemRangeBase::minValue
  • ItemRangeBase::maxValue
  • diff --git a/reference/api/ItemSubMenu.html b/reference/api/ItemSubMenu.html index 67fa3ee5..92589bb8 100644 --- a/reference/api/ItemSubMenu.html +++ b/reference/api/ItemSubMenu.html @@ -18,7 +18,7 @@ - + + + +
    + Skip to content +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +

    CharacterDisplayInterface

    +
    +
    +class CharacterDisplayInterface : public DisplayInterface
    +
    +#include <CharacterDisplayInterface.h>
    +

    An interface for character-based display devices.

    +

    This interface extends the DisplayInterface and provides additional methods specific to character-based displays, such as creating custom characters and controlling a blinker.

    +
    +

    Note

    +

    This is an abstract class and cannot be instantiated directly.

    +
    +

    Subclassed by LiquidCrystalAdapter, LiquidCrystal_I2CAdapter

    +
    +

    Public Functions

    +
    +
    +inline virtual ~CharacterDisplayInterface()
    +

    Virtual destructor for the CharacterDisplayInterface.

    +
    +
    +
    +virtual void createChar(uint8_t id, uint8_t *c) = 0
    +

    Creates a custom character on the display.

    +
    +
    Parameters:
    +
      +
    • id – The identifier for the custom character.

    • +
    • c – A pointer to an array representing the custom character.

    • +
    +
    +
    +
    +
    +
    +virtual void drawBlinker() = 0
    +

    Draws a blinker on the display.

    +
    +
    +
    +virtual void clearBlinker() = 0
    +

    Clears the blinker from the display.

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    © 2024, Thomas Forntoh 

    +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/api/display/DisplayInterface.html b/reference/api/display/DisplayInterface.html index 3183a1c5..af625668 100644 --- a/reference/api/display/DisplayInterface.html +++ b/reference/api/display/DisplayInterface.html @@ -19,7 +19,7 @@ - + + + +
    + Skip to content +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +

    CharacterDisplayRenderer

    +
    +
    +class CharacterDisplayRenderer : public MenuRenderer
    +
    +#include <CharacterDisplayRenderer.h>
    +

    A renderer for character-based displays, extending the MenuRenderer class.

    +

    This class provides functionality to render menus on character-based displays. It supports custom icons for cursor and edit cursor, as well as up and down arrows for navigation indicators.

    +

    The CharacterDisplayRenderer class is designed to work with displays that implement the CharacterDisplayInterface. It provides methods to draw menu items, cursors, and navigation indicators. The class also handles text truncation and cursor movement.

    +
    +

    Note

    +

    The class uses dynamic memory allocation for the upArrow and downArrow icons.

    +
    +
    +

    Public Functions

    +
    +
    +CharacterDisplayRenderer(CharacterDisplayInterface *display, const uint8_t maxCols, const uint8_t maxRows, const uint8_t cursorIcon = 0x7E, const uint8_t editCursorIcon = 0x7F, uint8_t *upArrow = new uint8_t[8]{0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04}, uint8_t *downArrow = new uint8_t[8]{0x04, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04})
    +

    Constructor for CharacterDisplayRenderer. Initializes the renderer with the display, maximum columns, and maximum rows. Also sets the up and down arrow icons, cursor icons, and edit cursor icons.

    +
    +

    Note

    +

    slots 1 and 2 are reserved for up and down arrow icons. The available custom characters slots are 0 and 3 to 7.

    +
    +
    +
    Parameters:
    +
      +
    • display – A pointer to the CharacterDisplayInterface object.

    • +
    • maxCols – The maximum number of columns on the display.

    • +
    • maxRows – The maximum number of rows on the display.

    • +
    • cursorIcon – A byte representing the cursor icon, default is →, if 0, cursor will not be displayed

    • +
    • editCursorIcon – A byte representing the edit cursor icon, default is ←, if 0, edit cursor will not be displayed

    • +
    • upArrow – A pointer to an array of bytes representing the up arrow icon, default is ↑, if null, up arrow will not be displayed

    • +
    • downArrow – A pointer to an array of bytes representing the down arrow icon, default is ↓, if null, down arrow will not be displayed

    • +
    +
    +
    +
    +
    +
    +virtual void begin() override
    +

    Initializes the renderer and creates custom characters on the display.

    +
    +
    +
    +virtual void drawItem(const char *text) override
    +

    Draws a menu item on the character display.

    +

    This function overrides the base class implementation to draw a menu item on the character display. It handles appending a cursor to the text, truncating the text if it’s too long, padding the text with spaces, appending an indicator to the text, and finally drawing the text on the display.

    +
    +
    Parameters:
    +

    text – The text of the menu item to be drawn.

    +
    +
    +
    +
    +
    +virtual void draw(uint8_t byte) override
    +

    Function to draw a byte on the display.

    +
    +
    Parameters:
    +

    byte – The byte to be drawn.

    +
    +
    +
    +
    +
    +virtual void drawBlinker() override
    +

    Function to draw the blinker on the display.

    +
    +
    +
    +virtual void clearBlinker() override
    +

    Function to clear the blinker from the display.

    +
    +
    +
    +virtual void moveCursor(uint8_t cursorCol, uint8_t cursorRow) override
    +

    Moves the cursor to a specified position.

    +
    +
    Parameters:
    +
      +
    • cursorCol – Column position to move the cursor to.

    • +
    • cursorRow – Row position to move the cursor to.

    • +
    +
    +
    +
    +
    +
    +

    Protected Functions

    +
    +
    +void appendCursorToText(const char *text, char *buf)
    +

    Appends a cursor icon to the given text if the specified screen row is active.

    +
    +
    Parameters:
    +
      +
    • text – The original text to which the cursor icon will be appended.

    • +
    • buf – The buffer where the resulting text with the cursor icon will be stored.

    • +
    +
    +
    +
    +
    +
    +void appendIndicatorToText(const char *text, char *buf)
    +

    Appends an indicator to the provided text based on the item index and screen row.

    +
    +
    Parameters:
    +
      +
    • text – The original text to which the indicator may be appended.

    • +
    • buf – The buffer where the resulting text with the indicator will be stored.

    • +
    +
    +
    +
    +
    +
    +void padText(const char *text, char *buf)
    +

    Pads the given text with spaces to fit within the available length.

    +

    This function takes a text string and pads it with spaces so that the total length of the text fits within the available length of the display. If the text is longer than the available length, no padding is added.

    +
    +
    Parameters:
    +
      +
    • text – The input text to be padded.

    • +
    • buf – The buffer where the padded text will be stored. It should be large enough to hold the padded text.

    • +
    +
    +
    +
    +
    +
    +uint8_t calculateAvailableLength()
    +

    Calculates the available length for display.

    +

    This function computes the number of columns available for displaying content on the character display. It takes into account the presence of up and down arrows, which occupy one column if either is present.

    +
    +
    Returns:
    +

    The number of columns available for displaying content.

    +
    +
    +
    +
    +
    +

    Protected Attributes

    +
    +
    +uint8_t *upArrow
    +
    +
    +
    +uint8_t *downArrow
    +
    +
    +
    +const uint8_t cursorIcon
    +
    +
    +
    +const uint8_t editCursorIcon
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    © 2024, Thomas Forntoh 

    +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/api/renderer/MenuRenderer.html b/reference/api/renderer/MenuRenderer.html new file mode 100644 index 00000000..e1b4a2fe --- /dev/null +++ b/reference/api/renderer/MenuRenderer.html @@ -0,0 +1,499 @@ + + + + + + + + + +MenuRenderer | LcdMenu + + + + + + + + + + + + + + + +
    + Skip to content +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    + +
    +
    +
    +
    +
    +
    +

    © 2024, Thomas Forntoh 

    +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/api/renderer/index.html b/reference/api/renderer/index.html new file mode 100644 index 00000000..14d1be44 --- /dev/null +++ b/reference/api/renderer/index.html @@ -0,0 +1,266 @@ + + + + + + + + + +renderer | LcdMenu + + + + + + + + + + + + + + + +
    + + + + + + + \ No newline at end of file diff --git a/reference/changelog.html b/reference/changelog.html index 34f16ccf..e9475ecd 100644 --- a/reference/changelog.html +++ b/reference/changelog.html @@ -134,11 +134,23 @@

    Changelog

    This is the changelog of LcdMenu library. It contains information about the changes between versions.

    -
    -

    LcdMenu v5.0.0

    +
    +

    LcdMenu v5.1.0

    What’s Changed

      +
    • Remove itemIndex dependency from renderer by @forntoh in #234

    • +
    • Patch/remove screen row dependency in renderer by @forntoh in #235

    • +
    • [Feat] Add Menu Renderer by @forntoh in #233

    • +
    +

    Full Changelog: https://github.com/forntoh/LcdMenu/compare/5.0.0…5.1.0

    +
    +
    +
    +

    LcdMenu v5.0.0

    +
    +

    What’s Changed

    +
    • Move logic from LcdMenu to items by @ShishkinDmitriy in #193

    • Expand RotaryEncoder usability for text input by @forntoh in #196

    • Update ClangFormat settings and add linting workflow by @forntoh in #201

    • @@ -176,8 +188,8 @@

      Breaking Changes

      LcdMenu v4.2.0

      -
      -

      What’s Changed

      +
      +

      What’s Changed

      • Make global util functions inline by @ShishkinDmitriy in #192

      • Add SimpleNavConfig and deprecate processMenuCommand by @forntoh in #189

      • @@ -213,8 +225,8 @@

        Bug Fixes:

        LcdMenu 4.0.0

        This release introduces a major refactor of the display management system, aimed at making it more modular and flexible. The key change is the introduction of a display interface abstraction that decouples the display logic from the specific hardware, allowing for easier integration of different display types.

        -
        -

        What’s Changed

        +
        +

        What’s Changed

        • Display Interface Abstraction: * A new DisplayInterface class has been introduced to define a common interface for all display types. @@ -235,8 +247,8 @@

          Bug Fixes and Improvements -

          Breaking Changes

          +
          +

          Breaking Changes

          • API Changes: The introduction of the DisplayInterface class and its implementation may require changes to existing projects. Users must update their code to work with the new interface and adapters.

          • Some methods and features directly tied to the LiquidCrystal_I2C library have been refactored or removed. Please review [the migration guide](https://lcdmenu.forntoh.dev/reference/migration-guide) for details on how to update your code.

          • @@ -246,8 +258,8 @@

            Breaking Changes

            LcdMenu 3.5.6

            -
            -

            What’s Changed

            +
            +

            What’s Changed

            • Make isAtTheStart and isAtTheEnd public by @forntoh in #172

            @@ -256,8 +268,8 @@

            What’s Changed

            LcdMenu 3.5.5

            -
            -

            What’s Changed

            +
            +

            What’s Changed

            • #167 Update condition to check if cursor is at the top and bottom. by @forntoh in #170

            @@ -266,8 +278,8 @@

            What’s Changed

            LcdMenu 3.5.4

            -
            -

            What’s Changed

            +
            +

            What’s Changed

            • BugFix: After setCursorPosition navigation is broken by @forntoh in #165

            @@ -276,8 +288,8 @@

            What’s Changed

            LcdMenu 3.5.3

            -
            -

            What’s Changed

            +
            +

            What’s Changed

            • BugFix: Fixed setText and getSubMenu not working by @forntoh in #164

            @@ -286,8 +298,8 @@

            What’s Changed

            LcdMenu 3.5.2

            -
            -

            What’s Changed

            +
            +

            What’s Changed

            • BugFix - Charset Input value copied to all Input items on screen by @forntoh in #159

            @@ -296,8 +308,8 @@

            What’s Changed

            LcdMenu 3.5.1

            -
            -

            What’s Changed

            +
            +

            What’s Changed

            • BugFix - Update ItemList only in edit mode by @forntoh in #154

            • Add more logging functions by @forntoh in #155

            • @@ -320,8 +332,8 @@

              What’s New

              LcdMenu 3.4.0

              -
              -

              What’s Changed

              +
              +

              What’s Changed

              • Moved utils and constants to utils directory by @forntoh in #149

              • Allow a current progress to be set on ItemProgress by @PaulEmich in #150

              • @@ -337,14 +349,14 @@

                New Contributors

                LcdMenu 3.3.4

                -
                -

                What’s Changed

                +
                +

                What’s Changed

                • fix: compilation error with standard lcd by @andcan in #142

                -
                -

                New Contributors

                +
                +

                New Contributors

                • @andcan made their first contribution in #142

                @@ -353,8 +365,8 @@

                New Contributors

                LcdMenu 3.3.3

                -
                -

                What’s Changed

                +
                +

                What’s Changed

                • Update bug_report.yml by @forntoh in #130

                • Separated utils definition from declaration by @forntoh in #135

                • @@ -364,8 +376,8 @@

                  What’s Changed

                  LcdMenu 3.3.2

                  -
                  -

                  What’s Changed

                  +
                  +

                  What’s Changed

                  • Update callback function parameter types to use uint16_t instead of uint8_t. by @forntoh in #126

                  @@ -374,8 +386,8 @@

                  What’s Changed

                  LcdMenu 3.3.1

                  -
                  -

                  What’s Changed

                  +
                  +

                  What’s Changed

                  • Update LICENSE by @forntoh in #115

                  • added stale bot by @forntoh in #122

                  • @@ -386,8 +398,8 @@

                    What’s Changed

                    LcdMenu 3.3.0

                    -
                    -

                    ⭐ What’s new

                    +
                    +

                    ⭐ What’s new

                    • Progress, Integer and Float values support by @forntoh in #114

                    • Added custom edit mode cursor by @forntoh in #110

                    • @@ -404,8 +416,8 @@

                      🐛 Bugfix

                      LcdMenu 3.2.0

                      -
                      -

                      What’s Changed

                      +
                      +

                      What’s Changed

                      • Update bug_report.yml by @forntoh in #103

                      • Fixed ItemSubMenu text not displayed by @forntoh in #102

                      • @@ -418,8 +430,8 @@

                        What’s Changed

                        LcdMenu 3.1.1

                        -
                        -

                        What’s Changed

                        +
                        +

                        What’s Changed

                        • Fixed compile warnings related to ItemList by @forntoh in #101

                        @@ -428,8 +440,8 @@

                        What’s Changed

                        LcdMenu 3.1.0

                        -
                        -

                        What’s Changed

                        +
                        +

                        What’s Changed

                        • added unit testing and changed most instances of String to char* by @forntoh in #86

                        @@ -438,14 +450,14 @@

                        What’s Changed

                        LcdMenu 3.0.1

                        -
                        -

                        What’s Changed

                        +
                        +

                        What’s Changed

                        • Fixed library unusable without I2C 🐛 by 🫡 @dejanmeznarc in #93

                        -
                        -

                        New Contributors

                        +
                        +

                        New Contributors

                        • @dejanmeznarc made their first contribution in #93

                        @@ -461,14 +473,14 @@

                        Chore

                        LcdMenu 3.0.0 🚀

                        -
                        -

                        What’s new 🚀

                        +
                        +

                        What’s new 🚀

                        In previous versions of LcdMenu, the menu used a lot of memory since space has to be reserved for every field on the menu even if it is not used, this release fixes that by allowing the user to import only MenuItems which is needed.

                        You can expect to save up to 10% on memory usage (or even more 😎), depending on which menu item types you use.

                        There’s also a new way to create menus, check the readme.

                        -
                        -

                        Changelog

                        +
                        +

                        Changelog

    diff --git a/reference/faq.html b/reference/faq.html index 9e7a1024..871dc8f6 100644 --- a/reference/faq.html +++ b/reference/faq.html @@ -112,6 +112,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    diff --git a/reference/migration/index.html b/reference/migration/index.html index 8bd3c2bb..29d27caa 100644 --- a/reference/migration/index.html +++ b/reference/migration/index.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -211,17 +216,55 @@

    Migration

    This guide details the changes and how to change your code between versions of the LcdMenu library.

    -
    -

    Migration from v4.x to v5.x

    -

    This guide details the changes and how to change your code to migrate to LcdMenu v5.x.

    +
    +

    Migration from v5.0.0 to v5.1.x

    +

    This guide details the changes and how to change your code to migrate to LcdMenu v5.1.x

    +
    +

    LcdMenu initialization changes

    +

    In v5.0.0, the menu was initialized with the display adapter interface. +In this version, the menu is initialized with a renderer.

    +
    +

    Imports

    +

    The first change you’ll need to make is to add the import for the renderer. +Currently, the only renderer available is the CharacterDisplayRenderer.

    +
    #include <renderer/CharacterDisplayRenderer.h>
    +
    +
    +
    +
    +

    Construct the renderer interface

    +

    The renderer instance is created and passed to the menu.

    +
     LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS);
    + LiquidCrystal_I2CAdapter lcdAdapter(&lcd);
    + CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS);
    + LcdMenu menu(renderer);
    +
    +
    +
    +
    +
    +

    Setup changes

    +

    The setup function remains the same, but the menu is now initialized with the renderer.

    +
     void setup() {
    +     lcdAdapter.begin();
    +     renderer.begin();
    + }
    +
    +
    +

    This change allows for more flexibility in the display interface and the ability to create custom renderers.

    +
    +
    +
    +

    Migration from v4.x.x to v5.0.0

    +

    This guide details the changes and how to change your code to migrate to LcdMenu v5.0.0

    This is a major release with a lot of changes.

    Display interface changes

    In v4.x, the display instance was created and initialised in the display adapter. In this version, the display instance is created separately and passed to the display adapter. The existing display adapters have been renamed and placed in a new directory to closely match the display they are designed for.

    -
    -

    Imports

    +
    +

    Imports

    The first change you’ll need to make is to add the import for your desired display interface.

    @@ -344,8 +387,8 @@

    New imports -

    Construct the display adapter interface

    +
    +

    Construct the display adapter interface

    The second change is to construct the display adapter interface. For example, if you are using the LiquidCrystalI2CAdapter, you will need to construct it like this:

    LiquidCrystalI2CAdapter lcd(0x27, 16, 2);
    @@ -398,9 +441,18 @@ 

    Other changes

    Reference

    @@ -162,7 +167,7 @@
    @@ -203,12 +208,12 @@ -
    /
    Migration from v4.x to v5.x +
    /
    Migration from v4.x.x to v5.0.0
    -
    -

    Migration from v4.x to v5.x

    -

    This guide details the changes and how to change your code to migrate to LcdMenu v5.x.

    +
    +

    Migration from v4.x.x to v5.0.0

    +

    This guide details the changes and how to change your code to migrate to LcdMenu v5.0.0

    This is a major release with a lot of changes.

    Display interface changes

    diff --git a/reference/migration/v5.0.0-v5.1.x.html b/reference/migration/v5.0.0-v5.1.x.html new file mode 100644 index 00000000..e028f68c --- /dev/null +++ b/reference/migration/v5.0.0-v5.1.x.html @@ -0,0 +1,286 @@ + + + + + + + + + +Migration from v5.0.0 to v5.1.x | LcdMenu + + + + + + + + + + + + + +
    + Skip to content +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +
    +

    Migration from v5.0.0 to v5.1.x

    +

    This guide details the changes and how to change your code to migrate to LcdMenu v5.1.x

    +
    +

    LcdMenu initialization changes

    +

    In v5.0.0, the menu was initialized with the display adapter interface. +In this version, the menu is initialized with a renderer.

    +
    +

    Imports

    +

    The first change you’ll need to make is to add the import for the renderer. +Currently, the only renderer available is the CharacterDisplayRenderer.

    +
    #include <renderer/CharacterDisplayRenderer.h>
    +
    +
    +
    +
    +

    Construct the renderer interface

    +

    The renderer instance is created and passed to the menu.

    +
     LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS);
    + LiquidCrystal_I2CAdapter lcdAdapter(&lcd);
    + CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS);
    + LcdMenu menu(renderer);
    +
    +
    +
    +
    +
    +

    Setup changes

    +

    The setup function remains the same, but the menu is now initialized with the renderer.

    +
     void setup() {
    +     lcdAdapter.begin();
    +     renderer.begin();
    + }
    +
    +
    +

    This change allows for more flexibility in the display interface and the ability to create custom renderers.

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    © 2024, Thomas Forntoh 

    +
    +
    +
    +
    + + + + + + + \ No newline at end of file diff --git a/reference/samples/Basic.html b/reference/samples/Basic.html index 586130ef..e57702fd 100644 --- a/reference/samples/Basic.html +++ b/reference/samples/Basic.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -215,35 +220,36 @@

    Basic 2#include <MenuScreen.h> 3#include <display/LiquidCrystal_I2CAdapter.h> 4#include <input/KeyboardAdapter.h> - 5 - 6#define LCD_ROWS 2 - 7#define LCD_COLS 16 - 8 - 9// Initialize the main menu items -10// clang-format off -11MENU_SCREEN(mainScreen, mainItems, -12 ITEM_BASIC("Start service"), -13 ITEM_BASIC("Connect to WiFi"), -14 ITEM_BASIC("Settings"), -15 ITEM_BASIC("Blink SOS"), -16 ITEM_BASIC("Blink random")); -17// clang-format on -18 -19LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -20LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -21LcdMenu menu(lcdAdapter); -22KeyboardAdapter keyboard(&menu, &Serial); -23 -24void setup() { -25 Serial.begin(9600); -26 // Initialize LcdMenu with the menu items -27 lcdAdapter.begin(); -28 menu.setScreen(mainScreen); -29} -30 -31void loop() { -32 keyboard.observe(); -33} + 5#include <renderer/CharacterDisplayRenderer.h> + 6 + 7#define LCD_ROWS 2 + 8#define LCD_COLS 16 + 9 +10// Initialize the main menu items +11// clang-format off +12MENU_SCREEN(mainScreen, mainItems, +13 ITEM_BASIC("Start service"), +14 ITEM_BASIC("Connect to WiFi"), +15 ITEM_BASIC("Settings"), +16 ITEM_BASIC("Blink SOS"), +17 ITEM_BASIC("Blink random")); +18// clang-format on +19 +20LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +21CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +22LcdMenu menu(renderer); +23KeyboardAdapter keyboard(&menu, &Serial); +24 +25void setup() { +26 Serial.begin(9600); +27 // Initialize LcdMenu with the menu items +28 renderer.begin(); +29 menu.setScreen(mainScreen); +30} +31 +32void loop() { +33 keyboard.observe(); +34}

    diff --git a/reference/samples/ButtonAdapter.html b/reference/samples/ButtonAdapter.html index 4cedb234..3fd0389f 100644 --- a/reference/samples/ButtonAdapter.html +++ b/reference/samples/ButtonAdapter.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -217,50 +222,52 @@

    ButtonAdapter 4#include <MenuScreen.h> 5#include <display/LiquidCrystal_I2CAdapter.h> 6#include <input/ButtonAdapter.h> - 7 - 8#define LCD_ROWS 2 - 9#define LCD_COLS 16 -10 -11// Declare the call back function -12void toggleBacklight(bool isOn); -13 -14// clang-format off -15MENU_SCREEN(mainScreen, mainItems, -16 ITEM_BASIC("Start service"), -17 ITEM_BASIC("Connect to WiFi"), -18 ITEM_TOGGLE("Backlight", toggleBacklight), -19 ITEM_BASIC("Blink SOS"), -20 ITEM_BASIC("Blink random")); -21// clang-format on -22 -23LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -24LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -25LcdMenu menu(lcdAdapter); -26Button upBtn(2); -27ButtonAdapter upBtnA(&menu, &upBtn, UP); -28Button downBtn(3); -29ButtonAdapter downBtnA(&menu, &downBtn, DOWN); -30Button enterBtn(4); -31ButtonAdapter enterBtnA(&menu, &enterBtn, ENTER); -32 -33void setup() { -34 upBtn.begin(); -35 downBtn.begin(); -36 enterBtn.begin(); -37 lcdAdapter.begin(); -38 Serial.begin(9600); -39 menu.setScreen(mainScreen); -40} -41 -42void loop() { -43 upBtnA.observe(); -44 downBtnA.observe(); -45 enterBtnA.observe(); -46} -47/** -48 * Define callback -49 */ -50void toggleBacklight(bool isOn) { lcdAdapter.setBacklight(isOn); } + 7#include <renderer/CharacterDisplayRenderer.h> + 8 + 9#define LCD_ROWS 2 +10#define LCD_COLS 16 +11 +12// Declare the call back function +13void toggleBacklight(bool isOn); +14 +15// clang-format off +16MENU_SCREEN(mainScreen, mainItems, +17 ITEM_BASIC("Start service"), +18 ITEM_BASIC("Connect to WiFi"), +19 ITEM_TOGGLE("Backlight", toggleBacklight), +20 ITEM_BASIC("Blink SOS"), +21 ITEM_BASIC("Blink random")); +22// clang-format on +23 +24LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +25LiquidCrystal_I2CAdapter lcdAdapter(&lcd); +26CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS); +27LcdMenu menu(renderer); +28Button upBtn(5); +29ButtonAdapter upBtnA(&menu, &upBtn, UP); +30Button downBtn(6); +31ButtonAdapter downBtnA(&menu, &downBtn, DOWN); +32Button enterBtn(7); +33ButtonAdapter enterBtnA(&menu, &enterBtn, ENTER); +34 +35void setup() { +36 upBtn.begin(); +37 downBtn.begin(); +38 enterBtn.begin(); +39 renderer.begin(); +40 Serial.begin(9600); +41 menu.setScreen(mainScreen); +42} +43 +44void loop() { +45 upBtnA.observe(); +46 downBtnA.observe(); +47 enterBtnA.observe(); +48} +49/** +50 * Define callback +51 */ +52void toggleBacklight(bool isOn) { lcdAdapter.setBacklight(isOn); }

    diff --git a/reference/samples/ButtonWithRotaryAdapter.html b/reference/samples/ButtonWithRotaryAdapter.html index eab2697a..c6451719 100644 --- a/reference/samples/ButtonWithRotaryAdapter.html +++ b/reference/samples/ButtonWithRotaryAdapter.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -224,58 +229,60 @@

    ButtonWithRotaryAdapter11#include <display/LiquidCrystal_I2CAdapter.h> 12#include <input/ButtonAdapter.h> 13#include <input/SimpleRotaryAdapter.h> -14 -15#define LCD_ROWS 2 -16#define LCD_COLS 16 -17 -18// Declare the callbacks -19void colorsCallback(uint8_t pos); -20void toggleBacklight(bool isOn); -21void inputCallback(char* value); -22 -23String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"}; -24 -25// clang-format off -26MENU_SCREEN(mainScreen, mainItems, -27 ITEM_INPUT_CHARSET("User", (const char*)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", inputCallback), -28 ITEM_STRING_LIST("Color", colors, 8, colorsCallback), -29 ITEM_TOGGLE("Backlight", toggleBacklight), -30 ITEM_BASIC("Placeholder 1"), -31 ITEM_BASIC("Placeholder 2")); -32// clang-format on -33 -34LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -35LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -36LcdMenu menu(lcdAdapter); -37SimpleRotary encoder(2, 3, 4); -38SimpleRotaryAdapter rotaryInput(&menu, &encoder); // Rotary input adapter -39Button backspaceBtn(5); -40ButtonAdapter backspaceBtnA(&menu, &backspaceBtn, BACKSPACE); // Push button for backspace -41 -42void setup() { -43 backspaceBtn.begin(); -44 lcdAdapter.begin(); -45 Serial.begin(9600); -46 menu.setScreen(mainScreen); -47} -48 -49void loop() { -50 rotaryInput.observe(); -51 backspaceBtnA.observe(); -52} -53 -54// Define the callbacks -55void toggleBacklight(bool isOn) { -56 lcdAdapter.setBacklight(isOn); -57} -58 -59void colorsCallback(uint8_t pos) { -60 Serial.println(colors[pos]); -61} -62 -63void inputCallback(char* value) { -64 Serial.println(value); -65} +14#include <renderer/CharacterDisplayRenderer.h> +15 +16#define LCD_ROWS 2 +17#define LCD_COLS 16 +18 +19// Declare the callbacks +20void colorsCallback(uint8_t pos); +21void toggleBacklight(bool isOn); +22void inputCallback(char* value); +23 +24String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"}; +25 +26// clang-format off +27MENU_SCREEN(mainScreen, mainItems, +28 ITEM_INPUT_CHARSET("User", (const char*)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", inputCallback), +29 ITEM_STRING_LIST("Color", colors, 8, colorsCallback), +30 ITEM_TOGGLE("Backlight", toggleBacklight), +31 ITEM_BASIC("Placeholder 1"), +32 ITEM_BASIC("Placeholder 2")); +33// clang-format on +34 +35LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +36LiquidCrystal_I2CAdapter lcdAdapter(&lcd); +37CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS); +38LcdMenu menu(renderer); +39SimpleRotary encoder(2, 3, 4); +40SimpleRotaryAdapter rotaryInput(&menu, &encoder); // Rotary input adapter +41Button backspaceBtn(11); +42ButtonAdapter backspaceBtnA(&menu, &backspaceBtn, BACKSPACE); // Push button for backspace +43 +44void setup() { +45 backspaceBtn.begin(); +46 renderer.begin(); +47 Serial.begin(9600); +48 menu.setScreen(mainScreen); +49} +50 +51void loop() { +52 rotaryInput.observe(); +53 backspaceBtnA.observe(); +54} +55 +56// Define the callbacks +57void toggleBacklight(bool isOn) { +58 lcdAdapter.setBacklight(isOn); +59} +60 +61void colorsCallback(uint8_t pos) { +62 Serial.println(colors[pos]); +63} +64 +65void inputCallback(char* value) { +66 Serial.println(value); +67}

    diff --git a/reference/samples/Callbacks.html b/reference/samples/Callbacks.html index d7d8bb4f..2d5fc39a 100644 --- a/reference/samples/Callbacks.html +++ b/reference/samples/Callbacks.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -216,43 +221,45 @@

    Callbacks 3#include <MenuScreen.h> 4#include <display/LiquidCrystal_I2CAdapter.h> 5#include <input/KeyboardAdapter.h> - 6 - 7#define LCD_ROWS 2 - 8#define LCD_COLS 16 - 9 -10// Declare the call back function -11void toggleBacklight(bool isOn); -12 -13// clang-format off -14MENU_SCREEN(mainScreen, mainItems, -15 ITEM_BASIC("Start service"), -16 ITEM_BASIC("Connect to WiFi"), -17 ITEM_TOGGLE("Backlight", toggleBacklight), -18 ITEM_BASIC("Blink SOS"), -19 ITEM_BASIC("Blink random")); -20// clang-format on -21 -22LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -23LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -24LcdMenu menu(lcdAdapter); -25KeyboardAdapter keyboard(&menu, &Serial); -26 -27void setup() { -28 Serial.begin(9600); -29 lcdAdapter.begin(); -30 menu.setScreen(mainScreen); -31} -32 -33void loop() { -34 keyboard.observe(); -35} -36 -37/** -38 * Define callback -39 */ -40void toggleBacklight(bool isOn) { -41 lcdAdapter.setBacklight(isOn); -42} + 6#include <renderer/CharacterDisplayRenderer.h> + 7 + 8#define LCD_ROWS 2 + 9#define LCD_COLS 16 +10 +11// Declare the call back function +12void toggleBacklight(bool isOn); +13 +14// clang-format off +15MENU_SCREEN(mainScreen, mainItems, +16 ITEM_BASIC("Start service"), +17 ITEM_BASIC("Connect to WiFi"), +18 ITEM_TOGGLE("Backlight", toggleBacklight), +19 ITEM_BASIC("Blink SOS"), +20 ITEM_BASIC("Blink random")); +21// clang-format on +22 +23LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +24LiquidCrystal_I2CAdapter lcdAdapter(&lcd); +25CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS); +26LcdMenu menu(renderer); +27KeyboardAdapter keyboard(&menu, &Serial); +28 +29void setup() { +30 Serial.begin(9600); +31 renderer.begin(); +32 menu.setScreen(mainScreen); +33} +34 +35void loop() { +36 keyboard.observe(); +37} +38 +39/** +40 * Define callback +41 */ +42void toggleBacklight(bool isOn) { +43 lcdAdapter.setBacklight(isOn); +44}

    diff --git a/reference/samples/CharsetInput.html b/reference/samples/CharsetInput.html index 67500821..44755025 100644 --- a/reference/samples/CharsetInput.html +++ b/reference/samples/CharsetInput.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -217,46 +222,47 @@

    CharsetInput 4#include <MenuScreen.h> 5#include <display/LiquidCrystal_I2CAdapter.h> 6#include <input/KeyboardAdapter.h> - 7 - 8#define LCD_ROWS 2 - 9#define LCD_COLS 16 -10 -11// Create your charset -12const char* charset = "0123456789"; -13 -14// Declare the call back function -15void inputCallback(char* value); -16 -17// clang-format off -18MENU_SCREEN(mainScreen, mainItems, -19 ITEM_INPUT_CHARSET("Con", "0123456", charset, inputCallback), -20 ITEM_BASIC("Connect to WiFi"), -21 ITEM_BASIC("Blink SOS"), -22 ITEM_BASIC("Blink random")); -23// clang-format on -24 -25LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -26LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -27LcdMenu menu(lcdAdapter); -28KeyboardAdapter keyboard(&menu, &Serial); -29 -30void setup() { -31 Serial.begin(9600); -32 lcdAdapter.begin(); -33 menu.setScreen(mainScreen); -34} -35 -36void loop() { -37 keyboard.observe(); -38} -39/** -40 * Define callback -41 */ -42void inputCallback(char* value) { -43 // Do stuff with value -44 Serial.print(F("# ")); -45 Serial.println(value); -46} + 7#include <renderer/CharacterDisplayRenderer.h> + 8 + 9#define LCD_ROWS 2 +10#define LCD_COLS 16 +11 +12// Create your charset +13const char* charset = "0123456789"; +14 +15// Declare the call back function +16void inputCallback(char* value); +17 +18// clang-format off +19MENU_SCREEN(mainScreen, mainItems, +20 ITEM_INPUT_CHARSET("Con", "0123456", charset, inputCallback), +21 ITEM_BASIC("Connect to WiFi"), +22 ITEM_BASIC("Blink SOS"), +23 ITEM_BASIC("Blink random")); +24// clang-format on +25 +26LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +27CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +28LcdMenu menu(renderer); +29KeyboardAdapter keyboard(&menu, &Serial); +30 +31void setup() { +32 Serial.begin(9600); +33 renderer.begin(); +34 menu.setScreen(mainScreen); +35} +36 +37void loop() { +38 keyboard.observe(); +39} +40/** +41 * Define callback +42 */ +43void inputCallback(char* value) { +44 // Do stuff with value +45 Serial.print(F("# ")); +46 Serial.println(value); +47}

    diff --git a/reference/samples/InputRotary.html b/reference/samples/InputRotary.html index 29231fba..e48f117b 100644 --- a/reference/samples/InputRotary.html +++ b/reference/samples/InputRotary.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -220,57 +225,58 @@

    InputRotary 7#include <SimpleRotary.h> 8#include <display/LiquidCrystal_I2CAdapter.h> 9#include <input/SimpleRotaryAdapter.h> -10 -11#define LCD_ROWS 2 -12#define LCD_COLS 16 -13 -14// Create your charset -15const char* charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -16 -17// Declare the call back functions -18void inputCallback(char* value); -19void clearInput(); -20 -21extern MenuScreen* userScreen; -22 -23// clang-format off -24MENU_SCREEN(mainScreen, mainItems, -25 ITEM_SUBMENU("Set user", userScreen), -26 ITEM_BASIC("Settings"), -27 ITEM_BASIC("More Settings"), -28 ITEM_BASIC("And more Settings")); -29 -30MENU_SCREEN(userScreen, userItems, -31 ITEM_INPUT_CHARSET("User", charset, inputCallback), -32 ITEM_COMMAND("Clear", clearInput)); -33// clang-format on -34 -35LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -36LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -37LcdMenu menu(lcdAdapter); -38SimpleRotary encoder(2, 3, 4); -39SimpleRotaryAdapter rotaryInput(&menu, &encoder); -40 -41void setup() { -42 Serial.begin(9600); -43 lcdAdapter.begin(); -44 menu.setScreen(mainScreen); -45} -46 -47void loop() { rotaryInput.observe(); } -48 -49// Define the callbacks -50void inputCallback(char* value) { -51 // Do stuff with value -52 Serial.print(F("# ")); -53 Serial.println(value); -54} -55 -56void clearInput() { -57 if ((static_cast<ItemInput*>(userItems[0]))->setValue((char*)"")) { -58 menu.refresh(); -59 } -60} +10#include <renderer/CharacterDisplayRenderer.h> +11 +12#define LCD_ROWS 2 +13#define LCD_COLS 16 +14 +15// Create your charset +16const char* charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +17 +18// Declare the call back functions +19void inputCallback(char* value); +20void clearInput(); +21 +22extern MenuScreen* userScreen; +23 +24// clang-format off +25MENU_SCREEN(mainScreen, mainItems, +26 ITEM_SUBMENU("Set user", userScreen), +27 ITEM_BASIC("Settings"), +28 ITEM_BASIC("More Settings"), +29 ITEM_BASIC("And more Settings")); +30 +31MENU_SCREEN(userScreen, userItems, +32 ITEM_INPUT_CHARSET("User", charset, inputCallback), +33 ITEM_COMMAND("Clear", clearInput)); +34// clang-format on +35 +36LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +37CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +38LcdMenu menu(renderer); +39SimpleRotary encoder(2, 3, 4); +40SimpleRotaryAdapter rotaryInput(&menu, &encoder); +41 +42void setup() { +43 Serial.begin(9600); +44 renderer.begin(); +45 menu.setScreen(mainScreen); +46} +47 +48void loop() { rotaryInput.observe(); } +49 +50// Define the callbacks +51void inputCallback(char* value) { +52 // Do stuff with value +53 Serial.print(F("# ")); +54 Serial.println(value); +55} +56 +57void clearInput() { +58 if ((static_cast<ItemInput*>(userItems[0]))->setValue((char*)"")) { +59 menu.refresh(); +60 } +61}

    diff --git a/reference/samples/IntFloatValues.html b/reference/samples/IntFloatValues.html index 76dd8ab3..5c627005 100644 --- a/reference/samples/IntFloatValues.html +++ b/reference/samples/IntFloatValues.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -217,50 +222,51 @@

    IntFloatValues 4#include <MenuScreen.h> 5#include <display/LiquidCrystal_I2CAdapter.h> 6#include <input/KeyboardAdapter.h> - 7 - 8#define LCD_ROWS 2 - 9#define LCD_COLS 16 -10 -11// Declare the callbacks -12void callbackInt(int value); -13void callbackFloat(float value); -14 -15// Initialize the main menu items -16// clang-format off -17MENU_SCREEN(mainScreen, mainItems, -18 ITEM_BASIC("Con"), -19 ITEM_INT_RANGE("Dist", 100, 200, 100, callbackInt, (const char*) "m"), -20 ITEM_FLOAT_RANGE("Curr", -1.0f, 1.0f, -1.0f, callbackFloat, (const char*) "mA", 0.01f), -21 ITEM_BASIC("Blink SOS"), -22 ITEM_BASIC("Blink random")); -23// clang-format on -24 -25// Construct the LcdMenu -26LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -27LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -28LcdMenu menu(lcdAdapter); -29KeyboardAdapter keyboard(&menu, &Serial); -30 -31void setup() { -32 Serial.begin(9600); -33 // Initialize LcdMenu with the menu items -34 lcdAdapter.begin(); -35 menu.setScreen(mainScreen); -36} -37 -38void loop() { -39 keyboard.observe(); -40} -41 -42void callbackInt(int value) { -43 // do something with the integer value -44 Serial.println(value); -45} -46 -47void callbackFloat(float value) { -48 // do something with the float value -49 Serial.println(value); -50} + 7#include <renderer/CharacterDisplayRenderer.h> + 8 + 9#define LCD_ROWS 2 +10#define LCD_COLS 16 +11 +12// Declare the callbacks +13void callbackInt(int value); +14void callbackFloat(float value); +15 +16// Initialize the main menu items +17// clang-format off +18MENU_SCREEN(mainScreen, mainItems, +19 ITEM_BASIC("Con"), +20 ITEM_INT_RANGE("Dist", 100, 200, 100, callbackInt, (const char*) "m"), +21 ITEM_FLOAT_RANGE("Curr", -1.0f, 1.0f, -1.0f, callbackFloat, (const char*) "mA", 0.01f), +22 ITEM_BASIC("Blink SOS"), +23 ITEM_BASIC("Blink random")); +24// clang-format on +25 +26// Construct the LcdMenu +27LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +28CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +29LcdMenu menu(renderer); +30KeyboardAdapter keyboard(&menu, &Serial); +31 +32void setup() { +33 Serial.begin(9600); +34 // Initialize LcdMenu with the menu items +35 renderer.begin(); +36 menu.setScreen(mainScreen); +37} +38 +39void loop() { +40 keyboard.observe(); +41} +42 +43void callbackInt(int value) { +44 // do something with the integer value +45 Serial.println(value); +46} +47 +48void callbackFloat(float value) { +49 // do something with the float value +50 Serial.println(value); +51}

    diff --git a/reference/samples/ItemBack.html b/reference/samples/ItemBack.html index 65f09019..f8868b97 100644 --- a/reference/samples/ItemBack.html +++ b/reference/samples/ItemBack.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -217,44 +222,45 @@

    ItemBack 4#include <MenuScreen.h> 5#include <display/LiquidCrystal_I2CAdapter.h> 6#include <input/KeyboardAdapter.h> - 7 - 8#define LCD_ROWS 2 - 9#define LCD_COLS 16 -10 -11extern MenuScreen* settingsScreen; -12 -13// Define the main menu -14// clang-format off -15MENU_SCREEN(mainScreen, mainItems, -16 ITEM_BASIC("Start service"), -17 ITEM_BASIC("Connect to WiFi"), -18 ITEM_SUBMENU("Settings", settingsScreen), -19 ITEM_BASIC("Blink SOS"), -20 ITEM_BASIC("Blink random")); -21 -22// Create submenu and precise its parent -23MENU_SCREEN(settingsScreen, settingsItems, -24 ITEM_BASIC("Backlight"), -25 ITEM_BASIC("Contrast"), -26 ITEM_BACK()); -27// clang-format on -28 -29LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -30LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -31LcdMenu menu(lcdAdapter); -32 -33// Initialize the KeyboardAdapter -34KeyboardAdapter keyboard(&menu, &Serial); -35 -36void setup() { -37 Serial.begin(9600); -38 lcdAdapter.begin(); -39 menu.setScreen(mainScreen); -40} -41 -42void loop() { -43 keyboard.observe(); -44} + 7#include <renderer/CharacterDisplayRenderer.h> + 8 + 9#define LCD_ROWS 2 +10#define LCD_COLS 16 +11 +12extern MenuScreen* settingsScreen; +13 +14// Define the main menu +15// clang-format off +16MENU_SCREEN(mainScreen, mainItems, +17 ITEM_BASIC("Start service"), +18 ITEM_BASIC("Connect to WiFi"), +19 ITEM_SUBMENU("Settings", settingsScreen), +20 ITEM_BASIC("Blink SOS"), +21 ITEM_BASIC("Blink random")); +22 +23// Create submenu and precise its parent +24MENU_SCREEN(settingsScreen, settingsItems, +25 ITEM_BASIC("Backlight"), +26 ITEM_BASIC("Contrast"), +27 ITEM_BACK()); +28// clang-format on +29 +30LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +31CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +32LcdMenu menu(renderer); +33 +34// Initialize the KeyboardAdapter +35KeyboardAdapter keyboard(&menu, &Serial); +36 +37void setup() { +38 Serial.begin(9600); +39 renderer.begin(); +40 menu.setScreen(mainScreen); +41} +42 +43void loop() { +44 keyboard.observe(); +45} diff --git a/reference/samples/KeyboardAdapter.html b/reference/samples/KeyboardAdapter.html index 9ae23c93..f988a50c 100644 --- a/reference/samples/KeyboardAdapter.html +++ b/reference/samples/KeyboardAdapter.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -216,46 +221,47 @@

    KeyboardAdapter 3#include <MenuScreen.h> 4#include <display/LiquidCrystal_I2CAdapter.h> 5#include <input/KeyboardAdapter.h> - 6 - 7#define LCD_ROWS 2 - 8#define LCD_COLS 16 - 9 -10// Create your charset -11const char* charset = "0123456789"; -12 -13// Declare the call back function -14void inputCallback(char* value); -15 -16// clang-format off -17MENU_SCREEN(mainScreen, mainItems, -18 ITEM_INPUT_CHARSET("Con", "0123456", charset, inputCallback), -19 ITEM_BASIC("Connect to WiFi"), -20 ITEM_BASIC("Blink SOS"), -21 ITEM_BASIC("Blink random")); -22// clang-format on -23 -24LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -25LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -26LcdMenu menu(lcdAdapter); -27KeyboardAdapter keyboard(&menu, &Serial); -28 -29void setup() { -30 Serial.begin(9600); -31 lcdAdapter.begin(); -32 menu.setScreen(mainScreen); -33} -34 -35void loop() { -36 keyboard.observe(); -37} -38/** -39 * Define callback -40 */ -41void inputCallback(char* value) { -42 // Do stuff with value -43 Serial.print(F("# ")); -44 Serial.println(value); -45} + 6#include <renderer/CharacterDisplayRenderer.h> + 7 + 8#define LCD_ROWS 2 + 9#define LCD_COLS 16 +10 +11// Create your charset +12const char* charset = "0123456789"; +13 +14// Declare the call back function +15void inputCallback(char* value); +16 +17// clang-format off +18MENU_SCREEN(mainScreen, mainItems, +19 ITEM_INPUT_CHARSET("Con", "0123456", charset, inputCallback), +20 ITEM_BASIC("Connect to WiFi"), +21 ITEM_BASIC("Blink SOS"), +22 ITEM_BASIC("Blink random")); +23// clang-format on +24 +25LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +26CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +27LcdMenu menu(renderer); +28KeyboardAdapter keyboard(&menu, &Serial); +29 +30void setup() { +31 Serial.begin(9600); +32 renderer.begin(); +33 menu.setScreen(mainScreen); +34} +35 +36void loop() { +37 keyboard.observe(); +38} +39/** +40 * Define callback +41 */ +42void inputCallback(char* value) { +43 // Do stuff with value +44 Serial.print(F("# ")); +45 Serial.println(value); +46} diff --git a/reference/samples/List.html b/reference/samples/List.html index a9a42672..8aa0e963 100644 --- a/reference/samples/List.html +++ b/reference/samples/List.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -216,59 +221,60 @@

    List 3#include <MenuScreen.h> 4#include <display/LiquidCrystal_I2CAdapter.h> 5#include <input/KeyboardAdapter.h> - 6 - 7#define LCD_ROWS 2 - 8#define LCD_COLS 16 - 9 -10// Declare the callbacks -11void colorsCallback(uint8_t pos); -12void numsCallback(uint8_t pos); -13 -14// Declare the array -15extern String colors[]; -16// Initialize the array -17String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"}; -18 -19// Declare the array -20extern String nums[]; -21// Initialize the array -22String nums[] = {"5", "7", "9", "12", "32"}; -23 -24// Initialize the main menu items -25// clang-format off -26MENU_SCREEN(mainScreen, mainItems, -27 ITEM_BASIC("List demo"), -28 ITEM_STRING_LIST("Col", colors, 8, colorsCallback), -29 ITEM_STRING_LIST("Num", nums, 5, numsCallback), -30 ITEM_BASIC("Example")); -31// clang-format on -32 -33// Construct the LcdMenu -34LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -35LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -36LcdMenu menu(lcdAdapter); -37KeyboardAdapter keyboard(&menu, &Serial); -38 -39void setup() { -40 Serial.begin(9600); -41 lcdAdapter.begin(); -42 menu.setScreen(mainScreen); -43} -44 -45void loop() { -46 keyboard.observe(); -47} -48 -49// Define the callbacks -50void colorsCallback(uint8_t pos) { -51 // do something with the index -52 Serial.println(colors[pos]); -53} -54 -55void numsCallback(uint8_t pos) { -56 // do something with the index -57 Serial.println(nums[pos]); -58} + 6#include <renderer/CharacterDisplayRenderer.h> + 7 + 8#define LCD_ROWS 2 + 9#define LCD_COLS 16 +10 +11// Declare the callbacks +12void colorsCallback(uint8_t pos); +13void numsCallback(uint8_t pos); +14 +15// Declare the array +16extern String colors[]; +17// Initialize the array +18String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"}; +19 +20// Declare the array +21extern String nums[]; +22// Initialize the array +23String nums[] = {"5", "7", "9", "12", "32"}; +24 +25// Initialize the main menu items +26// clang-format off +27MENU_SCREEN(mainScreen, mainItems, +28 ITEM_BASIC("List demo"), +29 ITEM_STRING_LIST("Col", colors, 8, colorsCallback), +30 ITEM_STRING_LIST("Num", nums, 5, numsCallback), +31 ITEM_BASIC("Example")); +32// clang-format on +33 +34// Construct the LcdMenu +35LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +36CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +37LcdMenu menu(renderer); +38KeyboardAdapter keyboard(&menu, &Serial); +39 +40void setup() { +41 Serial.begin(9600); +42 renderer.begin(); +43 menu.setScreen(mainScreen); +44} +45 +46void loop() { +47 keyboard.observe(); +48} +49 +50// Define the callbacks +51void colorsCallback(uint8_t pos) { +52 // do something with the index +53 Serial.println(colors[pos]); +54} +55 +56void numsCallback(uint8_t pos) { +57 // do something with the index +58 Serial.println(nums[pos]); +59} diff --git a/reference/samples/MenuTimeout.html b/reference/samples/MenuTimeout.html index 3c9bdfad..913f9439 100644 --- a/reference/samples/MenuTimeout.html +++ b/reference/samples/MenuTimeout.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -215,40 +220,42 @@

    MenuTimeout 2#include <MenuScreen.h> 3#include <display/LiquidCrystal_I2CAdapter.h> 4#include <input/KeyboardAdapter.h> - 5 - 6#define LCD_ROWS 2 - 7#define LCD_COLS 16 - 8 - 9// clang-format off -10MENU_SCREEN(mainScreen, mainItems, -11 ITEM_BASIC("Start service"), -12 ITEM_BASIC("Connect to WiFi"), -13 ITEM_BASIC("Settings"), -14 ITEM_BASIC("Blink SOS"), -15 ITEM_BASIC("Blink random")); -16// clang-format on -17 -18LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -19LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -20LcdMenu menu(lcdAdapter); -21 -22// Initialize the KeyboardAdapter -23KeyboardAdapter keyboard(&menu, &Serial); -24 -25void setup() { -26 Serial.begin(9600); -27 lcdAdapter.begin(); -28 menu.setScreen(mainScreen); -29} -30 -31void loop() { -32 /** -33 * IMPORTANT: You must call this function for the timeout to work -34 * The default timeout is 10000ms -35 */ -36 lcdAdapter.updateTimer(); -37 keyboard.observe(); -38} + 5#include <renderer/CharacterDisplayRenderer.h> + 6 + 7#define LCD_ROWS 2 + 8#define LCD_COLS 16 + 9 +10// clang-format off +11MENU_SCREEN(mainScreen, mainItems, +12 ITEM_BASIC("Start service"), +13 ITEM_BASIC("Connect to WiFi"), +14 ITEM_BASIC("Settings"), +15 ITEM_BASIC("Blink SOS"), +16 ITEM_BASIC("Blink random")); +17// clang-format on +18 +19LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +20LiquidCrystal_I2CAdapter lcdAdapter(&lcd); +21CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS); +22LcdMenu menu(renderer); +23 +24// Initialize the KeyboardAdapter +25KeyboardAdapter keyboard(&menu, &Serial); +26 +27void setup() { +28 Serial.begin(9600); +29 renderer.begin(); +30 menu.setScreen(mainScreen); +31} +32 +33void loop() { +34 /** +35 * IMPORTANT: You must call this function for the timeout to work +36 * The default timeout is 10000ms +37 */ +38 renderer.updateTimer(); +39 keyboard.observe(); +40} diff --git a/reference/samples/RTOS.html b/reference/samples/RTOS.html index 32d99fe2..fd1a6988 100644 --- a/reference/samples/RTOS.html +++ b/reference/samples/RTOS.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -219,116 +224,118 @@

    RTOS 6#include <MenuScreen.h> 7#include <display/LiquidCrystal_I2CAdapter.h> 8#include <input/KeyboardAdapter.h> - 9 - 10// 2x20 LCD Display - 11#define LCD_ROWS 4 - 12#define LCD_COLS 20 - 13 - 14float temperature1; - 15float temperature2; - 16float temperature3; - 17 - 18bool relay1State, relay2State, relay3State; - 19 - 20// Relay 1 Toggle - 21void toggleRelay1(bool isOn) { - 22 printLog(F("relay1State")); - 23} - 24 - 25// Relay 2 Toggle - 26void toggleRelay2(bool isOn) { - 27 printLog(F("relay2State")); - 28} - 29 - 30// Relay 3 Toggle - 31void toggleRelay3(bool isOn) { - 32 printLog(F("relay3State")); - 33} - 34 - 35LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); - 36LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); - 37LcdMenu menu(lcdAdapter); - 38KeyboardAdapter keyboard(&menu, &Serial); - 39 - 40extern MenuScreen* relayScreen; - 41extern MenuScreen* tempScreen; - 42 - 43// clang-format off - 44MENU_SCREEN(mainScreen, mainItems, - 45 ITEM_BASIC("Relay Test"), - 46 ITEM_SUBMENU("Temp. Observing", tempScreen), - 47 ITEM_BASIC("Hello World"), - 48 ITEM_BASIC("I'm World")); - 49// clang-format on - 50 - 51// Sub Menu 1: Relays - 52// clang-format off - 53MENU_SCREEN(relayScreen, relayItems, - 54 ITEM_TOGGLE("Relay 1", toggleRelay1), - 55 ITEM_TOGGLE("Relay 2", toggleRelay2), - 56 ITEM_TOGGLE("Relay 3", toggleRelay3)); - 57// clang-format on - 58 - 59// Sub Menu 2: Temperature Values - 60// clang-format off - 61MENU_SCREEN(tempScreen, tempItems, - 62 ITEM_BASIC(""), - 63 ITEM_BASIC(""), - 64 ITEM_BASIC("")); - 65// clang-format on - 66 - 67// RTOS func. to measure temperature value - 68static void tempMeas(void* pvParameters) { - 69 (void)pvParameters; - 70 for (;;) { - 71 //-------------------BEGIN: TEST WITH RANDOM------------------// - 72 temperature1 = random(1, 1000) / 100.0; // Generate random float - 73 temperature2 = random(1, 2000) / 100.0; // Generate random float - 74 temperature3 = random(1, 3000) / 100.0; // Generate random float - 75 //-------------------END: TEST WITH RANDOM--------------------// - 76 - 77 char buffer1[8]; - 78 tempItems[0]->setText(dtostrf(temperature1, 5, 2, buffer1)); - 79 - 80 char buffer2[8]; - 81 tempItems[1]->setText(dtostrf(temperature2, 5, 2, buffer2)); - 82 - 83 char buffer3[8]; - 84 tempItems[2]->setText(dtostrf(temperature3, 5, 2, buffer3)); - 85 - 86 if (menu.getScreen() == tempScreen) { - 87 menu.refresh(); - 88 } - 89 vTaskDelay(5000 / portTICK_PERIOD_MS); // wait for five seconds - 90 } - 91} - 92 - 93// RTOS func to read serial input from keyboard - 94static void keyPad(void* pvParameters) { - 95 (void)pvParameters; // Unused parameter - 96 - 97 for (;;) { - 98 keyboard.observe(); - 99 vTaskDelay(1); -100 } -101} -102 -103void setup() { -104 Serial.begin(9600); -105 // LCD activation -106 lcdAdapter.begin(); -107 menu.setScreen(mainScreen); -108 // Run RTOS func. -109 xTaskCreate(keyPad, "keyPad", 128, NULL, tskIDLE_PRIORITY + 2, NULL); -110 xTaskCreate(tempMeas, "tempMeas", 128, NULL, tskIDLE_PRIORITY + 1, NULL); -111 // Setup random seed -112 pinMode(A0, INPUT); -113 randomSeed(analogRead(A0)); -114} -115 -116void loop() { -117 lcdAdapter.updateTimer(); -118} + 9#include <renderer/CharacterDisplayRenderer.h> + 10 + 11// 2x20 LCD Display + 12#define LCD_ROWS 4 + 13#define LCD_COLS 20 + 14 + 15float temperature1; + 16float temperature2; + 17float temperature3; + 18 + 19bool relay1State, relay2State, relay3State; + 20 + 21// Relay 1 Toggle + 22void toggleRelay1(bool isOn) { + 23 printLog(F("relay1State")); + 24} + 25 + 26// Relay 2 Toggle + 27void toggleRelay2(bool isOn) { + 28 printLog(F("relay2State")); + 29} + 30 + 31// Relay 3 Toggle + 32void toggleRelay3(bool isOn) { + 33 printLog(F("relay3State")); + 34} + 35 + 36LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); + 37LiquidCrystal_I2CAdapter lcdAdapter(&lcd); + 38CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS); + 39LcdMenu menu(renderer); + 40KeyboardAdapter keyboard(&menu, &Serial); + 41 + 42extern MenuScreen* relayScreen; + 43extern MenuScreen* tempScreen; + 44 + 45// clang-format off + 46MENU_SCREEN(mainScreen, mainItems, + 47 ITEM_BASIC("Relay Test"), + 48 ITEM_SUBMENU("Temp. Observing", tempScreen), + 49 ITEM_BASIC("Hello World"), + 50 ITEM_BASIC("I'm World")); + 51// clang-format on + 52 + 53// Sub Menu 1: Relays + 54// clang-format off + 55MENU_SCREEN(relayScreen, relayItems, + 56 ITEM_TOGGLE("Relay 1", toggleRelay1), + 57 ITEM_TOGGLE("Relay 2", toggleRelay2), + 58 ITEM_TOGGLE("Relay 3", toggleRelay3)); + 59// clang-format on + 60 + 61// Sub Menu 2: Temperature Values + 62// clang-format off + 63MENU_SCREEN(tempScreen, tempItems, + 64 ITEM_BASIC(""), + 65 ITEM_BASIC(""), + 66 ITEM_BASIC("")); + 67// clang-format on + 68 + 69// RTOS func. to measure temperature value + 70static void tempMeas(void* pvParameters) { + 71 (void)pvParameters; + 72 for (;;) { + 73 //-------------------BEGIN: TEST WITH RANDOM------------------// + 74 temperature1 = random(1, 1000) / 100.0; // Generate random float + 75 temperature2 = random(1, 2000) / 100.0; // Generate random float + 76 temperature3 = random(1, 3000) / 100.0; // Generate random float + 77 //-------------------END: TEST WITH RANDOM--------------------// + 78 + 79 char buffer1[8]; + 80 tempItems[0]->setText(dtostrf(temperature1, 5, 2, buffer1)); + 81 + 82 char buffer2[8]; + 83 tempItems[1]->setText(dtostrf(temperature2, 5, 2, buffer2)); + 84 + 85 char buffer3[8]; + 86 tempItems[2]->setText(dtostrf(temperature3, 5, 2, buffer3)); + 87 + 88 if (menu.getScreen() == tempScreen) { + 89 menu.refresh(); + 90 } + 91 vTaskDelay(5000 / portTICK_PERIOD_MS); // wait for five seconds + 92 } + 93} + 94 + 95// RTOS func to read serial input from keyboard + 96static void keyPad(void* pvParameters) { + 97 (void)pvParameters; // Unused parameter + 98 + 99 for (;;) { +100 keyboard.observe(); +101 vTaskDelay(1); +102 } +103} +104 +105void setup() { +106 Serial.begin(9600); +107 // LCD activation +108 renderer.begin(); +109 menu.setScreen(mainScreen); +110 // Run RTOS func. +111 xTaskCreate(keyPad, "keyPad", 128, NULL, tskIDLE_PRIORITY + 2, NULL); +112 xTaskCreate(tempMeas, "tempMeas", 128, NULL, tskIDLE_PRIORITY + 1, NULL); +113 // Setup random seed +114 pinMode(A0, INPUT); +115 randomSeed(analogRead(A0)); +116} +117 +118void loop() { +119 renderer.updateTimer(); +120} diff --git a/reference/samples/SimpleInput.html b/reference/samples/SimpleInput.html index 696bf870..c48573b1 100644 --- a/reference/samples/SimpleInput.html +++ b/reference/samples/SimpleInput.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -216,43 +221,44 @@

    SimpleInput 3#include <MenuScreen.h> 4#include <display/LiquidCrystal_I2CAdapter.h> 5#include <input/KeyboardAdapter.h> - 6 - 7#define LCD_ROWS 2 - 8#define LCD_COLS 16 - 9 -10// Declare the call back function -11void inputCallback(char* value); -12 -13// clang-format off -14MENU_SCREEN(mainScreen, mainItems, -15 ITEM_INPUT("Con", inputCallback), -16 ITEM_BASIC("Connect to WiFi"), -17 ITEM_BASIC("Blink SOS"), -18 ITEM_BASIC("Blink random")); -19// clang-format on -20 -21LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -22LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -23LcdMenu menu(lcdAdapter); -24KeyboardAdapter keyboard(&menu, &Serial); -25 -26void setup() { -27 Serial.begin(9600); -28 lcdAdapter.begin(); -29 menu.setScreen(mainScreen); -30} -31 -32void loop() { -33 keyboard.observe(); -34} -35 -36/** -37 * Define callback -38 */ -39void inputCallback(char* value) { -40 // do something with the input value -41 Serial.println(value); -42} + 6#include <renderer/CharacterDisplayRenderer.h> + 7 + 8#define LCD_ROWS 2 + 9#define LCD_COLS 16 +10 +11// Declare the call back function +12void inputCallback(char* value); +13 +14// clang-format off +15MENU_SCREEN(mainScreen, mainItems, +16 ITEM_INPUT("Con", inputCallback), +17 ITEM_BASIC("Connect to WiFi"), +18 ITEM_BASIC("Blink SOS"), +19 ITEM_BASIC("Blink random")); +20// clang-format on +21 +22LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +23CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +24LcdMenu menu(renderer); +25KeyboardAdapter keyboard(&menu, &Serial); +26 +27void setup() { +28 Serial.begin(9600); +29 renderer.begin(); +30 menu.setScreen(mainScreen); +31} +32 +33void loop() { +34 keyboard.observe(); +35} +36 +37/** +38 * Define callback +39 */ +40void inputCallback(char* value) { +41 // do something with the input value +42 Serial.println(value); +43} diff --git a/reference/samples/SimpleRotary.html b/reference/samples/SimpleRotary.html index e02d2d73..dd360ac4 100644 --- a/reference/samples/SimpleRotary.html +++ b/reference/samples/SimpleRotary.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -219,53 +224,55 @@

    SimpleRotary 6#include <SimpleRotary.h> 7#include <display/LiquidCrystal_I2CAdapter.h> 8#include <input/SimpleRotaryAdapter.h> - 9 -10#define LCD_ROWS 2 -11#define LCD_COLS 16 -12 -13// Declare the callbacks -14void callback(int pos); -15void colorsCallback(uint8_t pos); -16void toggleBacklight(bool isOn); -17 -18String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"}; -19 -20// clang-format off -21MENU_SCREEN(mainScreen, mainItems, -22 ITEM_BASIC("Connect to WiFi"), -23 ITEM_STRING_LIST("Color", colors, 8, colorsCallback), -24 ITEM_BASIC("Blink SOS"), -25 ITEM_INT_RANGE("Dist", 0, 50, 0, callback, (const char*) "m"), -26 ITEM_TOGGLE("Backlight", toggleBacklight), -27 ITEM_BASIC("Blink random")); -28// clang-format on -29 -30LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -31LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -32LcdMenu menu(lcdAdapter); -33SimpleRotary encoder(2, 3, 4); -34SimpleRotaryAdapter rotaryInput(&menu, &encoder); -35 -36void setup() { -37 Serial.begin(9600); -38 lcdAdapter.begin(); -39 menu.setScreen(mainScreen); -40} -41 -42void loop() { rotaryInput.observe(); } + 9#include <renderer/CharacterDisplayRenderer.h> +10 +11#define LCD_ROWS 2 +12#define LCD_COLS 16 +13 +14// Declare the callbacks +15void callback(int pos); +16void colorsCallback(uint8_t pos); +17void toggleBacklight(bool isOn); +18 +19String colors[] = {"Red", "Green", "Blue", "Orange", "Aqua", "Yellow", "Purple", "Pink"}; +20 +21// clang-format off +22MENU_SCREEN(mainScreen, mainItems, +23 ITEM_BASIC("Connect to WiFi"), +24 ITEM_STRING_LIST("Color", colors, 8, colorsCallback), +25 ITEM_BASIC("Blink SOS"), +26 ITEM_INT_RANGE("Dist", 0, 50, 0, callback, (const char*) "m"), +27 ITEM_TOGGLE("Backlight", toggleBacklight), +28 ITEM_BASIC("Blink random")); +29// clang-format on +30 +31LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +32LiquidCrystal_I2CAdapter lcdAdapter(&lcd); +33CharacterDisplayRenderer renderer(&lcdAdapter, LCD_COLS, LCD_ROWS); +34LcdMenu menu(renderer); +35SimpleRotary encoder(2, 3, 4); +36SimpleRotaryAdapter rotaryInput(&menu, &encoder); +37 +38void setup() { +39 Serial.begin(9600); +40 renderer.begin(); +41 menu.setScreen(mainScreen); +42} 43 -44// Define the callbacks -45void toggleBacklight(bool isOn) { -46 lcdAdapter.setBacklight(isOn); -47} -48 -49void callback(int pos) { -50 Serial.println(pos); -51} -52 -53void colorsCallback(uint8_t pos) { -54 Serial.println(colors[pos]); -55} +44void loop() { rotaryInput.observe(); } +45 +46// Define the callbacks +47void toggleBacklight(bool isOn) { +48 lcdAdapter.setBacklight(isOn); +49} +50 +51void callback(int pos) { +52 Serial.println(pos); +53} +54 +55void colorsCallback(uint8_t pos) { +56 Serial.println(colors[pos]); +57} diff --git a/reference/samples/SubMenu.html b/reference/samples/SubMenu.html index 786b17e7..b9c6d7cb 100644 --- a/reference/samples/SubMenu.html +++ b/reference/samples/SubMenu.html @@ -113,6 +113,10 @@
  • Rotary Encoder Adapter
  • +
  • +
  • Reference

    @@ -216,55 +221,56 @@

    SubMenu 3#include <MenuScreen.h> 4#include <display/LiquidCrystal_I2CAdapter.h> 5#include <input/KeyboardAdapter.h> - 6 - 7#define LCD_ROWS 2 - 8#define LCD_COLS 16 - 9 -10extern MenuScreen* settingsScreen; -11extern MenuScreen* settings2Screen; -12 -13// Define the main menu -14// clang-format off -15MENU_SCREEN(mainScreen, mainItems, -16 ITEM_SUBMENU("Settings", settingsScreen), -17 ITEM_BASIC("Start service"), -18 ITEM_BASIC("Connect to WiFi"), -19 ITEM_BASIC("Blink SOS"), -20 ITEM_BASIC("Blink random"), -21 ITEM_SUBMENU("Settings 2", settings2Screen)); -22 -23// Create submenu and precise its parent -24MENU_SCREEN(settingsScreen, settingsItems, -25 ITEM_BASIC("Backlight"), -26 ITEM_BASIC("Contrast"), -27 ITEM_BASIC("Contrast1"), -28 ITEM_BASIC("Contrast2"), -29 ITEM_BASIC("Contrast3"), -30 ITEM_BASIC("Contrast4"), -31 ITEM_BASIC("Contrast5"), -32 ITEM_BASIC("Contrast6"), -33 ITEM_BASIC("Contrast7"), -34 ITEM_SUBMENU("Settings2", settings2Screen)); -35 -36MENU_SCREEN(settings2Screen, settings2Items, -37 ITEM_BASIC("Backlight"), -38 ITEM_BASIC("Contrast")); -39// clang-format on -40 -41LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); -42LiquidCrystal_I2CAdapter lcdAdapter(&lcd, LCD_COLS, LCD_ROWS); -43LcdMenu menu(lcdAdapter); -44KeyboardAdapter keyboard(&menu, &Serial); -45 -46void setup() { -47 Serial.begin(9600); -48 lcdAdapter.begin(); -49 menu.setScreen(mainScreen); -50} -51 -52void loop() { -53 keyboard.observe(); -54} + 6#include <renderer/CharacterDisplayRenderer.h> + 7 + 8#define LCD_ROWS 2 + 9#define LCD_COLS 16 +10 +11extern MenuScreen* settingsScreen; +12extern MenuScreen* settings2Screen; +13 +14// Define the main menu +15// clang-format off +16MENU_SCREEN(mainScreen, mainItems, +17 ITEM_SUBMENU("Settings", settingsScreen), +18 ITEM_BASIC("Start service"), +19 ITEM_BASIC("Connect to WiFi"), +20 ITEM_BASIC("Blink SOS"), +21 ITEM_BASIC("Blink random"), +22 ITEM_SUBMENU("Settings 2", settings2Screen)); +23 +24// Create submenu and precise its parent +25MENU_SCREEN(settingsScreen, settingsItems, +26 ITEM_BASIC("Backlight"), +27 ITEM_BASIC("Contrast"), +28 ITEM_BASIC("Contrast1"), +29 ITEM_BASIC("Contrast2"), +30 ITEM_BASIC("Contrast3"), +31 ITEM_BASIC("Contrast4"), +32 ITEM_BASIC("Contrast5"), +33 ITEM_BASIC("Contrast6"), +34 ITEM_BASIC("Contrast7"), +35 ITEM_SUBMENU("Settings2", settings2Screen)); +36 +37MENU_SCREEN(settings2Screen, settings2Items, +38 ITEM_BASIC("Backlight"), +39 ITEM_BASIC("Contrast")); +40// clang-format on +41 +42LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS); +43CharacterDisplayRenderer renderer(new LiquidCrystal_I2CAdapter(&lcd), LCD_COLS, LCD_ROWS); +44LcdMenu menu(renderer); +45KeyboardAdapter keyboard(&menu, &Serial); +46 +47void setup() { +48 Serial.begin(9600); +49 renderer.begin(); +50 menu.setScreen(mainScreen); +51} +52 +53void loop() { +54 keyboard.observe(); +55} diff --git a/reference/samples/index.html b/reference/samples/index.html index 28791625..3ffa5bf6 100644 --- a/reference/samples/index.html +++ b/reference/samples/index.html @@ -19,7 +19,7 @@ - +