Skip to content

Commit fcbb39c

Browse files
author
dave
committed
Improved documentation
1 parent 6adeeab commit fcbb39c

File tree

8 files changed

+131
-24
lines changed

8 files changed

+131
-24
lines changed

examples/arduino32/dynamicMenuItems/dynamicMenuItems.emf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@
386386
},
387387
{
388388
"name": "DISPLAY_BUFFER_SIZE",
389-
"latestValue": "0",
389+
"latestValue": "20",
390390
"subsystem": "DISPLAY"
391391
},
392392
{
@@ -521,12 +521,12 @@
521521
},
522522
{
523523
"name": "ITEM_FONT",
524-
"latestValue": "def:,1",
524+
"latestValue": "ada:OpenSansCyrillicLatin12,0",
525525
"subsystem": "THEME"
526526
},
527527
{
528528
"name": "TITLE_FONT",
529-
"latestValue": "def:,1",
529+
"latestValue": "ada:OpenSansCyrillicLatin12,0",
530530
"subsystem": "THEME"
531531
},
532532
{
@@ -541,7 +541,7 @@
541541
},
542542
{
543543
"name": "USE_TC_UNICODE",
544-
"latestValue": "false",
544+
"latestValue": "true",
545545
"subsystem": "THEME"
546546
},
547547
{

examples/arduino32/dynamicMenuItems/dynamicMenuItems.ino

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
* This example shows how to create scroll choices, lists, and dynamically add items to both dialogs and existing menus
33
* at runtime.
44
*
5-
* Test environment: Seeed MG126 - Adafruit 128x128 display, encoder on device pins.
5+
* Test environment: Seeed MG126 - Matrix Keyboard, Adafruit 128x128 display, rotary encoder
66
*
77
* Although it's set up to run on SAMD there is no reason it could not be easily reconfigured for any
8-
* other board.
8+
* other board. This is one of the biggest advantages of this framework, moving boards is easier.
99
*
1010
* Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/
11+
* Dialogs: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/
12+
* MenuManager: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menumanager-and-iteration/
1113
*/
1214

1315
#include "dynamicMenuItems_menu.h"
@@ -17,14 +19,17 @@
1719
#include <tcMenuVersion.h>
1820
#include <IoLogging.h>
1921

20-
// Pizza toppings that we forward referenced in the scroll choice item, when in RAM or EEPROM then they are declared in
21-
// a flat array based on the item size.
22-
// 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
22+
//
23+
// ScrollChoice menu items when using data in RAM mode reference a fixed width array in your code, these will be
24+
// created by the code generator if needed. Genreally they are an array of char large enough to hold all items.
25+
// In this case they are pizza toppings, each zero terminated.
26+
// 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
2327
char pizzaToppings[] = {"Peperoni\0 Onions\0 Olives\0 Sweetcorn\0Mushrooms\0Peppers\0 "};
2428

2529
//
2630
// We now create some menu items that we manually add to the oven menu during initialisation. We set the sub menu child
27-
// to be the first of the two menu items, which are provided in a linked list.
31+
// to be the first of the two menu items, which are provided in a linked list. Notice that these are completely created
32+
// RAM, and not program memory.
2833
//
2934
BooleanMenuInfo minfoOvenFull = { "Start Oven", nextRandomId(), 0xffff, 1, NO_CALLBACK, NAMING_YES_NO};
3035
BooleanMenuItem menuOvenFull(&minfoOvenFull, false, nullptr, false);
@@ -48,10 +53,13 @@ public:
4853
allowDialogBack = allow;
4954
}
5055

56+
// called when the structure of the menu has completely changed, IE menu items added or removed from the tree
5157
void structureHasChanged() override {
5258
serdebugF("Structure of menu tree has changed, IE item added or removed!");
5359
}
5460

61+
// editing is about to start on an item, or a submenu is about to be shown, return true to show the menu, false
62+
// to prevent the item from being edited or submenu shown
5563
bool menuEditStarting(MenuItem *item) override {
5664
serdebugF2("Item about to be actioned/editing", item->getId());
5765

@@ -73,10 +81,14 @@ public:
7381
return true; // otherwise, default to allowing all actions.
7482
}
7583

84+
// called when the menu has finished editing or a menu is coming off the display. Note that in the special case
85+
// of a submenu being shown, this will be after the new `menuEditStarted` because that could be prevented by
86+
// returning false.
7687
void menuEditEnded(MenuItem *item) override {
7788
serdebugF2("Edit has completed for ID ", item->getId());
7889
}
7990

91+
// called whenever the active item changes
8092
void activeItemHasChanged(MenuItem* newActive) override {
8193
serdebugF2("The active item changed to ", newActive->getId())
8294
}
@@ -122,13 +134,14 @@ void onTitlePressed(int /*id*/) {
122134
}
123135

124136
void setup() {
125-
// If we use wire or serial, it's our responsibility to prepare it.
126-
Serial.begin(115200);
127-
//while(!Serial);
128-
Wire.begin();
129-
137+
// This example logs using IoLogging, see the following guide to enable
138+
// https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/
139+
IOLOG_START_SERIAL
130140
serEnableLevel(SER_TCMENU_DEBUG, true);
131141

142+
// start wire if using I2C
143+
Wire.begin();
144+
132145
// now we turn off the reset support
133146
renderer.turnOffResetLogic();
134147

@@ -149,12 +162,17 @@ void loop() {
149162
taskManager.runLoop();
150163
}
151164

165+
//
166+
// Helper function to print a menu items name and value
167+
//
152168
void serialPrintMenuItem(MenuItem* item) {
153169
char sz[32];
154170
copyMenuItemNameAndValue(item, sz, sizeof sz);
155171
Serial.println(sz);
156172
}
157173

174+
//
175+
// Called when the start cooking menu item is clicked. It prints all the associated menu items out
158176
void CALLBACK_FUNCTION onStartCooking(int id) {
159177
Serial.println("We are making pizza!");
160178
serialPrintMenuItem(&menuPizzaMakerOvenTemp);
@@ -172,6 +190,8 @@ RENDERING_CALLBACK_NAME_INVOKE(fnExtraDialogLine, textItemRenderFn, "Detail: ",
172190
TextMenuItem secondItem(fnExtraDialogLine, nextRandomId(), 12, nullptr);
173191

174192
void CALLBACK_FUNCTION onDialogInfo(int id) {
193+
// withMenuDialogIfAvailable checks if the dialog can be presented now, and if so will call the function
194+
// provided with the dialog as the parameter. you then just prepare the dialog to be shown.
175195
withMenuDialogIfAvailable([](MenuBasedDialog* dlg) {
176196
// we set it to have only one button, named close.
177197
dlg->setButtons(BTNTYPE_NONE, BTNTYPE_CLOSE);
@@ -198,20 +218,28 @@ const char pgmQuestionHeader[] PROGMEM = {"Override the title?"};
198218
const char pgmTitleOverride[] PROGMEM = {"Title Overridden"};
199219
taskid_t questionTask = TASKMGR_INVALIDID;
200220
void CALLBACK_FUNCTION onDialogQuestion(int id) {
221+
// withMenuDialogIfAvailable checks if the dialog can be presented now, and if so will call the function
222+
// provided with the dialog as the parameter. you then just prepare the dialog to be shown.
201223
withMenuDialogIfAvailable([] (MenuBasedDialog* dlg) {
224+
// present a dialog with OK and CANCEL buttons with the question message, it has a completion handler.
202225
dlg->setButtons(BTNTYPE_OK, BTNTYPE_CANCEL);
203226
dlg->show(pgmQuestionHeader, true, [](ButtonType btn, void* data) {
204227
// this is the completion task that runs when the dialog is dismissed.
205228
Serial.print("Question result was "); Serial.println(btn);
206229
if(btn == BTNTYPE_OK) {
230+
// here we override the main menu title to a new value
207231
appTitleMenuItem.setTitleOverridePgm(pgmTitleOverride);
208232
}
209233
else {
234+
// here we clear the title override, and put it back to default.
210235
appTitleMenuItem.clearTitleOverride();
211236
}
237+
238+
// we must cancel the task that we started when the dialog was created
212239
taskManager.cancelTask(questionTask);
213240
});
214241

242+
// we create a task that keeps updating the value in the dialog buffer item.
215243
dlg->copyIntoBuffer("...");
216244
questionTask = taskManager.scheduleFixedRate(250, [] {
217245
char sz[10];
@@ -283,6 +311,8 @@ public:
283311
MyDialogController dialogController;
284312

285313
void CALLBACK_FUNCTION onDialogController(int id) {
314+
// withMenuDialogIfAvailable checks if the dialog can be presented now, and if so will call the function
315+
// provided with the dialog as the parameter. you then just prepare the dialog to be shown.
286316
withMenuDialogIfAvailable([](MenuBasedDialog* dlg) {
287317
dlg->setButtons(BTNTYPE_OK, BTNTYPE_CUSTOM0);
288318
dlg->showController(true, &dialogController);

examples/arduino32/dynamicMenuItems/dynamicMenuItems_menu.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
#include <tcMenu.h>
1212
#include "dynamicMenuItems_menu.h"
1313
#include "ThemeCoolBlueTraditional.h"
14+
#include <Fonts/OpenSansCyrillicLatin12.h>
1415

1516
// Global variable declarations
1617
const ConnectorLocalInfo applicationInfo = { "Dynamic Menus", "5f22995e-8da2-49c4-9ec8-d055901003af" };
1718
IoAbstractionRef ioexp_io23017 = ioFrom23017(0x20, ACTIVE_LOW_OPEN, 10);
1819
Adafruit_ST7735 gfx(1, 0, -1);
19-
AdafruitDrawable gfxDrawable(&gfx, 0);
20+
AdafruitDrawable gfxDrawable(&gfx, 20);
2021
GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable);
2122
MatrixKeyboardManager keyboard;
2223
const char keyboardKeys[] = "123A456B789C*0#D";
@@ -98,6 +99,7 @@ void setupMenu() {
9899
keyboard.setRepeatKeyMillis(850, 350);
99100
renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW);
100101
renderer.setUseSliderForAnalog(true);
101-
installCoolBlueTraditionalTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true);
102+
renderer.enableTcUnicode();
103+
installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin12, 0), MenuFontDef(&OpenSansCyrillicLatin12, 0), true);
102104
}
103105

examples/arduino32/dynamicMenuItems/dynamicMenuItems_menu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <Arduino.h>
1515
#include <tcMenu.h>
16+
#include <tcUnicodeHelper.h>
1617
#include "tcMenuAdaFruitGfx.h"
1718
#include <tcMenuKeyboard.h>
1819
#include <RuntimeMenuItem.h>
@@ -27,6 +28,7 @@ extern AdafruitDrawable gfxDrawable;
2728
extern GraphicsDeviceRenderer renderer;
2829
extern MatrixKeyboardManager keyboard;
2930
extern MenuEditingKeyListener tcMenuKeyListener;
31+
extern const UnicodeFont OpenSansCyrillicLatin12[];
3032

3133
// Any externals needed by IO expanders, EEPROMs etc
3234
extern IoAbstractionRef ioexp_io23017;

examples/arduino32/piPicoTftEncoder/piPicoTftEncoder.ino

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ const char* fileNames[] = {
2727
void onTitlePressed(int);
2828

2929
void setup() {
30-
// Initialise serial for logging
31-
// If you're using a pico probe, set build flag LoggingPort=Serial1 and initialise serial port 1.
32-
//Serial.begin(115200);
33-
Serial1.begin(115200);
30+
// This example logs using IoLogging, see the following guide to enable
31+
// https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/
32+
IOLOG_START_SERIAL
3433

3534
// This is added by the code generator, it initialises the menu
3635
setupMenu();

examples/arduino32/picoAdafruitDashboard/dashboardConfig.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
//
2+
// This file contains a simple dashboard that is set up using the dashboard classes
3+
// within the menu library extras. See ref docs:
4+
//
5+
// Reference docs https://www.thecoderscorner.com/ref-docs/tcmenu/html/_drawable_dashboard_8h.html
6+
//
17

28
#include "picoAdafruitDashboard_menu.h"
39
#include <Adafruit_ILI9341.h>
410
#include "dashboardConfig.h"
511

12+
// START a title widget that was built using TcMenu Designers widget generator, see the "Code" menu for the widget
13+
// generator. This is added to both the main renderer and the dashboard.
14+
615
// YesNo icon=0, width=17, height=12, size=36
716
const uint8_t YesNoWidIcon0[] PROGMEM = {
817
0x00,0x40,0x00,0x00,0xe0,0x00,0x00,0xf0,0x01,0x00,0xf8,0x00,0x00,0x7c,0x00,0x04,0x3e,0x00,0x0e,0x1f,
@@ -18,59 +27,105 @@ const uint8_t* const YesNoWidIcons[] PROGMEM = { YesNoWidIcon0, YesNoWidIcon1 };
1827
// Widget Generator yesNo
1928
TitleWidget YesNoWidget(YesNoWidIcons, 2, 17, 12, nullptr);
2029

30+
// END title widget
2131

2232
// TickIcon icon=0, width=17, height=12, size=36
2333
const uint8_t TickIconBitmap0[] PROGMEM = {
2434
0x00,0x40,0x00,0x00,0xe0,0x00,0x00,0xf0,0x01,0x00,0xf8,0x00,0x00,0x7c,0x00,0x04,0x3e,0x00,0x0e,0x1f,
2535
0x00,0x9f,0x0f,0x00,0xfe,0x07,0x00,0xfc,0x03,0x00,0xf8,0x01,0x00,0xf0,0x00,0x00
2636
};
2737

38+
// we define a global pointer to the dashboard, it will be created during the dash setup.
2839
DrawableDashboard* mainDashboard;
2940

41+
// Any value item or scroll choice (integer based items) can have ranges of colors, these allow the color to be
42+
// selected based on the value, IE for a rev-counter above 8000 RPM may be shown in red, otherwise green. These
43+
// represented as below. In this case we are creating for an enum value.
44+
// Note that this is a parameter, not the actual dashboard item, they are defined below
3045
DashDrawParametersIntUpdateRange::IntColorRange drawEnumColorRanges[] {
3146
{ILI9341_YELLOW, ILI9341_RED, 0, 1},
3247
{ILI9341_CYAN, ILI9341_BLUE, 2, 3}
3348
};
3449
DashDrawParametersIntUpdateRange drawEnumWithIntRange(ILI9341_WHITE, ILI9341_BLACK, ILI9341_BLACK, ILI9341_YELLOW,
3550
&RobotoMedium24, drawEnumColorRanges, 2);
3651

52+
// As above we create another one for the analog item, it has two ranges.
53+
// Note that this is a parameter, not the actual dashboard item, they are defined below
3754
DashDrawParametersIntUpdateRange::IntColorRange drawAnalogColorRanges[] {
3855
{ILI9341_LIGHTGREY, ILI9341_BLUE, 0, 50},
3956
{ILI9341_YELLOW, ILI9341_RED, 51, 100}
4057
};
4158
DashDrawParametersIntUpdateRange drawAnalogValueWithIntRange(ILI9341_WHITE, ILI9341_BLACK, ILI9341_BLACK, ILI9341_WHITE,
4259
&RobotoMedium24, drawAnalogColorRanges, 2);
60+
61+
// and lastly we create a simple one for the title.
62+
// Note that this is a parameter, not the actual dashboard item, they are defined below
4363
DashDrawParameters titleDrawParameters(ILI9341_WHITE, ILI9341_BLACK, &RobotoMedium24);
4464

65+
//
66+
// Although the dashboard support provides a wide range of menu drawing capabilities, it does not cover every case
67+
// so you can create a delegate that can do the extra drawing and other functions that are needed. Here is a simple
68+
// example that draws a few extra items onto the display
69+
// For drawing onto device drawble see:
70+
// https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/#drawing-direct-to-the-display-with-devicedrawabl
71+
// For more on the delegate class and all the points where you can extend
72+
// https://www.thecoderscorner.com/ref-docs/tcmenu/html/class_drawable_dashboard_delegate.html
73+
//
4574
class MyDrawableDashboardDelegate : public DrawableDashboardDelegate {
4675
public:
76+
// this is called after the dashboard has opened
4777
void dashboardDidOpen(BaseMenuRenderer *renderer) override {
4878
switches.getEncoder()->changePrecision(320, 100);
4979
}
5080

81+
// this is called before the dashboard draws any items
5182
void dashboardWillDraw(unsigned int encVal, RenderPressMode mode) override {
5283
renderer.getDeviceDrawable()->drawXBitmap(Coord(300, 30), Coord(17, 12), TickIconBitmap0);
5384
}
5485

86+
// this is called after the dashboard has drawn all items, you get the current value of the encoder and the
87+
// current state of the select button.
5588
void dashboardDidDraw(unsigned int encVal, RenderPressMode mode) override {
89+
// get the drawing device from the renderer and its dimensions
5690
DeviceDrawable *pDrawable = renderer.getDeviceDrawable();
5791
const Coord &totalSize = Coord(pDrawable->getDisplayDimensions().x, 20);
92+
93+
// create a dashboard wrapper that can work out if we are on a sub device or the main device.
5894
DrawableWrapper wrapper(pDrawable, &titleDrawParameters, &menuSettings, Coord(0, 200), totalSize);
95+
96+
// now we draw onto the drawable, we don't need to care if it is buffered or not
5997
wrapper.getDrawable()->setDrawColor(wrapper.bgCol());
6098
wrapper.getDrawable()->drawBox(wrapper.offsetLocation(Coord(0, 200)), totalSize, true);
6199
wrapper.getDrawable()->setDrawColor(wrapper.fgCol());
62100
wrapper.getDrawable()->drawBox(wrapper.offsetLocation(Coord(0, 200)), Coord(encVal, 20), true);
101+
102+
// lastly we tell the wrapper that we are done, if needed it will push the buffer to the screen
63103
wrapper.endDraw();
64104
}
65105
} myDrawableDashboardDelegate;
66106

67107
void setupDashboard() {
108+
// Reference docs https://www.thecoderscorner.com/ref-docs/tcmenu/html/_drawable_dashboard_8h.html
109+
110+
// create a dashboard instance, giving it the renderer and drawable, any widgets to display in the top corner,
111+
// and the mode in which it is to operate
68112
mainDashboard = new DrawableDashboard(renderer.getDeviceDrawable(), &renderer, &YesNoWidget,
69113
DrawableDashboard::DASH_ON_RESET_CLICK_EXIT);
114+
115+
// here we tell the dashboard about the delegate we created above.
70116
mainDashboard->setDelegate(&myDrawableDashboardDelegate);
117+
118+
// now prepare the base colors
71119
mainDashboard->setBaseColors(RGB(0, 0, 0), RGB(220, 220, 220));
120+
121+
// here we set up the entries on the dashboard, this is where we provide the menu item and position on the display
122+
// for each entry. A parameter object that we defined above is then associated with an item. Note that more than
123+
// one entry can share a parameter.
72124
mainDashboard->addDrawingItem(&menuAnalog, Coord(0, 0), &drawAnalogValueWithIntRange, 10, nullptr, 10);
73125
mainDashboard->addDrawingItem(&menuEnum, Coord(0, 50), &drawEnumWithIntRange, 10, nullptr, 10);
74126
mainDashboard->addDrawingItem(&menuSettings, Coord(0, 100), &titleDrawParameters, 0, "Dashboard");
127+
128+
// lastly, add the dashboard to the renderer, this is important, the dashboard implements CustomDrawing so it
129+
// handles taking over the display and reset notification.
75130
renderer.setCustomDrawingHandler(mainDashboard);
76-
}
131+
}

0 commit comments

Comments
 (0)