diff --git a/.github/workflows/platformio.yml b/.github/workflows/platformio.yml index 62fbb251..23a82c53 100644 --- a/.github/workflows/platformio.yml +++ b/.github/workflows/platformio.yml @@ -13,19 +13,14 @@ jobs: # - examples/arduino32/nano33ble # - examples/arduino32/picoAdafruitDashboard # - examples/arduino32/picoAw9523LcdEncoder - # - examples/arduino32/piPicoTftTouch # - examples/arduino32/stm32DuinoDemo # MBED # - examples/mbed/stm32EncoderLcdI2c # - examples/mbed/stm32f429FrameBuffer # - examples/mbed/stm32OledEncoder # AVR - - example: examples/avr/adafruitST7735Mega - board: megaatmega2560 - example: examples/avr/analogDfRobot board: megaatmega2560 - - example: examples/avr/analogJoystick1306Ascii - board: megaatmega2560 - example: examples/avr/keyboardEthernetShield board: megaatmega2560 - example: examples/avr/nokia5110 diff --git a/examples/arduino32/colorTftEthernet32/ColorEtherenetCustomDraw.h b/examples/arduino32/colorTftEthernet32/ColorEtherenetCustomDraw.h deleted file mode 100644 index dcb7162e..00000000 --- a/examples/arduino32/colorTftEthernet32/ColorEtherenetCustomDraw.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * This class implements CustomDrawing which means that it can be registered with the renderer - * to be told when the screen is about to reset (become idle basically). This callback will - * also be told when a takeOverDisplay call starts, and then the rendering function is called - * frequently, so you can update the display. - * - * Associated docs: - * https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/renderer-take-over-display/ - */ - -#ifndef TCMENU_EXAMPLE_COLORETHERENETCUSTOMDRAW_H -#define TCMENU_EXAMPLE_COLORETHERENETCUSTOMDRAW_H - -#include -#include "colorTftEthernet32_menu.h" - -// Here we implement the custom drawing capability of the renderer, it allows us to receive reset and custom drawing -// requests. More info in the link below: -// https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/renderer-take-over-display/ -class ColorEthernetCustomDraw : public CustomDrawing { -public: - void reset() override { - // When the display becomes idle, we take over the display, the no-arg version is - // used to indicate you want the custom draw class to do the rendering. - renderer.takeOverDisplay(); - } - - void started(BaseMenuRenderer *currentRenderer) override { - // this method is called by the renderer when the screen is first taken over - // you need to handle the clearing and preparation of the display when first called. - switches.getEncoder()->changePrecision(1000, 500); - gfx.setCursor(0, 0); - gfx.fillRect(0, 0, gfx.width(), gfx.height(), BLACK); - gfx.setFont(nullptr); - gfx.setTextSize(2); - gfx.print("Encoder "); - } - - - void renderLoop(unsigned int currentValue, RenderPressMode pressType) override { - // this method is called by the renderer when the screen is taken in a loop - // it is called at the display refresh interval. "started" is always called - // first. You are provided the current encoder value and state of the OK - // button. If you're using touch screen these value may not be relevant. - - // if the encoder / select button is held, we go back to the menu. - if(pressType == RPRESS_HELD) { - renderer.giveBackDisplay(); - return; - } - - GFXcanvas1 canvas(100, 20); - canvas.fillScreen(BLACK); - canvas.setCursor(0,0); - canvas.print(currentValue); - canvas.setTextSize(2); - gfx.drawBitmap(0, 35, canvas.getBuffer(), 100, 20, WHITE, BLACK); - - } -}; - -#endif //TCMENU_EXAMPLE_COLORETHERENETCUSTOMDRAW_H diff --git a/examples/arduino32/colorTftEthernet32/README.md b/examples/arduino32/colorTftEthernet32/README.md deleted file mode 100644 index 3b432c63..00000000 --- a/examples/arduino32/colorTftEthernet32/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Adafruit_GFX ILI9431 Arduino menu example with Ethernet control - - This example shows a more complex menu with the following components. - - * 320x240 ILI9431 screen controlled via Adafruit_GFX library. - * Rotary encoder wired via a PCF8574 IO expander - * I2C EEPROM device to load and save menu. - * Ethernet shield for MKR range attached. - -Out of the box this is built for an MKR board with an I2C 8574 expander and an I2C EEPROM also attached. For simplicity it does not use DHCP to configure the network interface. Just change the address to one within your networks range. - -In order to connect using the Java API there are two possibilities, either use the connector UI that's shipped with TcMenu, or work with the tcMenu API directly. See [https://github.com/TcMenu/tcMenu]. We'll be building out the API in other languages over time, but you can also write directly to the -protocol, which is very simple. - -The files in this example are as follows: - - * `colorTftEthernet.emf` the menu editor designer file, used only to load menu into the designer. - * `colorTftEthernet32.ino` the main sketch file, this will be modified by designer when new callbacks are added. - * `EthernetTransport.cpp` and `.h` contain the ethernet plugin for tcMenu and should not be altered. Rewritten each code generation - * `tcMenuAdaFruitGfx.cpp` and `.h` contain the graphics drawing plugin and should not be altered. Rewritten each code generation. - * `colorTftEthernet32_menu.cpp` and `.h` contain the definitions of the menu item, and should not be altered. Rewritten each code generation. - \ No newline at end of file diff --git a/examples/arduino32/colorTftEthernet32/ThemeCoolBlueTraditional.h b/examples/arduino32/colorTftEthernet32/ThemeCoolBlueTraditional.h deleted file mode 100644 index 7c249b90..00000000 --- a/examples/arduino32/colorTftEthernet32/ThemeCoolBlueTraditional.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -// -// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() -// - -// tcMenu drawing properties take a 4 color palette for items, titles and actions. -// this renderer shares the color configuration for items and actions. -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; - -void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // first we keep a reference to the screen size, and set the dimensions on the renderer. - auto width = bgr.getDeviceDrawable()->getDisplayDimensions().x; - auto height = bgr.getDeviceDrawable()->getDisplayDimensions().y; - bgr.setDisplayDimensions(width, height); - - // get hold of the item display factory that holds the drawing configuration. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // when an item is active, it will show in these colours instead of the default. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // here we calculate the item padding and row heights based on the resolution of the display - bool medResOrBetter = width > 160; - MenuPadding titlePadding(medResOrBetter ? 4 : 2); - MenuPadding itemPadding(medResOrBetter ? 2 : 1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - // we set the editing and selected icons here based on the row height. - if(needEditingIcons && itemHeight > 12) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defActiveIcon)); - } - else if(needEditingIcons) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - } - - // we tell the library how to draw titles, items and actions by default. - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, titlePadding, titleFont.fontData, titleFont.fontMag, - medResOrBetter ? 3 : 1, titleHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - - // after adjusting the drawing configuration, we must always refresh the cache. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE diff --git a/examples/arduino32/colorTftEthernet32/colorTftEthernet32.ino b/examples/arduino32/colorTftEthernet32/colorTftEthernet32.ino deleted file mode 100644 index f939d294..00000000 --- a/examples/arduino32/colorTftEthernet32/colorTftEthernet32.ino +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Shows how to use adafruit graphics with a TFT panel and an ethernet module. - * This is a 32 bit example, which by default targets 32 bit devices. - * Assumed board for this is a SAMD based MKR board. - * - * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ - * - * For more details see the README.md file in this directory. - */ - -#include "colorTftEthernet32_menu.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "ColorEtherenetCustomDraw.h" -#include - -// contains the tcMenu library included graphical widget title components. -#include "stockIcons/wifiAndConnectionIcons16x12.h" - -// we are going to allow control of the menu over local area network -// so therefore must configure ethernet.. -byte mac[] = { - 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED -}; - -// and we create an analog device with enhanced range because on M. -ArduinoAnalogDevice& analogDevice = internalAnalogDevice(); - -// We add a title widget that shows when a user is connected to the device. Connection icons -// are in the standard icon set we included at the top. -TitleWidget connectedWidget(iconsConnection, 2, 16, 12); - -// We also want to take over the display whenever the screen becomes idle, here we use the CustomDrawing -// technique described in the documentation. See ColorEthernetCustomDraw.h -ColorEthernetCustomDraw myCustomDraw; - -// Here we declare a string in const/PROGMEM for use with a dialog later. Note that this works even on ARM -// boards that don't have separated program memory. -const char pgmHeaderSavedItem[] PROGMEM = "Rom Item Saved"; - -// Start 2nd Encoder -// Here, we use a second rotary encoder to adjust one of the menu items, the button toggles a boolean item -// Here are the fields for the second rotary encoder -// If you only want one encoder you can comment these fields out. -const int encoder2Click = 0; -const int encoder2APin = 2; -const int encoder2BPin = 3; -HardwareRotaryEncoder *secondEncoder; -const int ledPin = 1; -// End 2nd Encoder - -// when there's a change in communication status (connection or disconnection for example) this gets called. -// see further down in the code where we add this to the remote IoT monitor. -void onCommsChange(CommunicationInfo info) { - if(info.remoteNo == 0U) { - connectedWidget.setCurrentState(info.connected ? 1 : 0); - } - // this relies on logging in IoAbstraction's ioLogging.h, to turn it on visit the file for instructions. - serdebugF4("Comms notify (rNo, con, enum)", info.remoteNo, info.connected, info.errorMode); -} - -void setup() { - // This example logs using IoLogging, see the following guide to enable - // https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/ - IOLOG_START_SERIAL - - // we used an i2c device (io8574) so must initialise wire too - Wire.begin(); - - // here we make all menu items except menu voltage wrap around. Wrap means that when the value hits maximum it - // goes back to 0, and when it hits 0 it goes back to maximum. Default is all wrapping off. - menuMgr.setUseWrapAroundEncoder(true); - menuMgr.addEncoderWrapOverride(menuVoltage, false); - - // Often the easiest way to add a comms listener, is to add it to an IoT monitor menu item as we show - // here, as it aggregates all the connection information together. - menuIoTMonitor.registerCommsNotification(onCommsChange); - - // and set up the dac on the 32 bit board. - analogDevice.initPin(A0, DIR_OUT); - analogDevice.initPin(A1, DIR_IN); - - menuShowHidden.setBoolean(false); - - // here we make the menuitem "hidden item" invisible. It will not be displayed. - // here it is done before setupMenu is called, so there's no need to refresh the - // display. If it's done after initialisation, the menu must be reset by calling - // menuMgr.setCurrentMenu(getRoot()); - menuHiddenItem.setVisible(false); - - // set up the widget to appear in the title. - renderer.setFirstWidget(&connectedWidget); - - // set up the menu - setupMenu(); - - // increase SPI speed - gfx.setSPISpeed(10000000UL); - - // and then load back the previous state - menuMgr.load(); - - // spin up the Ethernet library - byte* rawIp = menuIpAddress.getIpAddress(); - IPAddress ipAddr(rawIp[0], rawIp[1], rawIp[2], rawIp[3]); - Ethernet.begin(mac, ipAddr); - - char sz[20]; - menuIpAddress.copyValue(sz, sizeof(sz)); - Serial.print("Ethernet available on ");Serial.println(sz); - - taskManager.scheduleFixedRate(250, [] { - float a1Value = analogDevice.getCurrentFloat(A1); - menuVoltA1.setFloatValue(a1Value * 3.3F); - }); - - // register the custom drawing handler - renderer.setCustomDrawingHandler(&myCustomDraw); - - // set the LED pin that we control as output - switches.getIoAbstraction()->pinMode(ledPin, OUTPUT); - - // we can register call back that is called when the main menu title is pressed, in this case we just show - // the tcMenu version number in a dialog. - setTitlePressedCallback([](int id) { - // withMenuDialogIfAvailable checks if the dialog can be presented now, and if so will call the function - // provided with the dialog as the parameter. you then just prepare the dialog to be shown. - withMenuDialogIfAvailable([](MenuBasedDialog* dlg) { - dlg->setButtons(BTNTYPE_CLOSE, BTNTYPE_NONE); - dlg->showRam("ARM Example", false); - char menuVer[10]; - tccore::copyTcMenuVersion(menuVer, sizeof menuVer); - dlg->copyIntoBuffer(menuVer); - }); - }); - - Serial.println("Setting up second encoder now"); - - // here we want the encoder set to the range of values that menuCurrent takes, this is just for example, - // and you could set the range to anything that is required. We use the callback to update the menu item. - secondEncoder = new HardwareRotaryEncoder(encoder2APin, encoder2BPin, [](int encoderValue) { - menuCurrent.setCurrentValue(encoderValue); - }); - secondEncoder->changePrecision(menuCurrent.getMaximumValue(), menuCurrent.getCurrentValue(), true); - switches.setEncoder(1, secondEncoder); // put it into the 2nd available encoder slot. - - // now, when the additional encoder button is released, we toggle the state of menuPwrDelay. - // it will repeat at 25 * 20 millis before acceleration kicks in. - switches.addSwitch(encoder2Click, [](pinid_t pin, bool held) { - menuPwrDelay.setBoolean(!menuPwrDelay.getBoolean()); - switches.getIoAbstraction()->digitalWriteS(ledPin, menuPwrDelay.getBoolean()); - }, 25); - // End 2nd encoder -} - -void loop() { - taskManager.runLoop(); -} - -void writeToDac() { - // here we show how to convert analog menu items into floating point values - float volts = menuVoltage.getAsFloatingPointValue(); - float curr = menuCurrent.getAsFloatingPointValue(); - - // and now we set the output voltage of A0 using a float between 0..1 - float total = (volts / 64.0F) * (curr / 2.0F); - analogDevice.setCurrentFloat(A0, total); - menuVoltA0.setFloatValue(total); -} - -void CALLBACK_FUNCTION onVoltageChange(int /*id*/) { - writeToDac(); -} - -void CALLBACK_FUNCTION onCurrentChange(int /*id*/) { - writeToDac(); -} - -void CALLBACK_FUNCTION onLimitMode(int /*id*/) { - // TODO - your menu change code -} - -void CALLBACK_FUNCTION onSaveRom(int /*id*/) { - // save out the state, in a real system we could detect power down for this. - menuMgr.save(); -} - -void CALLBACK_FUNCTION onTakeDisplay(int /*id*/) { - renderer.takeOverDisplay(); -} - -void CALLBACK_FUNCTION onRgbChanged(int /*id*/) { - auto colorData = menuRGB.getColorData(); - serdebugF4("RGB changed: ", colorData.red, colorData.green, colorData.blue); -} - -void CALLBACK_FUNCTION onSaveItem(int /*id*/) { - auto itemNo = menuRomLocation.getCurrentValue(); - auto itemSize = menuRomChoice.getItemWidth(); - auto position = menuRomChoice.getEepromStart() + (itemNo * itemSize); - menuMgr.getEepromAbstraction()->writeArrayToRom(position, (const uint8_t*)menuRomText.getTextValue(), 10); - - if(renderer.getDialog()->isInUse()) return; - renderer.getDialog()->setButtons(BTNTYPE_NONE, BTNTYPE_OK); - renderer.getDialog()->show(pgmHeaderSavedItem, true); - renderer.getDialog()->copyIntoBuffer(menuRomText.getTextValue()); -} - -void CALLBACK_FUNCTION onRomLocationChange(int /*id*/) { - auto itemNo = menuRomLocation.getCurrentValue(); - char sz[12]; - auto itemSize = menuRomChoice.getItemWidth(); - menuMgr.getEepromAbstraction()->readIntoMemArray((uint8_t*)sz, menuRomChoice.getEepromStart() + (itemNo * itemSize), 10); - menuRomText.setTextValue(sz); - serdebugF2("Rom data was ", sz) -} - -// -// Here we handle the custom rendering for the runtime list menu item that just counts. We basically get called back -// every time it needs more data. For example when the name is required, when any index value is required or when -// it will be saved to EEPROM or invoked. -// -int CALLBACK_FUNCTION fnRomLocationRtCall(RuntimeMenuItem * item, uint8_t row, RenderFnMode mode, char * buffer, int bufferSize) { - switch(mode) { - case RENDERFN_INVOKE: - onRomLocationChange(int(item->getId())); - return true; - case RENDERFN_NAME: - // TODO - each row has it's own name - 0xff is the parent item - strncpy(buffer, "Rom Location", bufferSize); - return true; - case RENDERFN_VALUE: - // TODO - each row can has its own value - 0xff is the parent item - strncpy(buffer, "Item ", bufferSize); - fastltoa(buffer, row, 3, NOT_PADDED, bufferSize); - return true; - case RENDERFN_EEPROM_POS: return 0xFFFF; // lists are generally not saved to EEPROM - default: return false; - } -} - -void CALLBACK_FUNCTION onShowHidden(int id) { - menuHiddenItem.setVisible(menuShowHidden.getBoolean()); - menuMgr.notifyStructureChanged(); -} diff --git a/examples/arduino32/colorTftEthernet32/colorTftEthernet32_menu.cpp b/examples/arduino32/colorTftEthernet32/colorTftEthernet32_menu.cpp deleted file mode 100644 index 0c642b44..00000000 --- a/examples/arduino32/colorTftEthernet32/colorTftEthernet32_menu.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#include -#include "colorTftEthernet32_menu.h" -#include "ThemeCoolBlueTraditional.h" -#include - -// Global variable declarations -const ConnectorLocalInfo applicationInfo = { "Ada32 Ethernet", "22813e5e-88b1-42d5-9601-4831b2be369b" }; -TcMenuRemoteServer remoteServer(applicationInfo); -IoAbstractionRef ioexp_io8574 = ioFrom8574(0x20, 0); -I2cAt24Eeprom glI2cRom(0x50, PAGESIZE_AT24C128); -EepromAuthenticatorManager authManager(6); -Adafruit_ST7735 gfx(6, 7, 3); -AdafruitDrawable gfxDrawable(&gfx, 0); -GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); -EthernetServer server(3333); -EthernetInitialisation ethernetInitialisation(&server); -EthernetTagValTransport ethernetTransport; -TagValueRemoteServerConnection ethernetConnection(ethernetTransport, ethernetInitialisation); - -// Global Menu Item declarations -const AnyMenuInfo minfoTakeDisplay = { "Take display", 17, 0xffff, 0, onTakeDisplay }; -ActionMenuItem menuTakeDisplay(&minfoTakeDisplay, NULL, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSaveItem = { "Save item", 23, 0xffff, 0, onSaveItem }; -ActionMenuItem menuSaveItem(&minfoSaveItem, NULL, INFO_LOCATION_PGM); -const AnyMenuInfo minfoRomText = { "Rom Text", 21, 0xffff, 0, NO_CALLBACK }; -TextMenuItem menuRomText(&minfoRomText, "", 10, &menuSaveItem, INFO_LOCATION_PGM); -const AnyMenuInfo minfoRomLocation = { "Rom Location", 24, 0xffff, 0, NO_CALLBACK }; -ScrollChoiceMenuItem menuRomLocation(&minfoRomLocation, fnRomLocationRtCall, 0, 10, &menuRomText); -const AnyMenuInfo minfoRomChoice = { "Rom Choice", 25, 14, 0, NO_CALLBACK }; -ScrollChoiceMenuItem menuRomChoice(&minfoRomChoice, 0, 1024, 10, 10, &menuRomLocation); -const SubMenuInfo minfoRomValues = { "Rom Values", 20, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackRomValues(&minfoRomValues, &menuRomChoice, INFO_LOCATION_PGM); -SubMenuItem menuRomValues(&minfoRomValues, &menuBackRomValues, &menuTakeDisplay, INFO_LOCATION_PGM); -const char pgmStrIoTMonitorText[] = { "IoT Monitor" }; -RemoteMenuItem menuIoTMonitor(pgmStrIoTMonitorText, 29, NULL); -const char pgmStrAuthenticatorText[] = { "Authenticator" }; -EepromAuthenticationInfoMenuItem menuAuthenticator(pgmStrAuthenticatorText, NO_CALLBACK, 28, &menuIoTMonitor); -const AnyMenuInfo minfoIpAddress = { "Ip Address", 15, 10, 0, NO_CALLBACK }; -IpAddressMenuItem menuIpAddress(&minfoIpAddress, IpAddressStorage(127, 0, 0, 1), &menuAuthenticator, INFO_LOCATION_PGM); -const SubMenuInfo minfoConnectivity = { "Connectivity", 14, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackConnectivity(&minfoConnectivity, &menuIpAddress, INFO_LOCATION_PGM); -SubMenuItem menuConnectivity(&minfoConnectivity, &menuBackConnectivity, &menuRomValues, INFO_LOCATION_PGM); -const FloatMenuInfo minfoVoltA1 = { "Volt A1", 9, 0xffff, 2, NO_CALLBACK }; -FloatMenuItem menuVoltA1(&minfoVoltA1, 0.0, NULL, INFO_LOCATION_PGM); -const FloatMenuInfo minfoVoltA0 = { "Volt A0", 8, 0xffff, 2, NO_CALLBACK }; -FloatMenuItem menuVoltA0(&minfoVoltA0, 0.0, &menuVoltA1, INFO_LOCATION_PGM); -const SubMenuInfo minfoStatus = { "Status", 7, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackStatus(&minfoStatus, &menuVoltA0, INFO_LOCATION_PGM); -SubMenuItem menuStatus(&minfoStatus, &menuBackStatus, &menuConnectivity, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoShowHidden = { "Show Hidden", 30, 0xffff, 1, onShowHidden, NAMING_YES_NO }; -BooleanMenuItem menuShowHidden(&minfoShowHidden, false, NULL, INFO_LOCATION_PGM); -const AnyMenuInfo minfoRGB = { "RGB", 26, 16, 0, onRgbChanged }; -Rgb32MenuItem menuRGB(&minfoRGB, RgbColor32(0, 0, 0), false, &menuShowHidden, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoTempCheck = { "Temp Check", 13, 9, 1, NO_CALLBACK, NAMING_ON_OFF }; -BooleanMenuItem menuTempCheck(&minfoTempCheck, false, &menuRGB, INFO_LOCATION_PGM); -const AnyMenuInfo minfoHiddenItem = { "Hidden item", 16, 0xffff, 0, NO_CALLBACK }; -ActionMenuItem menuHiddenItem(&minfoHiddenItem, &menuTempCheck, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoSCircuitProtect = { "S-Circuit Protect", 12, 8, 1, NO_CALLBACK, NAMING_ON_OFF }; -BooleanMenuItem menuSCircuitProtect(&minfoSCircuitProtect, false, &menuHiddenItem, INFO_LOCATION_PGM); -const SubMenuInfo minfoAdvanced = { "Advanced", 11, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackAdvanced(&minfoAdvanced, &menuSCircuitProtect, INFO_LOCATION_PGM); -SubMenuItem menuAdvanced(&minfoAdvanced, &menuBackAdvanced, NULL, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSaveAll = { "Save all", 10, 0xffff, 0, onSaveRom }; -ActionMenuItem menuSaveAll(&minfoSaveAll, &menuAdvanced, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoPwrDelay = { "Pwr Delay", 5, 0xffff, 1, NO_CALLBACK, NAMING_YES_NO }; -BooleanMenuItem menuPwrDelay(&minfoPwrDelay, false, &menuSaveAll, INFO_LOCATION_PGM); -const SubMenuInfo minfoSettings = { "Settings", 4, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackSettings(&minfoSettings, &menuPwrDelay, INFO_LOCATION_PGM); -SubMenuItem menuSettings(&minfoSettings, &menuBackSettings, &menuStatus, INFO_LOCATION_PGM); -const char enumStrLimit_0[] = "Current"; -const char enumStrLimit_1[] = "Voltage"; -const char* const enumStrLimit[] = { enumStrLimit_0, enumStrLimit_1 }; -const EnumMenuInfo minfoLimit = { "Limit", 3, 6, 1, onLimitMode, enumStrLimit }; -EnumMenuItem menuLimit(&minfoLimit, 0, &menuSettings, INFO_LOCATION_PGM); -const AnalogMenuInfo minfoCurrent = { "Current", 2, 4, 255, onCurrentChange, 0, 100, "A" }; -AnalogMenuItem menuCurrent(&minfoCurrent, 0, &menuLimit, INFO_LOCATION_PGM); -const AnalogMenuInfo minfoVoltage = { "Voltage", 1, 2, 255, onVoltageChange, -128, 2, "V" }; -AnalogMenuItem menuVoltage(&minfoVoltage, 0, &menuCurrent, INFO_LOCATION_PGM); - -void setupMenu() { - // First we set up eeprom and authentication (if needed). - setSizeBasedEEPROMStorageEnabled(false); - menuMgr.setEepromRef(&glI2cRom); - authManager.initialise(menuMgr.getEepromAbstraction(), 100); - menuMgr.setAuthenticator(&authManager); - // Now add any readonly, non-remote and visible flags. - menuAuthenticator.setLocalOnly(true); - - // Code generated by plugins. - gfx.initR(INITR_BLACKTAB); - gfx.setRotation(1); - renderer.setUpdatesPerSecond(5); - switches.init(ioexp_io8574, SWITCHES_POLL_KEYS_ONLY, true); - menuMgr.initForEncoder(&renderer, &menuVoltage, 7, 6, 5); - remoteServer.addConnection(ðernetConnection); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_ALWAYS); - renderer.setUseSliderForAnalog(true); - installCoolBlueTraditionalTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(&FreeSansBold9pt7b, 1), true); - - // We have an IoT monitor, register the server - menuIoTMonitor.setRemoteServer(remoteServer); - - // We have an EEPROM authenticator, it needs initialising - menuAuthenticator.init(); -} - diff --git a/examples/arduino32/colorTftEthernet32/colorTftEthernet32_menu.h b/examples/arduino32/colorTftEthernet32/colorTftEthernet32_menu.h deleted file mode 100644 index 7ee38a24..00000000 --- a/examples/arduino32/colorTftEthernet32/colorTftEthernet32_menu.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#ifndef MENU_GENERATED_CODE_H -#define MENU_GENERATED_CODE_H - -#include -#include -#include "tcMenuAdaFruitGfx.h" -#include "EthernetTransport.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// variables we declare that you may need to access -extern const PROGMEM ConnectorLocalInfo applicationInfo; -extern TcMenuRemoteServer remoteServer; -extern Adafruit_ST7735 gfx; -extern AdafruitDrawable gfxDrawable; -extern GraphicsDeviceRenderer renderer; -extern EthernetServer server; -extern EthernetInitialisation ethernetInitialisation; - -// Any externals needed by IO expanders, EEPROMs etc -extern IoAbstractionRef ioexp_io8574; - -// Global Menu Item exports -extern ActionMenuItem menuTakeDisplay; -extern ActionMenuItem menuSaveItem; -extern TextMenuItem menuRomText; -extern ScrollChoiceMenuItem menuRomLocation; -extern ScrollChoiceMenuItem menuRomChoice; -extern BackMenuItem menuBackRomValues; -extern SubMenuItem menuRomValues; -extern RemoteMenuItem menuIoTMonitor; -extern EepromAuthenticationInfoMenuItem menuAuthenticator; -extern IpAddressMenuItem menuIpAddress; -extern BackMenuItem menuBackConnectivity; -extern SubMenuItem menuConnectivity; -extern FloatMenuItem menuVoltA1; -extern FloatMenuItem menuVoltA0; -extern BackMenuItem menuBackStatus; -extern SubMenuItem menuStatus; -extern BooleanMenuItem menuShowHidden; -extern Rgb32MenuItem menuRGB; -extern BooleanMenuItem menuTempCheck; -extern ActionMenuItem menuHiddenItem; -extern BooleanMenuItem menuSCircuitProtect; -extern BackMenuItem menuBackAdvanced; -extern SubMenuItem menuAdvanced; -extern ActionMenuItem menuSaveAll; -extern BooleanMenuItem menuPwrDelay; -extern BackMenuItem menuBackSettings; -extern SubMenuItem menuSettings; -extern EnumMenuItem menuLimit; -extern AnalogMenuItem menuCurrent; -extern AnalogMenuItem menuVoltage; - -// Provide a wrapper to get hold of the root menu item and export setupMenu -inline MenuItem& rootMenuItem() { return menuVoltage; } -void setupMenu(); - -// Callback functions must always include CALLBACK_FUNCTION after the return type -#define CALLBACK_FUNCTION - -int fnRomLocationRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize); -void CALLBACK_FUNCTION onCurrentChange(int id); -void CALLBACK_FUNCTION onLimitMode(int id); -void CALLBACK_FUNCTION onRgbChanged(int id); -void CALLBACK_FUNCTION onSaveItem(int id); -void CALLBACK_FUNCTION onSaveRom(int id); -void CALLBACK_FUNCTION onShowHidden(int id); -void CALLBACK_FUNCTION onTakeDisplay(int id); -void CALLBACK_FUNCTION onVoltageChange(int id); - -#endif // MENU_GENERATED_CODE_H diff --git a/examples/arduino32/dynamicMenuItems/ThemeCoolBlueTraditional.h b/examples/arduino32/dynamicMenuItems/ThemeCoolBlueTraditional.h deleted file mode 100644 index 7c249b90..00000000 --- a/examples/arduino32/dynamicMenuItems/ThemeCoolBlueTraditional.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -// -// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() -// - -// tcMenu drawing properties take a 4 color palette for items, titles and actions. -// this renderer shares the color configuration for items and actions. -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; - -void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // first we keep a reference to the screen size, and set the dimensions on the renderer. - auto width = bgr.getDeviceDrawable()->getDisplayDimensions().x; - auto height = bgr.getDeviceDrawable()->getDisplayDimensions().y; - bgr.setDisplayDimensions(width, height); - - // get hold of the item display factory that holds the drawing configuration. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // when an item is active, it will show in these colours instead of the default. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // here we calculate the item padding and row heights based on the resolution of the display - bool medResOrBetter = width > 160; - MenuPadding titlePadding(medResOrBetter ? 4 : 2); - MenuPadding itemPadding(medResOrBetter ? 2 : 1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - // we set the editing and selected icons here based on the row height. - if(needEditingIcons && itemHeight > 12) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defActiveIcon)); - } - else if(needEditingIcons) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - } - - // we tell the library how to draw titles, items and actions by default. - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, titlePadding, titleFont.fontData, titleFont.fontMag, - medResOrBetter ? 3 : 1, titleHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - - // after adjusting the drawing configuration, we must always refresh the cache. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE diff --git a/examples/arduino32/dynamicMenuItems/ThemeCoolBlueTraditionalBuilder.h b/examples/arduino32/dynamicMenuItems/ThemeCoolBlueTraditionalBuilder.h new file mode 100644 index 00000000..30e70f97 --- /dev/null +++ b/examples/arduino32/dynamicMenuItems/ThemeCoolBlueTraditionalBuilder.h @@ -0,0 +1,79 @@ +/** + * Cool blue traditional theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. + * This file will not be updated by the designer, you can edit. + * See https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + */ + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE + +#include + +// +// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() +// + +// tcMenu drawing properties take a 4 color palette for items, titles and actions. +// this renderer shares the color configuration for items and actions. +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + * @param titleMode the way that the title should be drawn (choose from the enum values) + * @param useUnicode if using tcUnicode drawing functions + */ +void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + bool medResOrBetter = gr.getWidth() > 160; + MenuPadding titlePadding(medResOrBetter ? 4 : 2); + MenuPadding itemPadding(medResOrBetter ? 2 : 1); + + themeBuilder.dimensionsFromRenderer() + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) + .withItemPadding(itemPadding) + .withTitlePadding(titlePadding) + .withRenderingSettings(titleMode, false) + .withPalette(coolBlueItemPalette) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + if(medResOrBetter) { + themeBuilder.withStandardMedResCursorIcons(); + } else { + themeBuilder.withStandardLowResCursorIcons(); + } + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultItemProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.defaultTitleProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(coolBlueTitlePalette) + .withSpacing(medResOrBetter ? 3 : 1) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //THEME_COOL_BLUE diff --git a/examples/arduino32/dynamicMenuItems/dynamicMenuItems.emf b/examples/arduino32/dynamicMenuItems/dynamicMenuItems.emf index 01237128..53e96f74 100644 --- a/examples/arduino32/dynamicMenuItems/dynamicMenuItems.emf +++ b/examples/arduino32/dynamicMenuItems/dynamicMenuItems.emf @@ -358,7 +358,7 @@ "lastRemoteUuids": [ "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" ], - "lastThemeUuid": "03c6b25f-db63-402a-8447-a5ce1484c14d", + "lastThemeUuid": "57945787-0A04-447B-BBA2-6461FC505397", "applicationUUID": "5f22995e-8da2-49c4-9ec8-d055901003af", "applicationName": "Dynamic Menus", "lastProperties": [ @@ -424,7 +424,7 @@ }, { "name": "DISPLAY_BUFFER_SIZE", - "latestValue": "20", + "latestValue": "40", "subsystem": "DISPLAY" }, { @@ -559,7 +559,7 @@ }, { "name": "ITEM_FONT", - "latestValue": "ada:OpenSansCyrillicLatin12,0", + "latestValue": "ada:OpenSansRegular8pt,0", "subsystem": "THEME" }, { @@ -567,11 +567,6 @@ "latestValue": "ada:OpenSansCyrillicLatin12,0", "subsystem": "THEME" }, - { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", - "subsystem": "THEME" - }, { "name": "TITLE_SHOW_MODE", "latestValue": "TITLE_FIRST_ROW", @@ -582,11 +577,6 @@ "latestValue": "true", "subsystem": "THEME" }, - { - "name": "USE_SLIDER_ANALOG", - "latestValue": "true", - "subsystem": "THEME" - }, { "name": "NEED_EDITING_ICONS", "latestValue": "true", diff --git a/examples/arduino32/dynamicMenuItems/dynamicMenuItems.ino b/examples/arduino32/dynamicMenuItems/dynamicMenuItems.ino index 2071ff05..5a270b04 100644 --- a/examples/arduino32/dynamicMenuItems/dynamicMenuItems.ino +++ b/examples/arduino32/dynamicMenuItems/dynamicMenuItems.ino @@ -2,14 +2,15 @@ * This example shows how to create scroll choices, lists, and dynamically add items to both dialogs and existing menus * at runtime. * - * Test environment: Seeed MG126 - Matrix Keyboard, Adafruit 128x128 display, rotary encoder + * Test environment: Seeed MG126 - Matrix Keyboard, Adafruit 128x128 display, rotary encoder. However, it is easy to + * apply these concepts to any other menu arrangements. * * Although it's set up to run on SAMD there is no reason it could not be easily reconfigured for any * other board. This is one of the biggest advantages of this framework, moving boards is easier. * - * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ - * Dialogs: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/ - * MenuManager: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menumanager-and-iteration/ + * Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ + * Dialogs: https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/rendering-with-tcmenu-lcd-tft-oled/ + * MenuManager: https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/menumanager-and-iteration/ */ #include "generated/dynamicMenuItems_menu.h" @@ -24,13 +25,14 @@ // ScrollChoice menu items when using data in RAM mode reference a fixed width array in your code, these will be // created by the code generator if needed. Genreally they are an array of char large enough to hold all items. // In this case they are pizza toppings, each zero terminated. +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/ // 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 char pizzaToppings[] = {"Peperoni\0 Onions\0 Olives\0 Sweetcorn\0Mushrooms\0Peppers\0 "}; // // We now create some menu items that we manually add to the oven menu during initialisation. We set the sub menu child // to be the first of the two menu items, which are provided in a linked list. Notice that these are completely created -// RAM, and not program memory. +// RAM, and not program memory: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/ // TextMenuItem menuTextExtra(newAnyMenuInfo("Text", nextRandomId(), 0xffff, NO_CALLBACK), "hello", 8, nullptr, INFO_LOCATION_RAM); BooleanMenuItem menuOvenFull(newBooleanMenuInfoP("Start Oven", nextRandomId(), 0xffff, NO_CALLBACK, NAMING_YES_NO), false, &menuTextExtra, INFO_LOCATION_RAM); @@ -42,6 +44,7 @@ AnalogMenuItem menuOvenTempItem(newAnalogMenuInfo("Oven Temp", nextRandomId(), 0 // Here's a few examples of how you can capture the state of various actions taking place in the menu manager, such as // actionable menu items being activated, editing starting and ending on editable items, and changes in tree structure. // We create an instance of this class and then register it with menuMgr further down. +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menumanager-and-iteration/ // class MyMenuManagerObserver : public MenuManagerObserver { private: @@ -133,7 +136,7 @@ void onTitlePressed(int /*id*/) { void setup() { // This example logs using IoLogging, see the following guide to enable - // https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/ + //https://tcmenu.github.io/documentation/arduino-libraries//io-abstraction/arduino-logging-with-io-logging/ IOLOG_START_SERIAL serEnableLevel(SER_TCMENU_DEBUG, true); @@ -183,6 +186,7 @@ void CALLBACK_FUNCTION onStartCooking(int id) { // here we create an extra menu item that allows us to have three lines of text in the info dialog, made up of the // title, the buffer line, and also this line, then the buttons. It uses the showRam function which shows from // a non constant / PGM string +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/#presenting-a-dialog-to-the-user // TextMenuItem secondItem(newAnyMenuInfo("Detail: ", nextRandomId(), 0xffff, NO_CALLBACK), "det", 12, nullptr, INFO_LOCATION_RAM); @@ -323,8 +327,8 @@ void CALLBACK_FUNCTION onDialogController(int id) { } // This callback needs to be implemented by you, see the below docs: -// 1. List Docs - https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/list-menu-item/ -// 2. ScrollChoice Docs - https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/ +// 1. List Docs - https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/list-menu-item/ +// 2. ScrollChoice Docs - https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/ // // This is called back each time a list item needs to draw data. This is a list that is based on an array of string values. // @@ -357,7 +361,7 @@ void CALLBACK_FUNCTION onDialogBack(int id) { // rotary encoder and by keyboards, it will allow the user to only enter values between 0 and 7, and hence is an // octal text filter. int CALLBACK_FUNCTION octalOnlyRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize) { - // See https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/based-on-runtimemenuitem/ + // See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/menu-item-types/based-on-runtimemenuitem/ auto textItem = reinterpret_cast(item); switch(mode) { case RENDERFN_NAME: diff --git a/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.cpp b/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.cpp index a7acbb5e..c69cc705 100644 --- a/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.cpp +++ b/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.cpp @@ -8,16 +8,19 @@ use elsewhere. */ +// Generated for Arduino 32bit ARM by TcMenu 4.3.1 on 2024-09-28T08:15:53.193774100Z. + #include #include "dynamicMenuItems_menu.h" -#include "../ThemeCoolBlueTraditional.h" +#include "../ThemeCoolBlueTraditionalBuilder.h" +#include #include // Global variable declarations const ConnectorLocalInfo applicationInfo = { "Dynamic Menus", "5f22995e-8da2-49c4-9ec8-d055901003af" }; IoAbstractionRef ioexp_io23017 = ioFrom23017(0x20, ACTIVE_LOW_OPEN, 10); Adafruit_ST7735 gfx(1, 0, -1); -AdafruitDrawable gfxDrawable(&gfx, 20); +AdafruitDrawable gfxDrawable(&gfx, 40); GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); MatrixKeyboardManager keyboard; const char keyboardKeys[] = "123A456B789C*0#D"; @@ -95,9 +98,6 @@ void setupMenu() { keyboardLayout.setColPin(3, 12); keyboard.initialise(ioexp_io23017, &keyboardLayout, &tcMenuKeyListener, true); keyboard.setRepeatKeyMillis(850, 350); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(true); - renderer.enableTcUnicode(); - installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin12, 0), MenuFontDef(&OpenSansCyrillicLatin12, 0), true); + installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansRegular8pt, 0), MenuFontDef(&OpenSansCyrillicLatin12, 0), true, BaseGraphicalRenderer::TITLE_FIRST_ROW, true); } diff --git a/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.h b/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.h index 401ced03..3ee4d24a 100644 --- a/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.h +++ b/examples/arduino32/dynamicMenuItems/generated/dynamicMenuItems_menu.h @@ -29,6 +29,7 @@ extern AdafruitDrawable gfxDrawable; extern GraphicsDeviceRenderer renderer; extern MatrixKeyboardManager keyboard; extern MenuEditingKeyListener tcMenuKeyListener; +extern const UnicodeFont OpenSansRegular8pt[]; extern const UnicodeFont OpenSansCyrillicLatin12[]; // Any externals needed by IO expanders, EEPROMs etc diff --git a/examples/arduino32/nano33ble/MotionDetection.h b/examples/arduino32/nano33ble/MotionDetection.h index c40893fb..97e71513 100644 --- a/examples/arduino32/nano33ble/MotionDetection.h +++ b/examples/arduino32/nano33ble/MotionDetection.h @@ -3,7 +3,7 @@ #include #include -#include "generated/nano33ble_menu.h" +#include "nano33ble_menu.h" /** * Here we create a polling event that checks if the acceleration / magnetic data is available, and whenever it is diff --git a/examples/arduino32/nano33ble/SensorManager.h b/examples/arduino32/nano33ble/SensorManager.h index 7a099bbc..e2ae1ada 100644 --- a/examples/arduino32/nano33ble/SensorManager.h +++ b/examples/arduino32/nano33ble/SensorManager.h @@ -5,7 +5,7 @@ #include #include #include -#include "generated/nano33ble_menu.h" +#include "nano33ble_menu.h" /** * Here we have a class that extends `Executable`, meaning that the `exec()` method is called every time the event diff --git a/examples/arduino32/nano33ble/ThemeMonoInverse.h b/examples/arduino32/nano33ble/ThemeMonoInverse.h deleted file mode 100644 index 1d689400..00000000 --- a/examples/arduino32/nano33ble/ThemeMonoInverse.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TCMENU_THEME_MONO_INVERSE -#define TCMENU_THEME_MONO_INVERSE - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; -color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; - -#define TITLE_PADDING 2 -#define TITLE_SPACING 2 - -void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 2); - - MenuPadding titlePadding(TITLE_PADDING); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_INVERSE \ No newline at end of file diff --git a/examples/arduino32/nano33ble/ThemeMonoInverseBuilder.h b/examples/arduino32/nano33ble/ThemeMonoInverseBuilder.h new file mode 100644 index 00000000..1ef2d8a6 --- /dev/null +++ b/examples/arduino32/nano33ble/ThemeMonoInverseBuilder.h @@ -0,0 +1,60 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; +color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; + +#define TITLE_PADDING 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoInverseTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 2) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(defaultTitlePaletteMono) + .withPadding(MenuPadding(TITLE_PADDING)) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/arduino32/nano33ble/generated/tcMenuBLERemoteConnector.cpp b/examples/arduino32/nano33ble/generated/tcMenuBLERemoteConnector.cpp deleted file mode 100644 index 179ceb1c..00000000 --- a/examples/arduino32/nano33ble/generated/tcMenuBLERemoteConnector.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#include "tcMenuBLERemoteConnector.h" - -using namespace tcremote; - -BLEDevice tcremote::central; -BLEService tcremote::bleApiService(bleServiceIdentifier); -BLECharacteristic tcremote::toApiCharacteristic(characteristicDeviceToApi, BLERead | BLENotify, 255, false); -BLECharacteristic tcremote::fromApiCharacteristic(characteristicApiToDevice, BLEWrite, 255, false); -BLECharacteristic tcremote::deviceSequenceCharacteristic(characteristicDeviceSeqCounter, BLERead | BLENotify, 4, true); -BLECharacteristic tcremote::apiSequenceCharacteristic(characteristicApiSeqCounter, BLEWrite, 4, true); - -inline uint32_t read32From(uint8_t* buf) { - return (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 | (uint32_t)buf[2] << 8 | (uint32_t)buf[3]; -} - -inline void writeToBuffer(uint8_t* buffer, uint32_t sequence) { - buffer[0] = (sequence >> 24); - buffer[1] = (sequence >> 16) & 0xFF; - buffer[2] = (sequence >> 8) & 0xFF; - buffer[3] = sequence & 0xFF; -} - -BLETagValTransport::BLETagValTransport() : BaseBufferedRemoteTransport(BUFFER_ONE_MESSAGE, 255, 255) { - writeBufferPos = 4; - writeToBuffer(writeBuffer, currDeviceSequence + 1); -} - -bool BLETagValTransport::readAvailable() { - if(readBufferAvail && readBufferPos < readBufferAvail) { - return true; - } - - fillReadBuffer(readBuffer, readBufferSize); - return readBufferPos < readBufferAvail; -} - -int BLETagValTransport::fillReadBuffer(uint8_t *dataBuffer, int maxSize) { - if(!central.connected() || !fromApiCharacteristic.written()) { - return 0; - } - - readBufferAvail = fromApiCharacteristic.readValue(readBuffer, readBufferSize); - if(readBufferAvail <= 4) - { - return 0; - } - - serlogHexDump(SER_NETWORK_DEBUG, "fromApi ", readBuffer, readBufferAvail); - - size_t i=4; - while(readBuffer[i] != 0 && i < readBufferAvail) { - i++; - } - readBufferAvail = i; - uint32_t rxSequence = read32From(readBuffer); - serlogF3(SER_NETWORK_DEBUG, "RxSeq ", rxSequence, readBufferAvail); - - uint8_t buffer[4]; - writeToBuffer(buffer, rxSequence); - bool writtenSeqOk = deviceSequenceCharacteristic.writeValue(buffer, 4) != 0; - serlogF2(SER_NETWORK_DEBUG, "RxSeqOK ", writtenSeqOk); - - readBufferPos = 4; - return readBufferAvail; -} - -void BLETagValTransport::flush() { - if(apiSequenceCharacteristic.written()) { - uint8_t buffer[4]; - apiSequenceCharacteristic.readValue(buffer, sizeof(buffer)); - currApiSequence = read32From(buffer); - serlogF3(SER_NETWORK_DEBUG, "ApiSeq rd ", currApiSequence, currDeviceSequence) - } - if(central.connected() && currApiSequence == currDeviceSequence) { - // bump the device sequence - currDeviceSequence += 1; - - // zero terminate if not full size of buffer - if((writeBufferSize - writeBufferPos) > 1) { - writeBuffer[writeBufferPos] = 0; - writeBufferPos++; - } - - // write the value out and make sure it all writes. - int written = toApiCharacteristic.writeValue(writeBuffer, writeBufferPos); - if(written != 0) { - serlogF3(SER_NETWORK_DEBUG, "ApiToDevice ", writeBufferPos, currDeviceSequence) - } else { - central.disconnect(); - } - writeBufferPos = 4; - writeToBuffer(writeBuffer, currDeviceSequence); - } -} - -bool BLETagValTransport::available() { - return central.connected(); -} - -bool BLETagValTransport::connected() { - return central.connected(); -} - -void BLETagValTransport::connectedClient() { - currApiSequence = currDeviceSequence = 0; - uint8_t zeroBuffer[] = {0}; - deviceSequenceCharacteristic.writeValue(zeroBuffer, 4); -} - -bool BLEDeviceInitialisation::attemptInitialisation() { - serlogF(SER_NETWORK_INFO, "BLE Starting"); - if(!initialised && BLE.begin() == 0) return false; - initialised = true; - if (!BLE.begin()) { - serlogF(SER_ERROR, "BLE failed!"); - } - - bleApiService.addCharacteristic(toApiCharacteristic); - bleApiService.addCharacteristic(fromApiCharacteristic); - bleApiService.addCharacteristic(apiSequenceCharacteristic); - bleApiService.addCharacteristic(deviceSequenceCharacteristic); - uint8_t buffer[4] = {0}; - apiSequenceCharacteristic.writeValue(buffer, 4); - deviceSequenceCharacteristic.writeValue(buffer, 4); - - BLE.addService(bleApiService); - BLE.setLocalName(applicationInfo.name); - BLE.setAdvertisedService(bleApiService); - BLE.advertise(); - - serlogF(SER_NETWORK_INFO, "BLE Up"); - return true; -} - -bool BLEDeviceInitialisation::attemptNewConnection(BaseRemoteServerConnection *transport) { - central = BLE.central(); - if(central.connected()) { - reinterpret_cast(transport)->connectedClient(); - return true; - } - return false; -} diff --git a/examples/arduino32/nano33ble/generated/tcMenuBLERemoteConnector.h b/examples/arduino32/nano33ble/generated/tcMenuBLERemoteConnector.h deleted file mode 100644 index 9265afaf..00000000 --- a/examples/arduino32/nano33ble/generated/tcMenuBLERemoteConnector.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#ifndef TCMENU_BLEREMOTECONNECTOR_H -#define TCMENU_BLEREMOTECONNECTOR_H - -#include -#include -#include -#include -#include -#include -#include - -#ifndef LARGEST_PROCESSABLE_MSG -#define LARGEST_PROCESSABLE_MSG 512 -#endif - -extern const PROGMEM ConnectorLocalInfo applicationInfo; - -namespace tcremote { - - const char bleServiceIdentifier[] PROGMEM = "8589F957-1916-4B27-BA6D-B0AF36F317EF"; - const char characteristicApiToDevice[] PROGMEM = "7E7CA4D5-CF52-4918-BD60-6E98A810F0EB"; - const char characteristicDeviceToApi[] PROGMEM = "D361F4F9-B13D-4118-A6C4-B54CF12EED3C"; - const char characteristicApiSeqCounter[] PROGMEM = "AB2ED3BE-C8C4-4E0D-8BF9-E7D6717F761C"; - const char characteristicDeviceSeqCounter[] PROGMEM = "79A24791-EEDA-4DA5-9E8C-04B8C9060B1F"; - - extern BLEDevice central; - extern BLEService bleApiService; - extern BLECharacteristic toApiCharacteristic; - extern BLECharacteristic fromApiCharacteristic; - extern BLECharacteristic deviceSequenceCharacteristic; - extern BLECharacteristic apiSequenceCharacteristic; - - class BLEDeviceInitialisation : public DeviceInitialisation { - public: - BLEDeviceInitialisation() = default; - bool attemptInitialisation() override; - bool attemptNewConnection(BaseRemoteServerConnection *connection) override; - }; - - enum TcConnectionStateType { BLE_CON_DISCONNECTED, BLE_CON_BUILDING_MSG, BLE_CON_SENDING_MSG, BLE_CON_AWAITING_ACK}; - - class BLETagValTransport : public BaseBufferedRemoteTransport { - private: - uint32_t currDeviceSequence; - uint32_t currApiSequence; - public: - BLETagValTransport(); - int fillReadBuffer(uint8_t* dataBuffer, int maxSize) override; - bool readAvailable() override; - void flush() override; - bool available() override; - bool connected() override; - void connectedClient(); - }; -} - -#endif //TCMENU_BLEREMOTECONNECTOR_H diff --git a/examples/arduino32/nano33ble/nano33ble.emf b/examples/arduino32/nano33ble/nano33ble.emf index 1dcc0771..030ce157 100644 --- a/examples/arduino32/nano33ble/nano33ble.emf +++ b/examples/arduino32/nano33ble/nano33ble.emf @@ -227,7 +227,7 @@ "lastRemoteUuids": [ "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" ], - "lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0", + "lastThemeUuid": "396ED4DF-AD7B-4951-A848-A9E5838A549B", "applicationUUID": "e95fcf8a-8a03-4043-9313-01fd8b8e8707", "applicationName": "Nano 33 BLE Sense", "lastProperties": [ @@ -343,12 +343,12 @@ }, { "name": "TITLE_HEADER_PADDING", - "latestValue": "2", + "latestValue": "1", "subsystem": "THEME" }, { "name": "TITLE_TO_ITEM_SPACING", - "latestValue": "2", + "latestValue": "0", "subsystem": "THEME" }, { @@ -364,13 +364,13 @@ ], "namingRecursive": true, "useCppMain": false, - "saveLocation": "PROJECT_TO_CURRENT_WITH_GENERATED", + "saveLocation": "ALL_TO_CURRENT", "usingSizedEEPROMStorage": false, "eepromDefinition": "", "authenticatorDefinition": "", "projectIoExpanders": [ - "customIO:io23017", - "deviceIO:" + "deviceIO:", + "customIO:io23017" ], "menuInMenuCollection": { "menuDefinitions": [] diff --git a/examples/arduino32/nano33ble/nano33ble.ino b/examples/arduino32/nano33ble/nano33ble.ino index 6e9c9e61..85b11bc2 100644 --- a/examples/arduino32/nano33ble/nano33ble.ino +++ b/examples/arduino32/nano33ble/nano33ble.ino @@ -9,7 +9,7 @@ * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ */ -#include "generated/nano33ble_menu.h" +#include "nano33ble_menu.h" #include "SensorManager.h" #include "MotionDetection.h" #include diff --git a/examples/arduino32/nano33ble/generated/nano33ble_menu.cpp b/examples/arduino32/nano33ble/nano33ble_menu.cpp similarity index 95% rename from examples/arduino32/nano33ble/generated/nano33ble_menu.cpp rename to examples/arduino32/nano33ble/nano33ble_menu.cpp index 5f41256f..fdb8c317 100644 --- a/examples/arduino32/nano33ble/generated/nano33ble_menu.cpp +++ b/examples/arduino32/nano33ble/nano33ble_menu.cpp @@ -8,9 +8,11 @@ use elsewhere. */ +// Generated for Arduino 32bit ARM by TcMenu 4.3.1 on 2024-09-28T18:34:44.260116300Z. + #include #include "nano33ble_menu.h" -#include "../ThemeMonoInverse.h" +#include "ThemeMonoInverseBuilder.h" // Global variable declarations const ConnectorLocalInfo applicationInfo = { "Nano 33 BLE Sense", "e95fcf8a-8a03-4043-9313-01fd8b8e8707" }; @@ -62,8 +64,6 @@ void setupMenu() { renderer.setUpdatesPerSecond(10); switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); menuMgr.initForEncoder(&renderer, &menuTemp, 5, 6, 4); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(false); - installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true); + installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true, BaseGraphicalRenderer::TITLE_FIRST_ROW, false); } diff --git a/examples/arduino32/nano33ble/generated/nano33ble_menu.h b/examples/arduino32/nano33ble/nano33ble_menu.h similarity index 100% rename from examples/arduino32/nano33ble/generated/nano33ble_menu.h rename to examples/arduino32/nano33ble/nano33ble_menu.h diff --git a/examples/arduino32/nano33ble/generated/tcMenuU8g2.cpp b/examples/arduino32/nano33ble/tcMenuU8g2.cpp similarity index 100% rename from examples/arduino32/nano33ble/generated/tcMenuU8g2.cpp rename to examples/arduino32/nano33ble/tcMenuU8g2.cpp diff --git a/examples/arduino32/nano33ble/generated/tcMenuU8g2.h b/examples/arduino32/nano33ble/tcMenuU8g2.h similarity index 100% rename from examples/arduino32/nano33ble/generated/tcMenuU8g2.h rename to examples/arduino32/nano33ble/tcMenuU8g2.h diff --git a/examples/arduino32/piPicoTftTouch/ThemeCoolBlueModern.h b/examples/arduino32/piPicoTftTouch/ThemeCoolBlueModern.h deleted file mode 100644 index 757ca5c8..00000000 --- a/examples/arduino32/piPicoTftTouch/ThemeCoolBlueModern.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Cool blue modern theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. - * This file will not be updated by the designer, you can edit. - */ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -#include - -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; -const color_t coolBlueActionPalette[] = {RGB(255, 255, 255), RGB(0,45,120), RGB(20,133,255), RGB(31,100,178)}; - -#define ACTION_BORDER_WIDTH 0 - -void installCoolBlueModernTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // here we get a refrerence to the drawable and then set the dimensions. - auto* rootDrawable = bgr.getDeviceDrawable(); - bgr.setDisplayDimensions(rootDrawable->getDisplayDimensions().x, rootDrawable->getDisplayDimensions().y); - - // we need a reference to the factory object that we will use to configure the drawing. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // change the selected colours. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // for this theme we use the same size padding for each case, we need touchable items. We calculate the height too - MenuPadding allPadding(4, 3, 4, 3); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, allPadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, allPadding); - - // now we configure the drawing for each item type - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, allPadding, titleFont.fontData, titleFont.fontMag, 3, titleHeight, - GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, - GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueActionPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, - GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(ACTION_BORDER_WIDTH)); - - // and lastly, whenever changing the configuration, we must refresh. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE \ No newline at end of file diff --git a/examples/arduino32/piPicoTftTouch/piPicoTftEncoder.emf b/examples/arduino32/piPicoTftTouch/piPicoTftEncoder.emf deleted file mode 100644 index f95809d9..00000000 --- a/examples/arduino32/piPicoTftTouch/piPicoTftEncoder.emf +++ /dev/null @@ -1,479 +0,0 @@ -{ - "version": "1.00", - "projectName": "RPiPico Tft Encoder", - "author": "dave", - "items": [ - { - "parentId": 0, - "type": "analogItem", - "defaultValue": "80", - "item": { - "maxValue": 255, - "offset": -180, - "divisor": 2, - "unitName": "dB", - "step": 1, - "name": "Volume", - "variableName": "Volume", - "id": 1, - "eepromAddress": 2, - "functionName": "onVolumeChanged", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "enumItem", - "defaultValue": "2", - "item": { - "enumEntries": [ - "CD Player", - "Computer USB", - "Turntable", - "Line 1" - ], - "name": "Input", - "variableName": "Input", - "id": 2, - "eepromAddress": 5, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "TRUE_FALSE", - "name": "Mute", - "variableName": "Mute", - "id": 3, - "eepromAddress": 4, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "subMenu", - "item": { - "secured": false, - "name": "Settings", - "variableName": "Settings", - "id": 4, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "analogItem", - "defaultValue": "144", - "item": { - "maxValue": 255, - "offset": -180, - "divisor": 2, - "unitName": "dB", - "step": 1, - "name": "Max On Volume", - "variableName": "SettingsMaxOnVolume", - "id": 5, - "eepromAddress": 7, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "ON_OFF", - "name": "Protection", - "variableName": "SettingsProtection", - "id": 6, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "textItem", - "defaultValue": "hello", - "item": { - "textLength": 10, - "itemType": "PLAIN_TEXT", - "name": "Text", - "variableName": "SettingsText", - "id": 13, - "eepromAddress": 9, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "textItem", - "defaultValue": "192.168.0.33", - "item": { - "textLength": 5, - "itemType": "IP_ADDRESS", - "name": "IP", - "variableName": "SettingsIP", - "id": 14, - "eepromAddress": 19, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "rgbItem", - "defaultValue": "#000000FF", - "item": { - "includeAlphaChannel": false, - "name": "RGB", - "variableName": "SettingsRGB", - "id": 15, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "largeNumItem", - "defaultValue": "100.500", - "item": { - "digitsAllowed": 8, - "decimalPlaces": 3, - "negativeAllowed": false, - "name": "LargeNum", - "variableName": "SettingsLargeNum", - "id": 16, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "largeNumItem", - "defaultValue": "0", - "item": { - "digitsAllowed": 8, - "decimalPlaces": 0, - "negativeAllowed": true, - "name": "NLge", - "variableName": "SettingsNlge", - "id": 18, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "subMenu", - "item": { - "secured": false, - "name": "Status", - "variableName": "Status", - "id": 7, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 7, - "type": "enumItem", - "defaultValue": "0", - "item": { - "enumEntries": [ - "Standby", - "Warm up", - "DC protect", - "Overload", - "Overheat" - ], - "name": "Amp Status", - "variableName": "StatusAmpStatus", - "id": 8, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 7, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "ON_OFF", - "name": "Amp Power", - "variableName": "StatusAmpPower", - "id": 9, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 7, - "type": "floatItem", - "defaultValue": "235.0", - "item": { - "numDecimalPlaces": 2, - "name": "Line Voltage", - "variableName": "StatusLineVoltage", - "id": 10, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 7, - "type": "actionMenu", - "item": { - "name": "Restart", - "variableName": "StatusRestart", - "id": 11, - "eepromAddress": -1, - "functionName": "onRestart", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": true - } - }, - { - "parentId": 7, - "type": "textItem", - "defaultValue": "", - "item": { - "textLength": 5, - "itemType": "PLAIN_TEXT", - "name": "Info", - "variableName": "StatusInfo", - "id": 19, - "eepromAddress": -1, - "functionName": "infoRenderingRtCall", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "actionMenu", - "item": { - "name": "Dialogs", - "variableName": "Dialogs", - "id": 12, - "eepromAddress": -1, - "functionName": "onShowDialogs", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "runtimeList", - "item": { - "initialRows": 0, - "listCreationMode": "CUSTOM_RTCALL", - "name": "Root List", - "variableName": "RootList", - "id": 17, - "eepromAddress": -1, - "functionName": "", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - } - ], - "codeOptions": { - "embeddedPlatform": "ARDUINO32", - "lastDisplayUuid": "e6342680-6fab-4d1b-ac08-ce8dbfc0974c", - "lastInputUuid": "89cd7f70-0457-4884-97c2-0db904ccb0ba", - "lastRemoteUuids": [ - "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" - ], - "lastThemeUuid": "850dc0a3-f534-47c2-94d8-1e64ff368a54", - "applicationUUID": "0c6972c4-addb-4931-a910-e4b2a85d2b2a", - "applicationName": "RPiPico Tft Encoder", - "lastProperties": [ - { - "name": "DISPLAY_VARIABLE", - "latestValue": "gfx", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_ROTATION", - "latestValue": "1", - "subsystem": "DISPLAY" - }, - { - "name": "DOUBLE_BUFFER_ROWS", - "latestValue": "45", - "subsystem": "DISPLAY" - }, - { - "name": "UPDATES_PER_SEC", - "latestValue": "15", - "subsystem": "DISPLAY" - }, - { - "name": "TOUCH_SEPARATOR", - "latestValue": "", - "subsystem": "DISPLAY" - }, - { - "name": "TFT_TOUCH_SCREEN_REQUIRED", - "latestValue": "true", - "subsystem": "DISPLAY" - }, - { - "name": "TOUCH_CALIB_WIDTH", - "latestValue": "4096", - "subsystem": "DISPLAY" - }, - { - "name": "TOUCH_CALIB_HEIGHT", - "latestValue": "4096", - "subsystem": "DISPLAY" - }, - { - "name": "TOUCH_USE_RAW_TFT_FUNCTION", - "latestValue": "true", - "subsystem": "DISPLAY" - }, - { - "name": "ORIENTATION_SEPARATOR", - "latestValue": "", - "subsystem": "DISPLAY" - }, - { - "name": "TFT_TOUCH_SWAP_XY", - "latestValue": "true", - "subsystem": "DISPLAY" - }, - { - "name": "TFT_TOUCH_X_INVERTED", - "latestValue": "false", - "subsystem": "DISPLAY" - }, - { - "name": "TFT_TOUCH_Y_INVERTED", - "latestValue": "false", - "subsystem": "DISPLAY" - }, - { - "name": "CALIB_SEPARATOR", - "latestValue": "", - "subsystem": "DISPLAY" - }, - { - "name": "TFT_TOUCH_SCREEN_CALIBRATE", - "latestValue": "true", - "subsystem": "DISPLAY" - }, - { - "name": "TFT_TOUCH_CALIBRATION_STORAGE_LOC", - "latestValue": "400", - "subsystem": "DISPLAY" - }, - { - "name": "ITEM_FONT", - "latestValue": "ada:OpenSansCyrillicLatin18,0", - "subsystem": "THEME" - }, - { - "name": "TITLE_FONT", - "latestValue": "ada:RobotoMedium24,1", - "subsystem": "THEME" - }, - { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", - "subsystem": "THEME" - }, - { - "name": "TITLE_SHOW_MODE", - "latestValue": "TITLE_FIRST_ROW", - "subsystem": "THEME" - }, - { - "name": "USE_TC_UNICODE", - "latestValue": "true", - "subsystem": "THEME" - }, - { - "name": "USE_SLIDER_ANALOG", - "latestValue": "true", - "subsystem": "THEME" - }, - { - "name": "NEED_EDITING_ICONS", - "latestValue": "false", - "subsystem": "THEME" - } - ], - "namingRecursive": true, - "useCppMain": false, - "saveLocation": "ALL_TO_CURRENT", - "usingSizedEEPROMStorage": false, - "eepromDefinition": "", - "authenticatorDefinition": "", - "projectIoExpanders": [ - "deviceIO:" - ], - "menuInMenuCollection": { - "menuDefinitions": [] - }, - "packageNamespace": "", - "appIsModular": false - }, - "stringLists": [] -} \ No newline at end of file diff --git a/examples/arduino32/piPicoTftTouch/piPicoTftTouch.ino b/examples/arduino32/piPicoTftTouch/piPicoTftTouch.ino deleted file mode 100644 index edbb5bcf..00000000 --- a/examples/arduino32/piPicoTftTouch/piPicoTftTouch.ino +++ /dev/null @@ -1,243 +0,0 @@ -/** - * An example that we test regularly on a Raspberry PI Pico (should work on either core), it has a screen based on - * the TFT_eSPI library and also a rotary encoder. It demonstrates quite a few features of the library. - * - * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ - */ -#include "piPicoTftTouch_menu.h" -#include -#include -#include -#include -#include - -// TFT_eSPI setup is "Setup60_RP2040_ILI9341.h". - - -const char* fileNames[] = { - "Automatic.dat", - "System.cpp", - "Driver123.h", - "SuperCode.java", - "TurboGame.o", -}; - -#define FILE_NAME_SIZE 5 - -void setup() { - // This example logs using IoLogging, see the following guide to enable - // https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/ - IOLOG_START_SERIAL - - // This is added by the code generator, it initialises the menu - setupMenu(); - - // check if the touch screen needs to be initialised, we provide a callback that will be called before and - // after the calibration UI is shown, it should reset the screen and touch to native orientation on start, and - // put it back to "menu" mode on finishing. - touchCalibrator.initCalibration([](bool starting) { - static iotouch::TouchOrientationSettings oldSettings = iotouch::TouchOrientationSettings(false, false, false); - if(starting) { - gfx.setRotation(0); - oldSettings = touchScreen.changeOrientation(iotouch::TouchOrientationSettings(false, true, true)); - } else { - gfx.setRotation(1); - touchScreen.changeOrientation(oldSettings); - } - }, true); - - // Add a callback to show the build version when the title is pressed - // this uses the standard function to show a version dialog from tcUtil.h - setTitlePressedCallback([](int) { - showVersionDialog(&applicationInfo); - }); - - // Add another button that directly controls the mute menu item - switches.addSwitch(22, [] (pinid_t key, bool held) { - if(!held) { - menuMute.setBoolean(!menuMute.getBoolean()); - } - }, NO_REPEAT); - - // and initialise the list menu item with the number of rows, see the list callback function below - // we set the number of items to all the files plus the refresh item - menuRootList.setNumberOfRows(FILE_NAME_SIZE + 1); -} - -void loop() { - taskManager.runLoop(); -} - -/** - * An example callback that was registered in the designer UI and generated for us here. - */ -void CALLBACK_FUNCTION onVolumeChanged(int /*id*/) { - serdebugF2("Volume changed ", menuVolume.getCurrentValue()); -} - -/** - * Here we create a task that will be scheduled to update the "second" dialog that appears. It keeps updating the - * count until the dialog is dismissed. - */ -class CountingTask : public Executable { -private: - MenuBasedDialog *dialog = nullptr; - int currentCount = 0; - taskid_t taskid = TASKMGR_INVALIDID; -public: - /** - * Store the dialog and reset. - * @param dlg the dialog manager - * @param taskIdParam the task id that was registered - */ - void init(MenuBasedDialog* dlg, taskid_t taskIdParam) { - dialog = dlg; - currentCount = 0; - taskid = taskIdParam; - } - - /** - * Called upon the schedule to bump the count and update the dialog - */ - void exec() override { - if(!dialog || taskid == TASKMGR_INVALIDID) return; - char sz[10]; - ltoaClrBuff(sz, ++currentCount, 4, NOT_PADDED, sizeof sz); - dialog->copyIntoBuffer(sz); - } - - /** - * Call this to deregister with task manager. - */ - void stop() { - if(taskid == TASKMGR_INVALIDID) return; - taskManager.cancelTask(taskid); - taskid = TASKMGR_INVALIDID; - dialog = nullptr; - } -} countingTask; - -/** - * When the 2nd dialog is dismissed, we stop the counting task - */ -void onCountingDlgComplete(ButtonType, void*) { - countingTask.stop(); -} - -/** - * When the first dialog is dismissed we check the button type and if it is accepted, we show a 2nd dialog - * @param btnPressed the button type pressed - * @param data this is the data provided in dialog's setUserData. - */ -void onCompletedDialog(ButtonType btnPressed, void* data) { - auto dlg = reinterpret_cast(data); - if(btnPressed == BTNTYPE_ACCEPT) { - dlg->setButtons(BTNTYPE_NONE, BTNTYPE_CLOSE, 0); - dlg->show("Pressed Accept", false, onCountingDlgComplete); - dlg->copyIntoBuffer(""); - auto taskId = taskManager.scheduleFixedRate(200, &countingTask); - countingTask.init(dlg, taskId); - } -} - -/** - * Show the first dialog, which has an accept and cancel button, when the show dialog menu item is pressed. - */ -void CALLBACK_FUNCTION onShowDialogs(int) { - withMenuDialogIfAvailable([](MenuBasedDialog *dlg) { - dlg->setButtons(BTNTYPE_ACCEPT, BTNTYPE_CANCEL, 1); - dlg->setUserData(dlg); - dlg->show("Dialogs test", true, onCompletedDialog); - dlg->copyIntoBuffer("Accept for more.."); - }); - -} - -/** - * Here we show a list callback that presents a list of "files", these simulated files are in a global array, but they - * could just as easily be somewhat dynamic and read from a proper source. - * See: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/list-menu-item/ - * @param item the actual list item - * @param row the currently selected row - * @param mode the action that is needed, eg copy value, invoke etc. - * @param buffer the buffer if appropriate for the action - * @param bufferSize the size of the buffer - * @return depends on the action, see the docs - */ -int CALLBACK_FUNCTION fnRootListRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize) { - switch(mode) { - case RENDERFN_ACTIVATE: - serlogF2(SER_DEBUG, "List activate ", row); - return false; - case RENDERFN_INVOKE: - // we have a list of files and a refresh option at the end. - if(row < FILE_NAME_SIZE) { - // a file has been selected, dismiss list. - serlogF2(SER_DEBUG, "List invoke: ", row); - menuMgr.resetMenu(false); // drop back one level dismissing the list - reinterpret_cast(item)->asParent(); - } else { - // refresh was selected, refresh and force recalc. - item->setNumberOfRows(item->getNumberOfRows() + 1); - menuMgr.recalculateListIfOnDisplay(item); - } - return true; - case RENDERFN_NAME: - strncpy(buffer, "Choose File", bufferSize); - return true; - case RENDERFN_VALUE: - if(row == LIST_PARENT_ITEM_POS) { - // no value on the parent item, IE when this list is displayed in a parent menu. - buffer[0]=0; - } else if(row < FILE_NAME_SIZE) { - // copy the file name into the buffer - strncpy(buffer, fileNames[row], bufferSize); - } else if(row == FILE_NAME_SIZE) { - strcpy(buffer, "Add more"); - } else { - ltoaClrBuff(buffer, row, 4, '0', bufferSize); - } - return true; - case RENDERFN_EEPROM_POS: return 0xffff; // lists are generally not saved to EEPROM - default: return false; - } -} - -// -// For Item: menuStatusInfo -// -// Here we present how to customize a runtime menu item such as a text item, RGB or Large number. You can take full -// control of the callback, or just override a few of the features to customize it. -// -// In this case we just want to override the name at runtime so we can change the name to be a counter of the number of -// times it is drawn. -// -// Steps -// 1. In the Designer of a text item, select "edit" next to the function callback text field -// 2. Select the "Runtime RenderFn override implementation" option -// 3. Once code generation the function is generated (exactly as below) -// -int CALLBACK_FUNCTION infoRenderingRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize) { - static int staticCounter = 0; - // See https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/based-on-runtimemenuitem/ - - switch(mode) { - case RENDERFN_NAME: - strncpy(buffer, "Count ", bufferSize); - fastltoa(buffer, staticCounter++, 7, NOT_PADDED, bufferSize); - return true; // override title by returning true - } - return textItemRenderFn(item, row, mode, buffer, bufferSize); -} - -/** - * How to change an item based on an Info block, such as Analog, Enum, Boolean, Float, Action and SubMenu. - * - * This is a standard callback function, it is attached in designer to the restart menu item. Here we show how to - * rename a menu item that is based on a menu info block. - */ -void CALLBACK_FUNCTION onRestart(int /*id*/) { - serdebugF("Restart selected"); - strncpy(minfoStatusRestart.name, "Restarting", NAME_SIZE_T); - menuStatusRestart.setChanged(true); -} diff --git a/examples/arduino32/piPicoTftTouch/piPicoTftTouch_menu.cpp b/examples/arduino32/piPicoTftTouch/piPicoTftTouch_menu.cpp deleted file mode 100644 index e1315745..00000000 --- a/examples/arduino32/piPicoTftTouch/piPicoTftTouch_menu.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#include -#include "piPicoTftTouch_menu.h" -#include "ThemeCoolBlueModern.h" -#include -#include - -// Global variable declarations -const ConnectorLocalInfo applicationInfo = { "RPiPico Tft Encoder", "0c6972c4-addb-4931-a910-e4b2a85d2b2a" }; - -TFT_eSPI gfx; -TfteSpiDrawable gfxDrawable(&gfx, 45); -GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); -iotouch::TftSpiTouchInterrogator touchInterrogator(&gfx, 4096, 4096, true); -iotouch::TouchOrientationSettings touchOrientation(true, false, false); -MenuTouchScreenManager touchScreen(&touchInterrogator, &renderer, touchOrientation); -tcextras::IoaTouchScreenCalibrator touchCalibrator(&touchScreen, &renderer, 400); - -// Global Menu Item declarations -const AnyMenuInfo minfoRootList = { "Root List", 17, 0xffff, 0, NO_CALLBACK }; -ListRuntimeMenuItem menuRootList(&minfoRootList, 0, fnRootListRtCall, nullptr, INFO_LOCATION_PGM); -const AnyMenuInfo minfoDialogs = { "Dialogs", 12, 0xffff, 0, onShowDialogs }; -ActionMenuItem menuDialogs(&minfoDialogs, &menuRootList, INFO_LOCATION_PGM); -RENDERING_CALLBACK_NAME_OVERRIDDEN(fnStatusInfoRtCall, infoRenderingRtCall, "Info", -1) -TextMenuItem menuStatusInfo(fnStatusInfoRtCall, "", 19, 5, nullptr); -AnyMenuInfo minfoStatusRestart = { "Restart", 11, 0xffff, 0, onRestart }; -ActionMenuItem menuStatusRestart(&minfoStatusRestart, &menuStatusInfo, INFO_LOCATION_RAM); -const FloatMenuInfo minfoStatusLineVoltage = { "Line Voltage", 10, 0xffff, 2, NO_CALLBACK }; -FloatMenuItem menuStatusLineVoltage(&minfoStatusLineVoltage, 235.0, &menuStatusRestart, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoStatusAmpPower = { "Amp Power", 9, 0xffff, 1, NO_CALLBACK, NAMING_ON_OFF }; -BooleanMenuItem menuStatusAmpPower(&minfoStatusAmpPower, false, &menuStatusLineVoltage, INFO_LOCATION_PGM); -const char enumStrStatusAmpStatus_0[] = "Standby"; -const char enumStrStatusAmpStatus_1[] = "Warm up"; -const char enumStrStatusAmpStatus_2[] = "DC protect"; -const char enumStrStatusAmpStatus_3[] = "Overload"; -const char enumStrStatusAmpStatus_4[] = "Overheat"; -const char* const enumStrStatusAmpStatus[] = { enumStrStatusAmpStatus_0, enumStrStatusAmpStatus_1, enumStrStatusAmpStatus_2, enumStrStatusAmpStatus_3, enumStrStatusAmpStatus_4 }; -const EnumMenuInfo minfoStatusAmpStatus = { "Amp Status", 8, 0xffff, 4, NO_CALLBACK, enumStrStatusAmpStatus }; -EnumMenuItem menuStatusAmpStatus(&minfoStatusAmpStatus, 0, &menuStatusAmpPower, INFO_LOCATION_PGM); -const SubMenuInfo minfoStatus = { "Status", 7, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackStatus(&minfoStatus, &menuStatusAmpStatus, INFO_LOCATION_PGM); -SubMenuItem menuStatus(&minfoStatus, &menuBackStatus, &menuDialogs, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSettingsNlge = { "NLge", 18, 0xffff, 0, NO_CALLBACK }; -EditableLargeNumberMenuItem menuSettingsNlge(&minfoSettingsNlge, LargeFixedNumber(8, 0, 0U, 0U, false), true, nullptr, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSettingsLargeNum = { "LargeNum", 16, 0xffff, 0, NO_CALLBACK }; -EditableLargeNumberMenuItem menuSettingsLargeNum(&minfoSettingsLargeNum, LargeFixedNumber(8, 3, 100U, 500U, false), false, &menuSettingsNlge, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSettingsRGB = { "RGB", 15, 0xffff, 0, NO_CALLBACK }; -Rgb32MenuItem menuSettingsRGB(&minfoSettingsRGB, RgbColor32(0, 0, 0), false, &menuSettingsLargeNum, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSettingsIP = { "IP", 14, 19, 0, NO_CALLBACK }; -IpAddressMenuItem menuSettingsIP(&minfoSettingsIP, IpAddressStorage(192, 168, 0, 33), &menuSettingsRGB, INFO_LOCATION_PGM); -const AnyMenuInfo minfoSettingsText = { "Text", 13, 9, 0, NO_CALLBACK }; -TextMenuItem menuSettingsText(&minfoSettingsText, "hello", 10, &menuSettingsIP, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoSettingsProtection = { "Protection", 6, 0xffff, 1, NO_CALLBACK, NAMING_ON_OFF }; -BooleanMenuItem menuSettingsProtection(&minfoSettingsProtection, false, &menuSettingsText, INFO_LOCATION_PGM); -const AnalogMenuInfo minfoSettingsMaxOnVolume = { "Max On Volume", 5, 7, 255, NO_CALLBACK, -180, 2, "dB" }; -AnalogMenuItem menuSettingsMaxOnVolume(&minfoSettingsMaxOnVolume, 144, &menuSettingsProtection, INFO_LOCATION_PGM); -const SubMenuInfo minfoSettings = { "Settings", 4, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackSettings(&minfoSettings, &menuSettingsMaxOnVolume, INFO_LOCATION_PGM); -SubMenuItem menuSettings(&minfoSettings, &menuBackSettings, &menuStatus, INFO_LOCATION_PGM); -const BooleanMenuInfo minfoMute = { "Mute", 3, 4, 1, NO_CALLBACK, NAMING_TRUE_FALSE }; -BooleanMenuItem menuMute(&minfoMute, false, &menuSettings, INFO_LOCATION_PGM); -const char enumStrInput_0[] = "CD Player"; -const char enumStrInput_1[] = "Computer USB"; -const char enumStrInput_2[] = "Turntable"; -const char enumStrInput_3[] = "Line 1"; -const char* const enumStrInput[] = { enumStrInput_0, enumStrInput_1, enumStrInput_2, enumStrInput_3 }; -const EnumMenuInfo minfoInput = { "Input", 2, 5, 3, NO_CALLBACK, enumStrInput }; -EnumMenuItem menuInput(&minfoInput, 2, &menuMute, INFO_LOCATION_PGM); -const AnalogMenuInfo minfoVolume = { "Volume", 1, 2, 255, onVolumeChanged, -180, 2, "dB" }; -AnalogMenuItem menuVolume(&minfoVolume, 80, &menuInput, INFO_LOCATION_PGM); - -void setupMenu() { - // First we set up eeprom and authentication (if needed). - setSizeBasedEEPROMStorageEnabled(false); - // Code generated by plugins. - gfx.begin(); - gfx.setRotation(1); - renderer.setUpdatesPerSecond(15); - touchScreen.start(); - menuMgr.initWithoutInput(&renderer, &menuVolume); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(true); - renderer.enableTcUnicode(); - installCoolBlueModernTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin18, 0), MenuFontDef(&RobotoMedium24, 1), false); -} - diff --git a/examples/arduino32/piPicoTftTouch/piPicoTftTouch_menu.h b/examples/arduino32/piPicoTftTouch/piPicoTftTouch_menu.h deleted file mode 100644 index 6058ced8..00000000 --- a/examples/arduino32/piPicoTftTouch/piPicoTftTouch_menu.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#ifndef MENU_GENERATED_CODE_H -#define MENU_GENERATED_CODE_H - -#include -#include -#include -#include "tcMenuTfteSpi.h" -#include -#include -#include -#include -#include -#include -#include - -// variables we declare that you may need to access -extern const PROGMEM ConnectorLocalInfo applicationInfo; -extern TFT_eSPI gfx; -extern TfteSpiDrawable gfxDrawable; -extern GraphicsDeviceRenderer renderer; -extern iotouch::TftSpiTouchInterrogator touchInterrogator; -extern MenuTouchScreenManager touchScreen; -extern tcextras::IoaTouchScreenCalibrator touchCalibrator; -extern const UnicodeFont OpenSansCyrillicLatin18[]; -extern const GFXfont RobotoMedium24; - -// Any externals needed by IO expanders, EEPROMs etc - - -// Global Menu Item exports -extern ListRuntimeMenuItem menuRootList; -extern ActionMenuItem menuDialogs; -extern TextMenuItem menuStatusInfo; -extern AnyMenuInfo minfoStatusRestart; -extern ActionMenuItem menuStatusRestart; -extern FloatMenuItem menuStatusLineVoltage; -extern BooleanMenuItem menuStatusAmpPower; -extern EnumMenuItem menuStatusAmpStatus; -extern BackMenuItem menuBackStatus; -extern SubMenuItem menuStatus; -extern EditableLargeNumberMenuItem menuSettingsNlge; -extern EditableLargeNumberMenuItem menuSettingsLargeNum; -extern Rgb32MenuItem menuSettingsRGB; -extern IpAddressMenuItem menuSettingsIP; -extern TextMenuItem menuSettingsText; -extern BooleanMenuItem menuSettingsProtection; -extern AnalogMenuItem menuSettingsMaxOnVolume; -extern BackMenuItem menuBackSettings; -extern SubMenuItem menuSettings; -extern BooleanMenuItem menuMute; -extern EnumMenuItem menuInput; -extern AnalogMenuItem menuVolume; - -// Provide a wrapper to get hold of the root menu item and export setupMenu -inline MenuItem& rootMenuItem() { return menuVolume; } -void setupMenu(); - -// Callback functions must always include CALLBACK_FUNCTION after the return type -#define CALLBACK_FUNCTION - -int fnRootListRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize); -int infoRenderingRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize); -void CALLBACK_FUNCTION onRestart(int id); -void CALLBACK_FUNCTION onShowDialogs(int id); -void CALLBACK_FUNCTION onVolumeChanged(int id); - -#endif // MENU_GENERATED_CODE_H diff --git a/examples/arduino32/piPicoTftTouch/tcMenuTfteSpi.cpp b/examples/arduino32/piPicoTftTouch/tcMenuTfteSpi.cpp deleted file mode 100644 index 6286c6fa..00000000 --- a/examples/arduino32/piPicoTftTouch/tcMenuTfteSpi.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * TFT_eSPI renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - * - * LIBRARY REQUIREMENT - * This library requires the AdaGfx library along with a suitable driver. - */ - -#include "tcMenuTfteSpi.h" -#include "tcUnicodeTFT_eSPI.h" -#include - -using namespace iotouch; -using namespace tcgfx; - -TfteSpiDrawable::TfteSpiDrawable(TFT_eSPI *tft, int spriteHeight) : tft(tft), spriteWithConfig(nullptr), spriteHeight(spriteHeight) {} - -DeviceDrawable *TfteSpiDrawable::getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) { - if(paletteSize > SPRITE_PALETTE_SIZE) return nullptr; // cant exceed color palette size - - if(spriteWithConfig == nullptr) spriteWithConfig = new TftSpriteAndConfig(this, tft->width(), spriteHeight); - if(!spriteWithConfig) return nullptr; - - if(spriteWithConfig->initSprite(where, size, palette, paletteSize)) { - return spriteWithConfig; - } - else return nullptr; -} - -void TfteSpiDrawable::internalDrawText(const Coord &where, const void *font, int mag, const char *text) { - fontPtrToNum(font, mag); - tft->setTextColor(drawColor, drawColor); // transparent background - tft->drawString(text, where.x, where.y); -} - -void TfteSpiDrawable::drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) { - if(icon->getIconType() == DrawableIcon::ICON_XBITMAP) { - tft->drawXBitmap(where.x, where.y, icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y, drawColor, backgroundColor); - } - else if(icon->getIconType() == DrawableIcon::ICON_MONO) { - tft->drawBitmap(where.x, where.y, icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y, drawColor, backgroundColor); - } - else if(icon->getIconType() == DrawableIcon::ICON_NATIVE) { - tft->pushImage(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, (const uint16_t*)icon->getIcon(selected)); - } -} - -void TfteSpiDrawable::drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) { - tft->drawXBitmap(where.x, where.y, data, size.x, size.y, drawColor, backgroundColor); -} - -void TfteSpiDrawable::drawBox(const Coord &where, const Coord &size, bool filled) { - if(filled) { - tft->fillRect(where.x, where.y, size.x, size.y, drawColor); - } - else { - tft->drawRect(where.x, where.y, size.x, size.y, drawColor); - } -} - -void TfteSpiDrawable::drawCircle(const Coord &where, int radius, bool filled) { - if(filled) { - tft->fillCircle(where.x, where.y, radius, drawColor); - } - else { - tft->drawCircle(where.x, where.y, radius, drawColor); - } -} - -void TfteSpiDrawable::drawPolygon(const Coord *points, int numPoints, bool filled) { - if(numPoints == 2) { - tft->drawLine(points[0].x, points[0].y, points[1].x, points[1].y, drawColor); - } - else if(numPoints == 3) { - if(filled) { - tft->fillTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, drawColor); - } - else { - tft->drawTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, drawColor); - } - } -} - -void TfteSpiDrawable::transaction(bool isStarting, bool redrawNeeded) { - if(isStarting) tft->setTextDatum(TL_DATUM); -} - -Coord TfteSpiDrawable::internalTextExtents(const void *font, int mag, const char *text, int *baseline) { - if(baseline) *baseline = 0; - fontPtrToNum(font, mag); - return Coord(tft->textWidth(text), tft->fontHeight()); -} - -void TfteSpiDrawable::drawPixel(uint16_t x, uint16_t y) { - tft->drawPixel(x, y, drawColor); -} - -void TfteSpiDrawable::fontPtrToNum(const void* font, int mag) { - if(font == nullptr) { - tft->setTextFont((uint8_t) mag); - } - else { - tft->setFreeFont(static_cast(font)); - } -} - -UnicodeFontHandler *TfteSpiDrawable::createFontHandler() { - return fontHandler = new UnicodeFontHandler(newTFT_eSPITextPipeline(tft), tccore::ENCMODE_UTF8); -} - -// -// Sprite object -// - -TftSpriteAndConfig::TftSpriteAndConfig(TfteSpiDrawable *root, int width, int height) : TfteSpiDrawable(&sprite, 0), - root(root), sprite(root->getTFT()), where(0,0), currentSize(0, 0), size(width, height), currentColorsDefined(0) { -} - -bool TftSpriteAndConfig::initSprite(const Coord &spriteWhere, const Coord &spriteSize, const color_t* palette, int palEntries) { - // if the area is too big, or the sprite is in use, don't proceed. - if(spriteSize.x > size.x || spriteSize.y > size.y) return false; - - if(root->isTcUnicodeEnabled() && fontHandler == nullptr) { - fontHandler = new UnicodeFontHandler(newTFT_eSPITextPipeline(&sprite), tccore::ENCMODE_UTF8); - } - - // create the sprite if needed - if(!sprite.created()) { - sprite.createSprite(size.x, size.y); - sprite.setColorDepth(4); - } - for(int i=0; igetTouchRaw(&touchX, &touchY); - pressed = tft->getTouchRawZ() > 600; - *ptrX = calib.calibrateX(float(touchX) / XPT_2046_MAX, rotation.isXInverted()); - *ptrY = calib.calibrateY(float(touchY) / XPT_2046_MAX, rotation.isYInverted()); - } else { - pressed = tft->getTouch(&touchX, &touchY); - *ptrX = calib.calibrateX(float(touchX) / maxWidthDim, rotation.isXInverted()); - *ptrY = calib.calibrateY(float(touchY) / maxHeightDim, rotation.isYInverted()); - } - - if(!pressed) return iotouch::NOT_TOUCHED; - //serdebugF3("point at ", touchX, touchY); - - return iotouch::TOUCHED; -} -#endif // TC_TFT_ESPI_NEEDS_TOUCH == true diff --git a/examples/arduino32/piPicoTftTouch/tcMenuTfteSpi.h b/examples/arduino32/piPicoTftTouch/tcMenuTfteSpi.h deleted file mode 100644 index 472ed10b..00000000 --- a/examples/arduino32/piPicoTftTouch/tcMenuTfteSpi.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * TFT_eSPI renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - */ - -#ifndef TCMENU_PLUGIN_TCMENUTFTESPI_H -#define TCMENU_PLUGIN_TCMENUTFTESPI_H - -#include -#include -#include -#include -#include - -#define TFT_SPRITE_BITS 4 -#define SPRITE_PALETTE_SIZE (1 << TFT_SPRITE_BITS) - -using namespace tcgfx; - -class TftSpriteAndConfig; - -class TfteSpiDrawable : public DeviceDrawable { -private: - TFT_eSPI* tft; - TftSpriteAndConfig* spriteWithConfig; - uint16_t spriteHeight; -public: - TfteSpiDrawable(TFT_eSPI *tft, int maxSpriteHeight); - - DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) override; - - void internalDrawText(const Coord &where, const void *font, int mag, const char *text) override; - - void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override; - - void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override; - - void drawBox(const Coord &where, const Coord &size, bool filled) override; - - void drawCircle(const Coord &where, int radius, bool filled) override; - - void drawPolygon(const Coord *points, int numPoints, bool filled) override; - - void drawPixel(uint16_t x, uint16_t y) override; - - void transaction(bool isStarting, bool redrawNeeded) override; - - Coord internalTextExtents(const void *font, int mag, const char *text, int *baseline) override; - Coord getDisplayDimensions() override { return Coord(tft->width(), tft->height());} - TFT_eSPI* getTFT() { return tft; } -protected: - UnicodeFontHandler* createFontHandler() override; -private: - void fontPtrToNum(const void* font, int mag); -}; - -class TftSpriteAndConfig : public TfteSpiDrawable { -private: - TfteSpiDrawable* root; - TFT_eSprite sprite; - Coord where; - Coord currentSize; - const Coord size; - uint8_t currentColorsDefined; -public: - TftSpriteAndConfig(TfteSpiDrawable *root, int width, int height); - - bool initSprite(const Coord& spriteWhere, const Coord& spriteSize, const color_t* palette, int paletteEntries); - DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) override { return nullptr; } - void transaction(bool isStarting, bool redrawNeeded) override; - color_t getUnderlyingColor(color_t col) override; -}; - -#define TC_TFT_ESPI_NEEDS_TOUCH true -#if TC_TFT_ESPI_NEEDS_TOUCH == true - -#define XPT_2046_MAX 4096 - -namespace iotouch { - - /** - * Implements the touch interrogator class, this purely gets the current reading from the device when requested. This - * implementation works with the TFT_eSPI touch functions providing tcMenu support for it. It is your responsibility - * to have run whatever calibration is needed before calling this function. The X and Y values to the constructor - * are the maximum values that can be returned by calling getTouch. - */ - class TftSpiTouchInterrogator : public iotouch::TouchInterrogator { - private: - TFT_eSPI* tft; - float maxWidthDim; - float maxHeightDim; - bool usingRawTouch; - public: - TftSpiTouchInterrogator(TFT_eSPI* tft, uint16_t xMax, uint16_t yMax, bool rawTouch) - : tft(tft), maxWidthDim(xMax), maxHeightDim(yMax), usingRawTouch(rawTouch) { } - - iotouch::TouchState internalProcessTouch(float *ptrX, float *ptrY, const TouchOrientationSettings& touchOrientationSettings, - const iotouch::CalibrationHandler& calib) override; - }; - -} -#endif // TC_TFT_ESPI_NEEDS_TOUCH == true - -#endif //TCMENU_PLUGIN_TCMENUTFTESPI_H diff --git a/examples/arduino32/picoAdafruitDashboard/ThemeCoolBlueModern.h b/examples/arduino32/picoAdafruitDashboard/ThemeCoolBlueModern.h deleted file mode 100644 index 757ca5c8..00000000 --- a/examples/arduino32/picoAdafruitDashboard/ThemeCoolBlueModern.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Cool blue modern theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. - * This file will not be updated by the designer, you can edit. - */ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -#include - -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; -const color_t coolBlueActionPalette[] = {RGB(255, 255, 255), RGB(0,45,120), RGB(20,133,255), RGB(31,100,178)}; - -#define ACTION_BORDER_WIDTH 0 - -void installCoolBlueModernTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // here we get a refrerence to the drawable and then set the dimensions. - auto* rootDrawable = bgr.getDeviceDrawable(); - bgr.setDisplayDimensions(rootDrawable->getDisplayDimensions().x, rootDrawable->getDisplayDimensions().y); - - // we need a reference to the factory object that we will use to configure the drawing. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // change the selected colours. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // for this theme we use the same size padding for each case, we need touchable items. We calculate the height too - MenuPadding allPadding(4, 3, 4, 3); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, allPadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, allPadding); - - // now we configure the drawing for each item type - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, allPadding, titleFont.fontData, titleFont.fontMag, 3, titleHeight, - GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, - GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueActionPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, - GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(ACTION_BORDER_WIDTH)); - - // and lastly, whenever changing the configuration, we must refresh. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE \ No newline at end of file diff --git a/examples/esp/espCapTouchTft/ThemeDarkModeTraditionalBuilder.h b/examples/arduino32/picoAdafruitDashboard/ThemeCoolBlueTraditionalBuilder.h similarity index 60% rename from examples/esp/espCapTouchTft/ThemeDarkModeTraditionalBuilder.h rename to examples/arduino32/picoAdafruitDashboard/ThemeCoolBlueTraditionalBuilder.h index f5510085..8553b9ed 100644 --- a/examples/esp/espCapTouchTft/ThemeDarkModeTraditionalBuilder.h +++ b/examples/arduino32/picoAdafruitDashboard/ThemeCoolBlueTraditionalBuilder.h @@ -1,15 +1,22 @@ /** - * Dark mode modern theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. + * Cool blue traditional theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. * This file will not be updated by the designer, you can edit. + * See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/themes/rendering-with-themes-icons-grids/ */ -#ifndef THEME_DARK_MODE -#define THEME_DARK_MODE + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE #include -const color_t darkModeTitlePalette[] = {RGB(255,255,255), RGB(43,43,43), RGB(192,192,192), RGB(0,133,255)}; -const color_t darkModeItemPalette[] = {RGB(255, 255, 255), RGB(0,0,0), RGB(43,43,43), RGB(65,65,65)}; -const color_t darkModeActionPalette[] = {RGB(255, 255, 255), RGB(35,35,35), RGB(20,45,110), RGB(192,192,192)}; +// +// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() +// + +// tcMenu drawing properties take a 4 color palette for items, titles and actions. +// this renderer shares the color configuration for items and actions. +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; /** * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu @@ -21,20 +28,21 @@ const color_t darkModeActionPalette[] = {RGB(255, 255, 255), RGB(35,35,35), RGB( * @param titleMode the way that the title should be drawn (choose from the enum values) * @param useUnicode if using tcUnicode drawing functions */ -void installDarkModeTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, - bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { +void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ TcThemeBuilder themeBuilder(gr); bool medResOrBetter = gr.getWidth() > 160; MenuPadding titlePadding(medResOrBetter ? 4 : 2); MenuPadding itemPadding(medResOrBetter ? 2 : 1); themeBuilder.dimensionsFromRenderer() - .withSelectedColors(RGB(46, 66, 161), RGB(255, 255, 255)) + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) .withItemPadding(itemPadding) .withTitlePadding(titlePadding) .withRenderingSettings(titleMode, false) - .withPalette(darkModeItemPalette) + .withPalette(coolBlueItemPalette) .withNativeFont(itemFont.fontData, itemFont.fontMag) .withSpacing(1); @@ -57,16 +65,15 @@ void installDarkModeTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontD themeBuilder.defaultTitleProperties() .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) .withNativeFont(titleFont.fontData, titleFont.fontMag) - .withPalette(darkModeTitlePalette) + .withPalette(coolBlueTitlePalette) .withSpacing(medResOrBetter ? 3 : 1) .apply(); themeBuilder.defaultActionProperties() - .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) - .withPalette(darkModeActionPalette) + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) .apply(); themeBuilder.apply(); } -#endif //THEME_DARK_MODE +#endif //THEME_COOL_BLUE diff --git a/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard.emf b/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard.emf index cdb1e974..5a919250 100644 --- a/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard.emf +++ b/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard.emf @@ -161,7 +161,7 @@ "lastRemoteUuids": [ "1e38dc42-672d-4c1c-a393-2c7632bf6c5c" ], - "lastThemeUuid": "850dc0a3-f534-47c2-94d8-1e64ff368a54", + "lastThemeUuid": "57945787-0A04-447B-BBA2-6461FC505397", "applicationUUID": "0ad4bdde-34a4-4507-912e-b495b0eac2c1", "applicationName": "%project.name", "lastProperties": [ @@ -282,17 +282,12 @@ }, { "name": "ITEM_FONT", - "latestValue": "ada:RobotoMedium24,1", + "latestValue": "ada:OpenSansRegular18pt,0", "subsystem": "THEME" }, { "name": "TITLE_FONT", - "latestValue": "ada:RobotoMedium24,1", - "subsystem": "THEME" - }, - { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", + "latestValue": "ada:RobotoMedium24,0", "subsystem": "THEME" }, { @@ -302,11 +297,6 @@ }, { "name": "USE_TC_UNICODE", - "latestValue": "false", - "subsystem": "THEME" - }, - { - "name": "USE_SLIDER_ANALOG", "latestValue": "true", "subsystem": "THEME" }, @@ -329,10 +319,7 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [ - "Mobile Pico" - ] + "appIsModular": false }, "stringLists": [] } \ No newline at end of file diff --git a/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.cpp b/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.cpp index 45b1c5a3..3ee1910a 100644 --- a/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.cpp +++ b/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.cpp @@ -8,9 +8,12 @@ use elsewhere. */ +// Generated for Arduino 32bit ARM by TcMenu 4.3.1 on 2024-10-05T13:45:33.378923800Z. + #include #include "picoAdafruitDashboard_menu.h" -#include "ThemeCoolBlueModern.h" +#include "ThemeCoolBlueTraditionalBuilder.h" +#include #include // Global variable declarations @@ -51,7 +54,6 @@ AnalogMenuItem menuAnalog(&minfoAnalog, 222, &menuFloat, INFO_LOCATION_PGM); void setupMenu() { // First we set up eeprom and authentication (if needed). - CombinedMessageProcessor::setFormTemplatesInFlash(tcMenuAllEmbeddedForms); setSizeBasedEEPROMStorageEnabled(false); // Code generated by plugins and new operators. gfx.begin(); @@ -60,46 +62,6 @@ void setupMenu() { switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); menuMgr.initForEncoder(&renderer, &menuAnalog, 16, 17, 21); remoteServer.addConnection(&serialConnection); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(true); - installCoolBlueModernTheme(renderer, MenuFontDef(&RobotoMedium24, 1), MenuFontDef(&RobotoMedium24, 1), false); + installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansRegular18pt, 0), MenuFontDef(&RobotoMedium24, 0), false, BaseGraphicalRenderer::TITLE_FIRST_ROW, true); } -// Embedded form data - -const uint8_t formData_MobilePico_d8[] { -0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xcd,0x94,0xdb,0x4b,0xc3,0x30, -0x18,0xc5,0xdf,0x05,0xff,0x87,0x10,0xf0,0x6d,0xb5,0x69,0x57,0x2f,0x83,0x56,0xd1, -0x59,0x2f,0xb0,0xb5,0x63,0xa6,0xea,0xdb,0x48,0x9b,0x28,0x85,0x34,0x9f,0xf4,0xe2, -0xe5,0xbf,0xf7,0x6b,0x1d,0xda,0x29,0xa2,0x0f,0x13,0x7d,0x4b,0x4e,0xc2,0xf9,0x7e, -0x39,0x81,0xe3,0x1f,0x3e,0x15,0x9a,0x3c,0xa8,0xb2,0xca,0xc1,0x04,0xd4,0xd9,0x66, -0x94,0x28,0x93,0x81,0xcc,0xcd,0x5d,0x40,0x13,0x7e,0x6a,0xed,0x53,0x52,0xd5,0xc2, -0x48,0xa1,0xc1,0xa8,0x80,0x1a,0xa0,0x87,0x07,0x9b,0x1b,0x7e,0x58,0xa4,0x4a,0x8e, -0xc1,0xd4,0x25,0x68,0x92,0x82,0x28,0x65,0xd2,0xe4,0x32,0xa0,0x4c,0x48,0x2f,0x95, -0x52,0x59,0x43,0x4f,0x78,0x96,0xb7,0xc3,0xf6,0xac,0x91,0xe3,0x2a,0x2b,0xf5,0x46, -0x3b,0x29,0x53,0x22,0x73,0x33,0x87,0x12,0x2d,0x9e,0xa1,0xa9,0x23,0x51,0xa0,0xe3, -0x14,0xd2,0x5c,0x2b,0x32,0xcb,0x33,0xa0,0xe8,0x4c,0x88,0x3f,0x55,0xa6,0x99,0x74, -0x37,0xaa,0x4e,0x58,0x91,0x48,0x06,0xba,0x0a,0xa8,0x4b,0xc9,0x2d,0x4e,0xbf,0x30, -0xb7,0x80,0xd8,0x8c,0x6d,0x51,0x52,0xaa,0xac,0xc1,0x77,0x3c,0xa0,0x67,0x5d,0x36, -0x0a,0x05,0x80,0xfa,0xa2,0x65,0xa2,0x4b,0x9b,0xa5,0x51,0xa8,0x55,0xa1,0x4c,0x4d, -0x84,0xce,0xef,0x4c,0xbb,0x0a,0xe8,0x24,0x3c,0xe5,0xb4,0xb5,0x86,0xf2,0x52,0xe1, -0xfe,0x4c,0x43,0x2a,0x74,0xab,0x74,0x2f,0xe4,0xcf,0xf7,0xe8,0x9a,0xcc,0x16,0x27, -0xf1,0x75,0xb4,0x18,0xc7,0x11,0x9f,0xc7,0x13,0x3c,0x6d,0xaa,0x1a,0x8a,0x93,0x52, -0x3c,0xb6,0xc1,0x18,0x1c,0x29,0x71,0x3d,0x05,0x89,0x97,0x2f,0xcf,0xe3,0xeb,0x45, -0x74,0x34,0x0d,0x17,0x57,0x47,0x93,0x24,0xfc,0x8c,0x8b,0x83,0x9b,0x96,0x0e,0xe3, -0xb8,0x87,0x2a,0xaf,0xbb,0x0f,0x60,0x03,0x36,0x70,0x06,0x2e,0xb5,0xd7,0x43,0xcc, -0xc3,0x1b,0xbe,0x66,0x5c,0xb7,0x8f,0xeb,0xac,0x17,0xf7,0x77,0x02,0x1e,0xf6,0x89, -0xdd,0x1f,0x13,0x8f,0xc3,0x88,0x87,0xf3,0x6f,0x99,0x8f,0x13,0xce,0xe3,0x75,0x23, -0x7b,0x7d,0xe4,0xe1,0x80,0xfd,0x31,0xee,0xd7,0xa0,0xbb,0xab,0xa0,0xce,0x3f,0xcf, -0x75,0xbf,0x8f,0xeb,0xfd,0x79,0xae,0xdf,0xe1,0x8e,0x56,0x71,0xdf,0xd3,0xf5,0xed, -0xf7,0x42,0x7c,0xed,0x4c,0xfb,0x63,0x69,0xfa,0xe3,0x25,0x70,0x65,0x2f,0xf7,0x6f, -0x44,0xd8,0xed,0x9d,0xe8,0xdb,0xfd,0x16,0x47,0xe1,0x05,0xa0,0xe7,0xfa,0xa6,0x0e, -0x06,0x00,0x00 -}; -const EmbedControlFlashedForm formData_MobilePico { - "Mobile Pico", - formData_MobilePico_d8, - 419 -}; - -const EmbedControlFlashedForm* tcMenuAllEmbeddedForms[] { &formData_MobilePico, nullptr }; diff --git a/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.h b/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.h index a9c83db7..364e9cdf 100644 --- a/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.h +++ b/examples/arduino32/picoAdafruitDashboard/picoAdafruitDashboard_menu.h @@ -13,6 +13,7 @@ #include #include +#include #include "tcMenuAdaFruitGfx.h" #include #include "SerialTransport.h" @@ -27,7 +28,8 @@ extern TcMenuRemoteServer remoteServer; extern Adafruit_ILI9341 gfx; extern AdafruitDrawable gfxDrawable; extern GraphicsDeviceRenderer renderer; -extern const GFXfont RobotoMedium24; +extern const UnicodeFont OpenSansRegular18pt[]; +extern const UnicodeFont RobotoMedium24[]; // Any externals needed by IO expanders, EEPROMs etc @@ -53,6 +55,4 @@ void setupMenu(); void CALLBACK_FUNCTION onSettingsAction(int id); -extern const EmbedControlFlashedForm* tcMenuAllEmbeddedForms[]; - #endif // MENU_GENERATED_CODE_H diff --git a/examples/arduino32/r4UnoButtonsTft/DiscoTime.cpp b/examples/arduino32/r4UnoButtonsTft/DiscoTime.cpp new file mode 100644 index 00000000..c19568a4 --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/DiscoTime.cpp @@ -0,0 +1,191 @@ +/** + * Create an event that will run our LED Matrix as something akin to disco lights. When the disco is running it will + * schedule very frequently and use an AdaFruit_GFX GFXCanvas1 to represent the 12x8 display, and with that you can + * draw anything onto it that is possible with Adafruit_GFX. Feel free to make it better! + * + * This also shows how to create custom messages, we have two custom "disco messages" that the Java API can receive and + * you can easily create additional protocol handlers to process them. + */ + +#include "DiscoTime.h" +#include +#include + +// +// Here we pre-define a few custom tags for the custom tag val message we send later on. Each key in a tag val message +// is two characters. Use 'Z' and 'z' for you own custom ones. This gives you around 100 possibilities. +// +#define MY_CUSTOM_DISCO_MSG msgFieldToWord('Z', 'D') +#define MY_CUSTOM_XBMP_MSG msgFieldToWord('Z', 'X') +#define MY_CUSTOM_DISCO_NAME_FIELD msgFieldToWord('Z', 'N') +#define MY_CUSTOM_DISCO_STATUS_FIELD msgFieldToWord('Z', 'B') + +ArduinoLEDMatrix matrix; + +void DiscoTime::stop() { + serlogF(SER_DEBUG, "Stop disco"); + discoIsRunning = false; + sendDiscoMsg(); + +} + +void DiscoTime::init() { + matrix.begin(); + taskManager.registerEvent(this); +} + +void DiscoTime::start(int sp) { + serlogF(SER_DEBUG, "Init disco"); + discoIsRunning = true; + speed = sp; + switchMode(SQUARES); + sendDiscoMsg(); +} + +// This is called during event handling, we can set here when we want to be asked again if the event is triggered. +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-iot/embed-control-tagval-wire-protocol/ +uint32_t DiscoTime::timeOfNextCheck() { + setTriggered(discoIsRunning); + return discoIsRunning ? millisToMicros(speed) : secondsToMicros(1); +} + +// Again this is part of the above event, if we are considered triggered, then this method is called, it works out +// which animation is running, and calls the right one. +void DiscoTime::exec() { + currPos++; + if(mode == TEXT) { + drawText(); + } else if(mode == SQUARES) { + runSquares(); + } else if(mode == STROBE) { + runStrobe(); + } else if(mode == CIRCLES){ + runCircles(); + } +} + +// Put an XBMP image onto the display using the canvas. +void DiscoTime::picture(const uint8_t* xbmpData) { + stop(); + switchMode(PICTURE); + serlogF(SER_DEBUG, "Picture"); + + canvas.fillScreen(0); + canvas.drawXBitmap(0, 0, xbmpData, 12, 8, 1); + sendXbmpData(xbmpData, 16); + drawCanvasToLeds(); +} + +// schedule text to be drawn onto the display +void DiscoTime::text(const char *data) { + start(500); + mode = TEXT; + currPos = 0; + strncpy(textBuffer, data, sizeof textBuffer); + serlogF3(SER_DEBUG, "Start Text", data, textBuffer); + textBuffer[sizeof(textBuffer)-1] = 0; +} + +// draw one character at a time onto the display +void DiscoTime::drawText() { + if(currPos >= strlen(textBuffer)) { + currPos = 0; + } + serlogF3(SER_DEBUG, "Text: ", (int)textBuffer[currPos], currPos); + canvas.fillScreen(0); + unicodeHelper.setCursor(0,7); + unicodeHelper.setDrawColor(1); + unicodeHelper.setFont(OpenSansRegular7pt); + unicodeHelper.print(textBuffer[currPos]); + drawCanvasToLeds(); +} + +// This actually maps every pixel on the matrix to the canvas. +void DiscoTime::drawCanvasToLeds() { + uint32_t output[3] = {0}; + int position = 0; + for(int row=0; row<8; row++) { + for(int col=0; col<12; col++) { + auto pix = canvas.getPixel(col, row); + if(pix) { + output[position / 32] |= (1 << ((31 - (position % 32)))); + // enable only for debugging + //serlogF4(SER_DEBUG, "Pix/y pos on ", col, row, position); + } + position++; + } + } + // enable only for debugging + //serlogHexDump(SER_DEBUG, "Output=", output, 8); + matrix.loadFrame(output); +} + +void DiscoTime::runStrobe() { + auto col = (currPos % 2 == 1); + canvas.fillScreen(col); + drawCanvasToLeds(); + + if(loopTimer++ > 100) switchMode(SQUARES); +} + +void DiscoTime::runCircles() { + canvas.fillScreen(0); + int rad = currPos % 7; + if(currPos > 36) { + canvas.fillCircle(6, 4, rad, 1); + } else { + canvas.drawCircle(6, 4, rad, 1); + } + drawCanvasToLeds(); + if(loopTimer++ > 100) switchMode(STROBE); +} + +void DiscoTime::runSquares() { + canvas.fillScreen(0); + int rad = currPos % 12; + if(currPos > 36) { + canvas.fillRect(0, 0, rad + 1, rad + 1, 1); + } else { + canvas.drawRect(0, 0, rad + 1, rad + 1, 1); + } + drawCanvasToLeds(); + if(loopTimer++ > 100) switchMode(CIRCLES); +} + +void DiscoTime::switchMode(DiscoMode m) { + mode = m; + loopTimer = currPos = 0; +} + +DiscoTime::DiscoTime() : canvas(12, 8), textBuffer{}, unicodeHelper(newAdafruitTextPipeline(&canvas), ENCMODE_UTF8) { +} + +// +// ADVANCED +// Here is how we send a custom tag val message to the remote server, we call the `encodeCustomTagValMessage` method +// providing a lambda, we only get into the lambda if the connection is made, and we then just write the fields we +// need to write. +// For the second case of binary message, we simply encode the binary data within the lambda callback instead of +// tag val fields. +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-iot/embed-control-tagval-wire-protocol/ +// +void DiscoTime::sendDiscoMsg() { + auto tagValConnector = remoteServer.getRemoteConnector(0); + tagValConnector->encodeCustomTagValMessage(MY_CUSTOM_DISCO_MSG, [](TagValueTransport* transport, void* data) { + auto myDisco = (DiscoTime*)data; + transport->writeField(MY_CUSTOM_DISCO_NAME_FIELD, "Disco"); + transport->writeFieldInt(MY_CUSTOM_DISCO_STATUS_FIELD, myDisco->discoIsRunning); + }, this); +} + +void DiscoTime::sendXbmpData(const uint8_t* xbmpData, size_t length) { + auto tagValConnector = remoteServer.getRemoteConnector(0); + tagValConnector->encodeCustomBinaryMessage(MY_CUSTOM_XBMP_MSG, length, [](TagValueTransport* transport, void* data, size_t len) { + auto xbmpData = (uint8_t*)data; + for(auto i=0; i< len; ++i) { + transport->writeChar(xbmpData[i]); + } + }, (void*)xbmpData); + + +} diff --git a/examples/arduino32/r4UnoButtonsTft/DiscoTime.h b/examples/arduino32/r4UnoButtonsTft/DiscoTime.h new file mode 100644 index 00000000..2e6b7643 --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/DiscoTime.h @@ -0,0 +1,77 @@ + +#ifndef TCLIBRARYDEV_DISCOTIME_H +#define TCLIBRARYDEV_DISCOTIME_H + +#include "r4UnoButtonsTft_menu.h" +#include +#include + +/** + * Create an event that will run our LED Matrix as something akin to disco lights. When the disco is running it will + * schedule very frequently and use an AdaFruit_GFX GFXCanvas1 to represent the 12x8 display, and with that you can + * draw anything onto it that is possible with Adafruit_GFX. Feel free to make it better! + * + * This also shows how to create custom messages, we have two custom "disco messages" that the Java API can receive and + * you can easily create additional protocol handlers to process them. + */ +class DiscoTime : public BaseEvent { +public: + // the types of disco lights we have! + enum DiscoMode { TEXT, CIRCLES, SQUARES, STROBE, PICTURE }; +private: + // when the disco is running, this is true + bool discoIsRunning = false; + // the speed of our disco in milliseconds + int speed = 250; + // the canvas we will draw into + GFXcanvas1 canvas; + // the text area to store the text to print in text mode + char textBuffer[32]; + // the font handler that draws unicode fonts using TcUnicode format + UnicodeFontHandler unicodeHelper; + // the current position in the animation + int currPos = 0; + // the amount of time the loop has been running + int loopTimer = 0; + // the current mode + DiscoMode mode = CIRCLES; +public: + explicit DiscoTime(); + void init(); + + // + // These two are part of TaskManagerIO BaseEvent processing, see TaskManagerIO event handling for docs: + // https://tcmenu.github.io/documentation/arduino-libraries/taskmanager-io/ + // + void exec() override; + uint32_t timeOfNextCheck() override; + + // start the disco on the matrix + void start(int speed); + // draw a picture on the matrix in 12x8 XBMP format + void picture(const uint8_t* xbmpData); + // draw text on the matrix + void text(const char* data); + // stop the animation + void stop(); + + // These two send non-standard custom messages over the wire, this shows how easy it is to define your own. + // https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-iot/embed-control-tagval-wire-protocol/ + void sendDiscoMsg(); + void sendXbmpData(const uint8_t* xbmpData, size_t length); + + // these are the animation methods + void runSquares(); + void drawText(); + void runStrobe(); + + // and lastly we convert the canvas to LED output with this + void drawCanvasToLeds(); + + void runCircles(); + + void switchMode(DiscoMode mode); +}; + + +#endif //TCLIBRARYDEV_DISCOTIME_H diff --git a/examples/arduino32/colorTftEthernet32/EthernetTransport.cpp b/examples/arduino32/r4UnoButtonsTft/EthernetTransport.cpp similarity index 100% rename from examples/arduino32/colorTftEthernet32/EthernetTransport.cpp rename to examples/arduino32/r4UnoButtonsTft/EthernetTransport.cpp diff --git a/examples/arduino32/colorTftEthernet32/EthernetTransport.h b/examples/arduino32/r4UnoButtonsTft/EthernetTransport.h similarity index 87% rename from examples/arduino32/colorTftEthernet32/EthernetTransport.h rename to examples/arduino32/r4UnoButtonsTft/EthernetTransport.h index 291b438c..b70c6929 100644 --- a/examples/arduino32/colorTftEthernet32/EthernetTransport.h +++ b/examples/arduino32/r4UnoButtonsTft/EthernetTransport.h @@ -16,12 +16,12 @@ #include #include -#include +#include #include #include #ifndef ETHERNET_BUFFER_SIZE -#define ETHERNET_BUFFER_SIZE 64 +#define ETHERNET_BUFFER_SIZE 96 #endif #if ETHERNET_BUFFER_SIZE > 0 @@ -37,11 +37,11 @@ namespace tcremote { */ class EthernetTagValTransport : public tcremote::BaseBufferedRemoteTransport { private: - EthernetClient client; + WiFiClient client; public: - EthernetTagValTransport() : BaseBufferedRemoteTransport(BUFFER_MESSAGES_TILL_FULL, ETHERNET_BUFFER_SIZE, MAX_VALUE_LEN) { } + EthernetTagValTransport() : BaseBufferedRemoteTransport(BUFFER_ONE_MESSAGE, ETHERNET_BUFFER_SIZE, MAX_VALUE_LEN) { } ~EthernetTagValTransport() override = default; - void setClient(EthernetClient cl) { this->client = cl; } + void setClient(WiFiClient cl) { this->client = cl; } int fillReadBuffer(uint8_t* data, int maxSize) override; void flush() override; @@ -57,11 +57,11 @@ namespace tcremote { */ class EthernetTagValTransport : public TagValueTransport { private: - EthernetClient client; + WiFiClient client; public: EthernetTagValTransport() : TagValueTransport(TagValueTransportType::TVAL_UNBUFFERED) {}; ~EthernetTagValTransport() override = default; - void setClient(EthernetClient client) { this->client = client; } + void setClient(WiFiClient client) { this->client = client; } int writeChar(char data) override ; int writeStr(const char* data) override; @@ -80,9 +80,9 @@ class EthernetTagValTransport : public TagValueTransport { */ class EthernetInitialisation : public DeviceInitialisation { private: - EthernetServer *server; + WiFiServer *server; public: - explicit EthernetInitialisation(EthernetServer* server) : server(server) {} + explicit EthernetInitialisation(WiFiServer* server) : server(server) {} bool attemptInitialisation() override; diff --git a/examples/arduino32/r4UnoButtonsTft/ThemeCoolBlueTraditionalBuilder.h b/examples/arduino32/r4UnoButtonsTft/ThemeCoolBlueTraditionalBuilder.h new file mode 100644 index 00000000..8553b9ed --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/ThemeCoolBlueTraditionalBuilder.h @@ -0,0 +1,79 @@ +/** + * Cool blue traditional theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. + * This file will not be updated by the designer, you can edit. + * See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/themes/rendering-with-themes-icons-grids/ + */ + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE + +#include + +// +// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() +// + +// tcMenu drawing properties take a 4 color palette for items, titles and actions. +// this renderer shares the color configuration for items and actions. +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + * @param titleMode the way that the title should be drawn (choose from the enum values) + * @param useUnicode if using tcUnicode drawing functions + */ +void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + bool medResOrBetter = gr.getWidth() > 160; + MenuPadding titlePadding(medResOrBetter ? 4 : 2); + MenuPadding itemPadding(medResOrBetter ? 2 : 1); + + themeBuilder.dimensionsFromRenderer() + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) + .withItemPadding(itemPadding) + .withTitlePadding(titlePadding) + .withRenderingSettings(titleMode, false) + .withPalette(coolBlueItemPalette) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + if(medResOrBetter) { + themeBuilder.withStandardMedResCursorIcons(); + } else { + themeBuilder.withStandardLowResCursorIcons(); + } + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultItemProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.defaultTitleProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(coolBlueTitlePalette) + .withSpacing(medResOrBetter ? 3 : 1) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //THEME_COOL_BLUE diff --git a/examples/arduino32/colorTftEthernet32/colorTftEthernet.emf b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft.emf similarity index 51% rename from examples/arduino32/colorTftEthernet32/colorTftEthernet.emf rename to examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft.emf index bb88d42b..cd125596 100644 --- a/examples/arduino32/colorTftEthernet32/colorTftEthernet.emf +++ b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft.emf @@ -1,23 +1,17 @@ { "version": "1.00", - "projectName": "C:\\Users\\dave\\Documents\\Arduino\\tcLibraryDev\\lib\\tcMenu\\examples\\colorTftEthernet32\\colorTftEthernet.emf", + "projectName": "Project description", "author": "dave", "items": [ { "parentId": 0, - "type": "analogItem", - "defaultValue": "0", + "type": "subMenu", "item": { - "maxValue": 255, - "offset": -128, - "divisor": 2, - "unitName": "V", - "step": 1, - "name": "Voltage", - "variableName": "", + "secured": false, + "name": "Disco", + "variableName": "Disco", "id": 1, - "eepromAddress": 2, - "functionName": "onVoltageChange", + "eepromAddress": -1, "readOnly": false, "localOnly": false, "visible": true, @@ -25,20 +19,19 @@ } }, { - "parentId": 0, + "parentId": 1, "type": "analogItem", - "defaultValue": "0", + "defaultValue": "2", "item": { - "maxValue": 255, + "maxValue": 10, "offset": 0, - "divisor": 100, - "unitName": "A", + "divisor": 1, + "unitName": "", "step": 1, - "name": "Current", - "variableName": "", + "name": "Speed", + "variableName": "DiscoSpeed", "id": 2, - "eepromAddress": 4, - "functionName": "onCurrentChange", + "eepromAddress": -1, "readOnly": false, "localOnly": false, "visible": true, @@ -46,19 +39,14 @@ } }, { - "parentId": 0, - "type": "enumItem", - "defaultValue": "0", + "parentId": 1, + "type": "actionMenu", "item": { - "enumEntries": [ - "Current", - "Voltage" - ], - "name": "Limit", - "variableName": "", - "id": 3, - "eepromAddress": 6, - "functionName": "onLimitMode", + "name": "Start Disco", + "variableName": "ZoomTextStartZoom", + "id": 10, + "eepromAddress": -1, + "functionName": "onStartDisco", "readOnly": false, "localOnly": false, "visible": true, @@ -70,8 +58,8 @@ "type": "subMenu", "item": { "secured": false, - "name": "Settings", - "variableName": "", + "name": "Scroll Text", + "variableName": "ScrollText", "id": 4, "eepromAddress": -1, "readOnly": false, @@ -82,13 +70,14 @@ }, { "parentId": 4, - "type": "boolItem", - "defaultValue": "false", + "type": "textItem", + "defaultValue": "TcMenu", "item": { - "naming": "YES_NO", - "name": "Pwr Delay", - "variableName": "", - "id": 5, + "textLength": 16, + "itemType": "PLAIN_TEXT", + "name": "Text", + "variableName": "ScrollTextText", + "id": 6, "eepromAddress": -1, "readOnly": false, "localOnly": false, @@ -100,106 +89,11 @@ "parentId": 4, "type": "actionMenu", "item": { - "name": "Save all", - "variableName": "", - "id": 10, - "eepromAddress": -1, - "functionName": "onSaveRom", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "subMenu", - "item": { - "secured": false, - "name": "Advanced", - "variableName": "", - "id": 11, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 11, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "ON_OFF", - "name": "S-Circuit Protect", - "variableName": "", - "id": 12, - "eepromAddress": 8, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 11, - "type": "actionMenu", - "item": { - "name": "Hidden item", - "variableName": "", - "id": 16, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 11, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "ON_OFF", - "name": "Temp Check", - "variableName": "", - "id": 13, - "eepromAddress": 9, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 11, - "type": "rgbItem", - "defaultValue": "#000000FF", - "item": { - "includeAlphaChannel": false, - "name": "RGB", - "variableName": "", - "id": 26, - "eepromAddress": 16, - "functionName": "onRgbChanged", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 11, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "YES_NO", - "name": "Show Hidden", - "variableName": "ShowHidden", - "id": 30, + "name": "Start Scroll", + "variableName": "ScrollTextStartScroll", + "id": 9, "eepromAddress": -1, - "functionName": "onShowHidden", + "functionName": "onStartScroll", "readOnly": false, "localOnly": false, "visible": true, @@ -211,8 +105,8 @@ "type": "subMenu", "item": { "secured": false, - "name": "Status", - "variableName": "", + "name": "Show Xbmp", + "variableName": "ShowXbmp", "id": 7, "eepromAddress": -1, "readOnly": false, @@ -223,12 +117,15 @@ }, { "parentId": 7, - "type": "floatItem", - "defaultValue": "0.0", + "type": "scrollItem", + "defaultValue": "0-No entries", "item": { - "numDecimalPlaces": 2, - "name": "Volt A0", - "variableName": "", + "itemWidth": 0, + "eepromOffset": 0, + "numEntries": 0, + "choiceMode": "CUSTOM_RENDERFN", + "name": "Xbmp", + "variableName": "ShowXbmpXbmp", "id": 8, "eepromAddress": -1, "readOnly": false, @@ -239,14 +136,13 @@ }, { "parentId": 7, - "type": "floatItem", - "defaultValue": "0.0", + "type": "actionMenu", "item": { - "numDecimalPlaces": 2, - "name": "Volt A1", - "variableName": "", - "id": 9, + "name": "Show Image", + "variableName": "ShowXbmpShowImage", + "id": 11, "eepromAddress": -1, + "functionName": "onShowXbmp", "readOnly": false, "localOnly": false, "visible": true, @@ -258,9 +154,9 @@ "type": "subMenu", "item": { "secured": false, - "name": "Connectivity", - "variableName": "", - "id": 14, + "name": "Analog", + "variableName": "Analog", + "id": 12, "eepromAddress": -1, "readOnly": false, "localOnly": false, @@ -269,44 +165,35 @@ } }, { - "parentId": 14, - "type": "textItem", - "defaultValue": "", - "item": { - "textLength": 20, - "itemType": "IP_ADDRESS", - "name": "Ip Address", - "variableName": "", - "id": 15, - "eepromAddress": 10, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 14, - "type": "customBuildItem", + "parentId": 12, + "type": "analogItem", + "defaultValue": "0", "item": { - "menuType": "AUTHENTICATION", - "name": "Authenticator", - "variableName": "Authenticator", - "id": 28, + "maxValue": 100, + "offset": 0, + "divisor": 1, + "unitName": "%", + "step": 1, + "name": "A0 DAC", + "variableName": "AnalogA0DAC", + "id": 13, "eepromAddress": -1, + "functionName": "onAnalogDacChange", "readOnly": false, - "localOnly": true, + "localOnly": false, "visible": true, "staticDataInRAM": false } }, { - "parentId": 14, - "type": "customBuildItem", + "parentId": 12, + "type": "floatItem", + "defaultValue": "0.0", "item": { - "menuType": "REMOTE_IOT_MONITOR", - "name": "IoT Monitor", - "id": 29, + "numDecimalPlaces": 3, + "name": "A1 Value", + "variableName": "AnalogA1Value", + "id": 14, "eepromAddress": -1, "readOnly": false, "localOnly": false, @@ -319,50 +206,10 @@ "type": "subMenu", "item": { "secured": false, - "name": "Rom Values", - "variableName": "", - "id": 20, - "eepromAddress": -1, - "functionName": "", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 20, - "type": "scrollItem", - "defaultValue": "0-", - "item": { - "itemWidth": 10, - "eepromOffset": 1024, - "numEntries": 10, - "choiceMode": "ARRAY_IN_EEPROM", - "name": "Rom Choice", - "variableName": "", - "id": 25, - "eepromAddress": 14, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 20, - "type": "scrollItem", - "defaultValue": "0-", - "item": { - "itemWidth": 10, - "eepromOffset": 0, - "numEntries": 10, - "choiceMode": "CUSTOM_RENDERFN", - "name": "Rom Location", - "variableName": "", - "id": 24, + "name": "WiFi", + "variableName": "WiFi", + "id": 15, "eepromAddress": -1, - "functionName": "", "readOnly": false, "localOnly": false, "visible": true, @@ -370,31 +217,16 @@ } }, { - "parentId": 20, + "parentId": 15, "type": "textItem", "defaultValue": "", "item": { - "textLength": 10, - "itemType": "PLAIN_TEXT", - "name": "Rom Text", - "variableName": "", - "id": 21, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 20, - "type": "actionMenu", - "item": { - "name": "Save item", - "variableName": "", - "id": 23, + "textLength": 5, + "itemType": "IP_ADDRESS", + "name": "IP Address", + "variableName": "WiFiIPAddress", + "id": 16, "eepromAddress": -1, - "functionName": "onSaveItem", "readOnly": false, "localOnly": false, "visible": true, @@ -402,14 +234,15 @@ } }, { - "parentId": 0, - "type": "actionMenu", + "parentId": 15, + "type": "boolItem", + "defaultValue": "false", "item": { - "name": "Take display", - "variableName": "", + "naming": "YES_NO", + "name": "Connected", + "variableName": "WiFiConnected", "id": 17, "eepromAddress": -1, - "functionName": "onTakeDisplay", "readOnly": false, "localOnly": false, "visible": true, @@ -420,13 +253,13 @@ "codeOptions": { "embeddedPlatform": "ARDUINO32", "lastDisplayUuid": "4dcb12ec-13d8-4466-b8b6-bd575eae4612", - "lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87", + "lastInputUuid": "2a3ae3ba-05f4-4c9c-aad3-3ddc88df9049", "lastRemoteUuids": [ - "0877131c-e03e-426b-8eaf-228e01f5e7f1" + "46c30011-cac6-4598-a7b8-b0630d55daab" ], - "lastThemeUuid": "03c6b25f-db63-402a-8447-a5ce1484c14d", - "applicationUUID": "22813e5e-88b1-42d5-9601-4831b2be369b", - "applicationName": "Ada32 Ethernet", + "lastThemeUuid": "57945787-0A04-447B-BBA2-6461FC505397", + "applicationUUID": "4f60a98f-ca51-4c80-acbd-78bfd1e90c8d", + "applicationName": "R4 Disco", "lastProperties": [ { "name": "DISPLAY_VARIABLE", @@ -440,7 +273,7 @@ }, { "name": "DISPLAY_WIDTH", - "latestValue": "160", + "latestValue": "128", "subsystem": "DISPLAY" }, { @@ -450,17 +283,17 @@ }, { "name": "DISPLAY_RESET_PIN", - "latestValue": "3", + "latestValue": "12", "subsystem": "DISPLAY" }, { "name": "DISPLAY_CS_PIN", - "latestValue": "6", + "latestValue": "10", "subsystem": "DISPLAY" }, { "name": "DISPLAY_RS_PIN", - "latestValue": "7", + "latestValue": "9", "subsystem": "DISPLAY" }, { @@ -480,7 +313,7 @@ }, { "name": "DISPLAY_ROTATION", - "latestValue": "1", + "latestValue": "3", "subsystem": "DISPLAY" }, { @@ -490,106 +323,96 @@ }, { "name": "DISPLAY_BUFFER_SIZE", - "latestValue": "0", + "latestValue": "40", "subsystem": "DISPLAY" }, { "name": "SW_POLLING_MODE", - "latestValue": "SWITCHES_POLL_KEYS_ONLY", + "latestValue": "SWITCHES_POLL_EVERYTHING", "subsystem": "INPUT" }, { "name": "SWITCH_IODEVICE", - "latestValue": "io8574", + "latestValue": "devicePins", "subsystem": "INPUT" }, { - "name": "ENCODER_PIN_A", - "latestValue": "7", + "name": "ENCODER_UP_PIN", + "latestValue": "5", "subsystem": "INPUT" }, { - "name": "ENCODER_PIN_B", - "latestValue": "6", + "name": "ENCODER_DOWN_PIN", + "latestValue": "4", "subsystem": "INPUT" }, { - "name": "ENCODER_PIN_OK", - "latestValue": "5", + "name": "ENCODER_BACK_PIN", + "latestValue": "6", "subsystem": "INPUT" }, { - "name": "ENCODER_BACK_PIN", - "latestValue": "-1", + "name": "ENCODER_NEXT_PIN", + "latestValue": "7", "subsystem": "INPUT" }, { - "name": "ENCODER_NEXT_PIN", + "name": "ENCODER_OK_PIN", "latestValue": "-1", "subsystem": "INPUT" }, { - "name": "PULLUP_LOGIC", - "latestValue": "true", + "name": "ENC_KEY_REPEAT", + "latestValue": "20", "subsystem": "INPUT" }, { - "name": "ENCODER_IS_QUARTER_CYCLE", - "latestValue": "false", + "name": "PULLUP_LOGIC", + "latestValue": "true", "subsystem": "INPUT" }, { - "name": "ETH_CONCURRENT_CONNECTIONS", + "name": "ESPWIFI_CONCURRENT_CONNECTIONS", "latestValue": "1", "subsystem": "REMOTE" }, { - "name": "ETH_LIBRARY_TYPE", - "latestValue": "ETHERNET_2", - "subsystem": "REMOTE" - }, - { - "name": "ETH_LISTEN_PORT1", + "name": "ESPWIFI_LISTEN_PORT1", "latestValue": "3333", "subsystem": "REMOTE" }, { - "name": "ETH_LISTEN_PORT2", + "name": "ESPWIFI_LISTEN_PORT2", "latestValue": "3334", "subsystem": "REMOTE" }, { - "name": "ETH_LISTEN_PORT3", + "name": "ESPWIFI_LISTEN_PORT3", "latestValue": "3335", "subsystem": "REMOTE" }, { - "name": "ITEM_FONT", - "latestValue": "def:,1", - "subsystem": "THEME" + "name": "ESPWIFI_BUFFERED", + "latestValue": "true", + "subsystem": "REMOTE" }, { - "name": "TITLE_FONT", - "latestValue": "ada:FreeSansBold9pt7b,1", + "name": "ITEM_FONT", + "latestValue": "ada:OpenSansRegular12pt,0", "subsystem": "THEME" }, { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", + "name": "TITLE_FONT", + "latestValue": "ada:OpenSansCyrillicLatin14,0", "subsystem": "THEME" }, { "name": "TITLE_SHOW_MODE", - "latestValue": "TITLE_ALWAYS", + "latestValue": "TITLE_FIRST_ROW", "subsystem": "THEME" }, { "name": "USE_TC_UNICODE", - "latestValue": "false", - "subsystem": "THEME" - }, - { - "name": "USE_SLIDER_ANALOG", "latestValue": "true", "subsystem": "THEME" }, @@ -599,14 +422,13 @@ "subsystem": "THEME" } ], - "namingRecursive": false, + "namingRecursive": true, "useCppMain": false, "saveLocation": "ALL_TO_CURRENT", - "usingSizedEEPROMStorage": false, - "eepromDefinition": "at24:80:PAGESIZE_AT24C128", - "authenticatorDefinition": "rom:100:6", + "usingSizedEEPROMStorage": true, + "eepromDefinition": "", + "authenticatorDefinition": "", "projectIoExpanders": [ - "pcf8574:io8574:32:0:false", "deviceIO:" ], "menuInMenuCollection": { @@ -614,5 +436,6 @@ }, "packageNamespace": "", "appIsModular": false - } + }, + "stringLists": [] } \ No newline at end of file diff --git a/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft.ino b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft.ino new file mode 100644 index 00000000..41f44108 --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft.ino @@ -0,0 +1,137 @@ +/** + * An example sketch for the Arduino Uno R4 Wifi board that includes support for a TFT screen and keypad input. It + * also has remote connectivity in the form of the inbuilt Wi-Fi module. The sketch controls the LED Matrix on the R4 + * WiFi version somewhat akin to a disco. + * + * The "disco" functionality is in DiscoTime.h/cpp to keep this file cleaner. + * + * For the example I connected the TFT as follows: + * SCLK - 13, COPI - 12, CS - 10, RST - 12, RS/DC - 9 + * and for the keypad + * UP - 5, DOWN - 4, LEFT - 6, RIGHT - 7 + */ +#include "r4UnoButtonsTft_menu.h" +#include "xbmpImages.h" +#include "IoAbstraction.h" +#include +#include +#include +#include +#include "DiscoTime.h" + +bool wifiFailed = false; + +TitleWidget wifiWidget(iconsWifi, 5, 16, 12); +TitleWidget connectedWidget(iconsConnection, 2, 16, 12); + +DiscoTime discoTime; + +// At the moment the Wi-Fi on this board has an issue with TagVal. +// We do not recommend using the Wi-Fi yet. +#define R4_START_WIFI false + +void tryAndStartWifi() { +#if (R4_START_WIFI == true) + serlogF(SER_DEBUG, "Attempt WiFi begin"); + int started = WiFi.begin("yourssid", "yourpwd"); + if(started == WL_CONNECTED) { + serlogF(SER_DEBUG, "WiFi Up"); + menuWiFiConnected.setBoolean(true); + auto ip = WiFi.localIP(); + menuWiFiIPAddress.setIpAddress(ip[0], ip[1], ip[2], ip[3]); + } else { + serlogF2(SER_ERROR, "Retrying in 2 seconds", started); + taskManager.schedule(onceSeconds(2), tryAndStartWifi); + } +#endif +} + +void setup() { + Serial.begin(115200); + + internalAnalogDevice().initPin(DAC, DIR_OUT); + internalAnalogDevice().initPin(A1, DIR_IN); + internalAnalogDevice().setCurrentValue(DAC, 0); + + setupMenu(); + + menuShowXbmpXbmp.setNumberOfRows(2); + + taskManager.schedule(repeatMillis(1500), [] { + menuAnalogA1Value.setFloatValue(internalAnalogDevice().getCurrentFloat(A1) * analogReference()); + if(!wifiFailed) { + wifiWidget.setCurrentState(fromWiFiRSSITo4StateIndicator(WiFi.RSSI())); + } + }); + + if (WiFi.status() == WL_NO_MODULE) { + serlogF(SER_ERROR, "WiFi module failure"); + wifiFailed = true; + wifiWidget.setCurrentState(0); + menuWiFiConnected.setBoolean(false); + } + + if(!wifiFailed) { + String fv = WiFi.firmwareVersion(); + if (fv < WIFI_FIRMWARE_LATEST_VERSION) { + serlogF(SER_WARNING, "Please upgrade the firmware"); + } + taskManager.schedule(onceMillis(100), tryAndStartWifi); + } + + // The easiest way to adjust drawing parameters is using theme builder. Here we are going to add two title widgets + // to the display, these appear top right. We use the stock provided icons. + // See https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(renderer); + themeBuilder.addingTitleWidget(wifiWidget) + .addingTitleWidget(connectedWidget) + .apply(); + + setTitlePressedCallback([](int) { + showVersionDialog(&applicationInfo); + }); + + discoTime.init(); +} + +void loop() { + taskManager.runLoop(); +} + +// In this case we show the image descriptions for the Xbitmap menu. We only need override the value callback. For each +// time the scroll choice needs the value for an index, it calls back here. +// +// This callback needs to be implemented by you, see the below docs: +// 1. List Docs - https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/list-menu-item/ +// 2. ScrollChoice Docs - https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/ +int CALLBACK_FUNCTION fnShowXbmpXbmpRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize) { + switch(mode) { + case RENDERFN_VALUE: + strncpy(buffer, imageWithDescription[row].getName(), bufferSize); + return true; + default: + return defaultRtListCallback(item, row, mode, buffer, bufferSize); + } +} + +void CALLBACK_FUNCTION onAnalogDacChange(int id) { + internalAnalogDevice().setCurrentFloat(DAC, menuAnalogA0DAC.getCurrentValue() / 100.0F); +} + +void CALLBACK_FUNCTION onShowXbmp(int id) { + GFXcanvas1 canvas(12, 8); + auto imgIdx = menuShowXbmpXbmp.getCurrentValue(); + if(imgIdx < 0 || imgIdx >= NUMBER_OF_XBMPS) return; + + discoTime.picture(imageWithDescription[imgIdx].getData()); +} + +void CALLBACK_FUNCTION onStartDisco(int id) { + discoTime.start(menuDiscoSpeed.getCurrentValue() * 20); +} + +void CALLBACK_FUNCTION onStartScroll(int id) { + char sz[20]; + menuScrollTextText.copyValue(sz, sizeof sz); + discoTime.text(sz); +} diff --git a/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft_menu.cpp b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft_menu.cpp new file mode 100644 index 00000000..3b8ee010 --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft_menu.cpp @@ -0,0 +1,80 @@ +/* + The code in this file uses open source libraries provided by thecoderscorner + + DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER + INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. + + All the variables you may need access to are marked extern in this file for easy + use elsewhere. + */ + +// Generated for Arduino 32bit ARM by TcMenu 4.3.1 on 2024-10-05T10:48:44.197140800Z. + +#include +#include "r4UnoButtonsTft_menu.h" +#include "ThemeCoolBlueTraditionalBuilder.h" +#include +#include + +// Global variable declarations +const ConnectorLocalInfo applicationInfo = { "R4 Disco", "4f60a98f-ca51-4c80-acbd-78bfd1e90c8d" }; +TcMenuRemoteServer remoteServer(applicationInfo); + +Adafruit_ST7735 gfx(10, 9, 12); +AdafruitDrawable gfxDrawable(&gfx, 40); +GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); +WiFiServer server(3333); +EthernetInitialisation ethernetInitialisation(&server); +EthernetTagValTransport ethernetTransport; +TagValueRemoteServerConnection ethernetConnection(ethernetTransport, ethernetInitialisation); + +// Global Menu Item declarations +const BooleanMenuInfo minfoWiFiConnected = { "Connected", 17, 0xffff, 1, NO_CALLBACK, NAMING_YES_NO }; +BooleanMenuItem menuWiFiConnected(&minfoWiFiConnected, false, nullptr, INFO_LOCATION_PGM); +const AnyMenuInfo minfoWiFiIPAddress = { "IP Address", 16, 0xffff, 0, NO_CALLBACK }; +IpAddressMenuItem menuWiFiIPAddress(&minfoWiFiIPAddress, IpAddressStorage(127, 0, 0, 1), &menuWiFiConnected, INFO_LOCATION_PGM); +const SubMenuInfo minfoWiFi = { "WiFi", 15, 0xffff, 0, NO_CALLBACK }; +BackMenuItem menuBackWiFi(&minfoWiFi, &menuWiFiIPAddress, INFO_LOCATION_PGM); +SubMenuItem menuWiFi(&minfoWiFi, &menuBackWiFi, nullptr, INFO_LOCATION_PGM); +const FloatMenuInfo minfoAnalogA1Value = { "A1 Value", 14, 0xffff, 3, NO_CALLBACK }; +FloatMenuItem menuAnalogA1Value(&minfoAnalogA1Value, 0.0, nullptr, INFO_LOCATION_PGM); +const AnalogMenuInfo minfoAnalogA0DAC = { "A0 DAC", 13, 0xffff, 100, onAnalogDacChange, 0, 1, "%" }; +AnalogMenuItem menuAnalogA0DAC(&minfoAnalogA0DAC, 0, &menuAnalogA1Value, INFO_LOCATION_PGM); +const SubMenuInfo minfoAnalog = { "Analog", 12, 0xffff, 0, NO_CALLBACK }; +BackMenuItem menuBackAnalog(&minfoAnalog, &menuAnalogA0DAC, INFO_LOCATION_PGM); +SubMenuItem menuAnalog(&minfoAnalog, &menuBackAnalog, &menuWiFi, INFO_LOCATION_PGM); +const AnyMenuInfo minfoShowXbmpShowImage = { "Show Image", 11, 0xffff, 0, onShowXbmp }; +ActionMenuItem menuShowXbmpShowImage(&minfoShowXbmpShowImage, nullptr, INFO_LOCATION_PGM); +const AnyMenuInfo minfoShowXbmpXbmp = { "Xbmp", 8, 0xffff, 0, NO_CALLBACK }; +ScrollChoiceMenuItem menuShowXbmpXbmp(&minfoShowXbmpXbmp, fnShowXbmpXbmpRtCall, 0, 0, &menuShowXbmpShowImage, INFO_LOCATION_PGM); +const SubMenuInfo minfoShowXbmp = { "Show Xbmp", 7, 0xffff, 0, NO_CALLBACK }; +BackMenuItem menuBackShowXbmp(&minfoShowXbmp, &menuShowXbmpXbmp, INFO_LOCATION_PGM); +SubMenuItem menuShowXbmp(&minfoShowXbmp, &menuBackShowXbmp, &menuAnalog, INFO_LOCATION_PGM); +const AnyMenuInfo minfoScrollTextStartScroll = { "Start Scroll", 9, 0xffff, 0, onStartScroll }; +ActionMenuItem menuScrollTextStartScroll(&minfoScrollTextStartScroll, nullptr, INFO_LOCATION_PGM); +const AnyMenuInfo minfoScrollTextText = { "Text", 6, 0xffff, 0, NO_CALLBACK }; +TextMenuItem menuScrollTextText(&minfoScrollTextText, "TcMenu", 16, &menuScrollTextStartScroll, INFO_LOCATION_PGM); +const SubMenuInfo minfoScrollText = { "Scroll Text", 4, 0xffff, 0, NO_CALLBACK }; +BackMenuItem menuBackScrollText(&minfoScrollText, &menuScrollTextText, INFO_LOCATION_PGM); +SubMenuItem menuScrollText(&minfoScrollText, &menuBackScrollText, &menuShowXbmp, INFO_LOCATION_PGM); +const AnyMenuInfo minfoZoomTextStartZoom = { "Start Disco", 10, 0xffff, 0, onStartDisco }; +ActionMenuItem menuZoomTextStartZoom(&minfoZoomTextStartZoom, nullptr, INFO_LOCATION_PGM); +const AnalogMenuInfo minfoDiscoSpeed = { "Speed", 2, 0xffff, 10, NO_CALLBACK, 0, 1, "" }; +AnalogMenuItem menuDiscoSpeed(&minfoDiscoSpeed, 2, &menuZoomTextStartZoom, INFO_LOCATION_PGM); +const SubMenuInfo minfoDisco = { "Disco", 1, 0xffff, 0, NO_CALLBACK }; +BackMenuItem menuBackDisco(&minfoDisco, &menuDiscoSpeed, INFO_LOCATION_PGM); +SubMenuItem menuDisco(&minfoDisco, &menuBackDisco, &menuScrollText, INFO_LOCATION_PGM); + +void setupMenu() { + // First we set up eeprom and authentication (if needed). + setSizeBasedEEPROMStorageEnabled(true); + // Code generated by plugins and new operators. + gfx.initR(INITR_BLACKTAB); + gfx.setRotation(3); + renderer.setUpdatesPerSecond(5); + switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); + menuMgr.initFor4WayJoystick(&renderer, &menuDisco, 4, 5, 6, 7, -1, 20); + remoteServer.addConnection(ðernetConnection); + installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansRegular12pt, 0), MenuFontDef(&OpenSansCyrillicLatin14, 0), true, BaseGraphicalRenderer::TITLE_FIRST_ROW, true); +} + diff --git a/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft_menu.h b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft_menu.h new file mode 100644 index 00000000..872b05d9 --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/r4UnoButtonsTft_menu.h @@ -0,0 +1,74 @@ +/* + The code in this file uses open source libraries provided by thecoderscorner + + DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER + INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. + + All the variables you may need access to are marked extern in this file for easy + use elsewhere. + */ + +#ifndef MENU_GENERATED_CODE_H +#define MENU_GENERATED_CODE_H + +#include +#include +#include +#include "tcMenuAdaFruitGfx.h" +#include "EthernetTransport.h" +#include +#include +#include +#include +#include + +// variables we declare that you may need to access +extern const PROGMEM ConnectorLocalInfo applicationInfo; +extern TcMenuRemoteServer remoteServer; +extern Adafruit_ST7735 gfx; +extern AdafruitDrawable gfxDrawable; +extern GraphicsDeviceRenderer renderer; +extern WiFiServer server; +extern EthernetInitialisation ethernetInitialisation; +extern const UnicodeFont OpenSansRegular12pt[]; +extern const UnicodeFont OpenSansCyrillicLatin14[]; + +// Any externals needed by IO expanders, EEPROMs etc + + +// Global Menu Item exports +extern BooleanMenuItem menuWiFiConnected; +extern IpAddressMenuItem menuWiFiIPAddress; +extern BackMenuItem menuBackWiFi; +extern SubMenuItem menuWiFi; +extern FloatMenuItem menuAnalogA1Value; +extern AnalogMenuItem menuAnalogA0DAC; +extern BackMenuItem menuBackAnalog; +extern SubMenuItem menuAnalog; +extern ActionMenuItem menuShowXbmpShowImage; +extern ScrollChoiceMenuItem menuShowXbmpXbmp; +extern BackMenuItem menuBackShowXbmp; +extern SubMenuItem menuShowXbmp; +extern ActionMenuItem menuScrollTextStartScroll; +extern TextMenuItem menuScrollTextText; +extern BackMenuItem menuBackScrollText; +extern SubMenuItem menuScrollText; +extern ActionMenuItem menuZoomTextStartZoom; +extern AnalogMenuItem menuDiscoSpeed; +extern BackMenuItem menuBackDisco; +extern SubMenuItem menuDisco; + +// Provide a wrapper to get hold of the root menu item and export setupMenu +inline MenuItem& rootMenuItem() { return menuDisco; } +void setupMenu(); + +// Callback functions must always include CALLBACK_FUNCTION after the return type +#define CALLBACK_FUNCTION + +int fnShowXbmpXbmpRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize); +void CALLBACK_FUNCTION onAnalogDacChange(int id); +void CALLBACK_FUNCTION onShowXbmp(int id); +void CALLBACK_FUNCTION onStartDisco(int id); +void CALLBACK_FUNCTION onStartScroll(int id); + +#endif // MENU_GENERATED_CODE_H diff --git a/examples/avr/adafruitST7735Mega/tcMenuAdaFruitGfx.cpp b/examples/arduino32/r4UnoButtonsTft/tcMenuAdaFruitGfx.cpp similarity index 100% rename from examples/avr/adafruitST7735Mega/tcMenuAdaFruitGfx.cpp rename to examples/arduino32/r4UnoButtonsTft/tcMenuAdaFruitGfx.cpp diff --git a/examples/avr/adafruitST7735Mega/tcMenuAdaFruitGfx.h b/examples/arduino32/r4UnoButtonsTft/tcMenuAdaFruitGfx.h similarity index 100% rename from examples/avr/adafruitST7735Mega/tcMenuAdaFruitGfx.h rename to examples/arduino32/r4UnoButtonsTft/tcMenuAdaFruitGfx.h diff --git a/examples/arduino32/r4UnoButtonsTft/xbmpImages.h b/examples/arduino32/r4UnoButtonsTft/xbmpImages.h new file mode 100644 index 00000000..aef8d95d --- /dev/null +++ b/examples/arduino32/r4UnoButtonsTft/xbmpImages.h @@ -0,0 +1,45 @@ +#ifndef XBMP_IMAGES_H +#define XBMP_IMAGES_H + +// To use palette and size constants we need to use tcgfx types +#include +#include + +using namespace tcgfx; + +// XBM_LSB_FIRST width=12, height=8, size=16 +// auto size = Coord(12, 8); +const uint8_t faceIconXbm12x8[] PROGMEM = { + 0x09,0x09,0x95,0x0a,0x62,0x04,0x0a,0x05,0x02,0x04,0x64,0x02,0x98,0x01,0x04,0x02 +}; + +// XBM_LSB_FIRST width=12, height=8, size=16 +// auto size = Coord(12, 8); +const uint8_t logoIconXbm12x8[] PROGMEM = { + 0x28,0x00,0x28,0x00,0x54,0x0c,0x54,0x02,0xca,0x02,0x4a,0x02,0x45,0x02,0x85,0x0d +}; + +/** + * A really simple value class that represents each of the icons declared above to be stored in a simple array + */ +class XBmpImageWithDescription { +private: + const uint8_t* data; + char name[20]; +public: + XBmpImageWithDescription(const uint8_t* data, const char* n): name{}, data(data) { + strncpy(name, n, sizeof name); + } + + const uint8_t* getData() { return data; } + const char* getName() { return name; } +}; + +XBmpImageWithDescription imageWithDescription[] = { + XBmpImageWithDescription(logoIconXbm12x8, "Tc Logo"), + XBmpImageWithDescription(faceIconXbm12x8, "Face") +}; + +#define NUMBER_OF_XBMPS 2 + +#endif //XBMP_IMAGES_H \ No newline at end of file diff --git a/examples/arduino32/stm32DuinoDemo/RawCustomDrawing.h b/examples/arduino32/stm32DuinoDemo/RawCustomDrawing.h index 166b9cd9..8e319b8d 100644 --- a/examples/arduino32/stm32DuinoDemo/RawCustomDrawing.h +++ b/examples/arduino32/stm32DuinoDemo/RawCustomDrawing.h @@ -20,7 +20,7 @@ class MyCustomDrawing : public CustomDrawing { } void started(BaseMenuRenderer *currentRenderer) override { - // called once when the take-over display is started before calling renderLoop so you can set things up. + // called once when the take-over display is started before calling renderLoop so you can set things up. switches.getEncoder()->changePrecision(100, 50); } @@ -35,7 +35,7 @@ class MyCustomDrawing : public CustomDrawing { } else if(++ticks % 10 == 1) { // Why write your own code using device drawable? The main reason is, that it works exactly the same over - // adafruit, u8g2 and TFTeSPI with a moderately complete API. + // Adafruit, PicoSDK, FrameBuffer, u8g2 and TFTeSPI with a moderately complete API. DeviceDrawable *dd = dev.getDeviceDrawable(); dd->startDraw(); const Coord &dims = dd->getDisplayDimensions(); diff --git a/examples/arduino32/stm32DuinoDemo/ThemeMonoInverse.h b/examples/arduino32/stm32DuinoDemo/ThemeMonoInverse.h deleted file mode 100644 index 02a68d3d..00000000 --- a/examples/arduino32/stm32DuinoDemo/ThemeMonoInverse.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TCMENU_THEME_MONO_INVERSE -#define TCMENU_THEME_MONO_INVERSE - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; -color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; - -#define TITLE_PADDING 1 -#define TITLE_SPACING 0 - -void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 2); - - MenuPadding titlePadding(TITLE_PADDING); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_INVERSE \ No newline at end of file diff --git a/examples/arduino32/stm32DuinoDemo/ThemeMonoInverseBuilder.h b/examples/arduino32/stm32DuinoDemo/ThemeMonoInverseBuilder.h new file mode 100644 index 00000000..1ef2d8a6 --- /dev/null +++ b/examples/arduino32/stm32DuinoDemo/ThemeMonoInverseBuilder.h @@ -0,0 +1,60 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; +color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; + +#define TITLE_PADDING 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoInverseTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 2) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(defaultTitlePaletteMono) + .withPadding(MenuPadding(TITLE_PADDING)) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/arduino32/stm32DuinoDemo/app_icondata.h b/examples/arduino32/stm32DuinoDemo/app_icondata.h index b604343a..6e9c160a 100644 --- a/examples/arduino32/stm32DuinoDemo/app_icondata.h +++ b/examples/arduino32/stm32DuinoDemo/app_icondata.h @@ -82,4 +82,18 @@ static unsigned char muteOnIcon40Bits[] = { 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +// XBM_LSB_FIRST width=32, height=32, size=128 +// auto size = Coord(32, 32); +const uint8_t cardIconBitmap[] PROGMEM = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x0f,0x00,0xc0,0x08,0x10,0x03, + 0x20,0x89,0x91,0x04,0x10,0xc9,0x93,0x08,0x10,0x8a,0x51,0x08,0x08,0x8c,0x31,0x11,0xe4,0x08,0x90,0x23, + 0xe2,0x08,0xd0,0x47,0xe4,0x08,0x10,0x23,0x04,0x08,0x10,0x21,0x08,0x08,0x10,0x10,0x10,0x08,0x10,0x08, + 0x10,0x08,0x10,0x08,0x20,0x08,0x10,0x04,0x40,0x08,0x10,0x02,0x80,0x08,0x10,0x01,0x80,0x08,0x10,0x01, + 0x00,0xf1,0x8f,0x00,0x00,0x02,0x40,0x00,0x00,0x82,0x41,0x00,0x00,0x44,0x22,0x00,0x00,0xfe,0x7f,0x00, + 0x00,0xf3,0xdf,0x00,0x00,0x9d,0xc8,0x00,0x00,0xad,0xd6,0x00,0x00,0xad,0xd6,0x00,0x00,0x93,0xce,0x00, + 0x00,0xfe,0x7f,0x00,0x00,0x00,0x00,0x00 +}; + + + #endif //TCMENU_STM32DUINO_ICONDATA_H diff --git a/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.cpp b/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.cpp index f446595c..ef52cd28 100644 --- a/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.cpp +++ b/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.cpp @@ -8,9 +8,11 @@ use elsewhere. */ +// Generated for STM32Duino by TcMenu 4.3.1 on 2024-09-21T08:48:23.694313500Z. + #include #include "stm32DuinoDemo_menu.h" -#include "../ThemeMonoInverse.h" +#include "../ThemeMonoInverseBuilder.h" // Global variable declarations const ConnectorLocalInfo applicationInfo = { "TcTT PSU", "ecd5607f-55eb-4252-a512-aab769452dd3" }; @@ -95,8 +97,19 @@ AnalogMenuItem menuStatusCurrent(&minfoStatusCurrent, 0, &menuStatusMotor, INFO_ const SubMenuInfo minfoStatus = { "Status", 22, 0xffff, 0, NO_CALLBACK }; BackMenuItem menuBackStatus(&minfoStatus, &menuStatusCurrent, INFO_LOCATION_PGM); SubMenuItem menuStatus(&minfoStatus, &menuBackStatus, &menuSettings, INFO_LOCATION_PGM); +const AnyMenuInfo minfoStatusCardsDmnd = { "Dmnd", 36, 0xffff, 0, NO_CALLBACK }; +ActionMenuItem menuStatusCardsDmnd(&minfoStatusCardsDmnd, nullptr, INFO_LOCATION_PGM); +const AnyMenuInfo minfoStatusCardsHrts = { "Hrts", 35, 0xffff, 0, NO_CALLBACK }; +ActionMenuItem menuStatusCardsHrts(&minfoStatusCardsHrts, &menuStatusCardsDmnd, INFO_LOCATION_PGM); +const AnyMenuInfo minfoStatusCardsClub = { "Club", 34, 0xffff, 0, NO_CALLBACK }; +ActionMenuItem menuStatusCardsClub(&minfoStatusCardsClub, &menuStatusCardsHrts, INFO_LOCATION_PGM); +const AnyMenuInfo minfoStatusCardsAce = { "Ace", 33, 0xffff, 0, NO_CALLBACK }; +ActionMenuItem menuStatusCardsAce(&minfoStatusCardsAce, &menuStatusCardsClub, INFO_LOCATION_PGM); +const SubMenuInfo minfoStatusCards = { "Cards", 32, 0xffff, 0, NO_CALLBACK }; +BackMenuItem menuBackStatusCards(&minfoStatusCards, &menuStatusCardsAce, INFO_LOCATION_PGM); +SubMenuItem menuStatusCards(&minfoStatusCards, &menuBackStatusCards, &menuStatus, INFO_LOCATION_PGM); const AnyMenuInfo minfo78 = { "78", 21, 0xffff, 0, NO_CALLBACK }; -ActionMenuItem menu78(&minfo78, &menuStatus, INFO_LOCATION_PGM); +ActionMenuItem menu78(&minfo78, &menuStatusCards, INFO_LOCATION_PGM); const AnyMenuInfo minfo45 = { "45", 20, 0xffff, 0, NO_CALLBACK }; ActionMenuItem menu45(&minfo45, &menu78, INFO_LOCATION_PGM); const AnyMenuInfo minfo33 = { "33", 19, 0xffff, 0, NO_CALLBACK }; @@ -104,7 +117,6 @@ ActionMenuItem menu33(&minfo33, &menu45, INFO_LOCATION_PGM); void setupMenu() { // First we set up eeprom and authentication (if needed). - CombinedMessageProcessor::setFormTemplatesInFlash(tcMenuAllEmbeddedForms); setSizeBasedEEPROMStorageEnabled(false); glBspRom.initialise(0); menuMgr.setEepromRef(&glBspRom); @@ -121,9 +133,7 @@ void setupMenu() { switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); menuMgr.initForEncoder(&renderer, &menu33, PC8, PC10, PC9); remoteServer.addConnection(ðernetConnection); - renderer.setTitleMode(BaseGraphicalRenderer::NO_TITLE); - renderer.setUseSliderForAnalog(false); - installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(u8g2_font_prospero_bold_nbp_tr, 1), true); + installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(u8g2_font_prospero_bold_nbp_tr, 1), true, BaseGraphicalRenderer::NO_TITLE, false); // We have an IoT monitor, register the server menuRuntimesIoTMonitor.setRemoteServer(remoteServer); @@ -132,47 +142,3 @@ void setupMenu() { menuRuntimesAuthenticator.init(); } -// Embedded form data - -const uint8_t formData_MobileFriendly_d8[] { -0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xd5,0x96,0x5d,0x6f,0x9b,0x30, -0x18,0x85,0xef,0x27,0xed,0x3f,0x58,0x96,0x76,0x97,0x2c,0x40,0x80,0xa4,0x12,0xb4, -0xca,0x12,0xb2,0x46,0x22,0x50,0x05,0x58,0xa5,0xdd,0x20,0x83,0x9d,0x0a,0xc9,0xd8, -0x15,0x98,0xae,0xf9,0xf7,0x33,0x34,0x5a,0xa0,0xd3,0x5a,0x2e,0x2a,0xc1,0x6e,0x90, -0x39,0x58,0xc7,0x8f,0x0f,0xfe,0x78,0xad,0x9b,0xe7,0x9c,0x82,0x27,0x52,0x94,0x19, -0x67,0x36,0x54,0xbf,0x2a,0x10,0x10,0x96,0x72,0x9c,0xb1,0x07,0x1b,0x46,0xe1,0x76, -0xba,0x84,0xa0,0x14,0x88,0x61,0x44,0x39,0x23,0x36,0x64,0x1c,0xde,0x5c,0x7f,0xfe, -0x64,0x39,0x79,0x42,0xf0,0x9a,0x33,0x51,0x70,0x0a,0x12,0x8e,0x0a,0x1c,0x55,0x19, -0xb6,0x21,0x49,0xb1,0x61,0x2a,0x8b,0xe3,0xd4,0x30,0x48,0x32,0xd5,0x35,0x43,0x9b, -0x22,0x43,0x95,0x0f,0x94,0x2c,0xcc,0x2b,0xdd,0xd0,0x30,0x9e,0x43,0x40,0xd1,0x89, -0x57,0xc2,0x43,0xb9,0x74,0xdc,0xf3,0x24,0xa3,0x04,0x6c,0x8b,0x8c,0x30,0x4c,0x4f, -0x50,0xba,0x03,0x60,0xed,0x09,0xab,0xdc,0xa6,0x57,0xd9,0x08,0x1d,0x09,0xa4,0x9c, -0x96,0x36,0xd4,0x20,0x38,0x4a,0x82,0x1d,0x3b,0x72,0x89,0xae,0x28,0x5f,0x20,0x28, -0x48,0x5a,0xc9,0xb9,0x3c,0x49,0x5f,0x51,0x54,0x44,0x0a,0x9c,0x8b,0x9d,0xe4,0x52, -0xe0,0xd9,0xe6,0x6c,0xe4,0x50,0x92,0x13,0x26,0x00,0xa2,0xd9,0x03,0xab,0x5b,0x36, -0x5c,0x3b,0x5e,0xe8,0x1c,0x60,0x6d,0xce,0x8b,0x80,0x48,0xe5,0x3b,0xe5,0x09,0xa2, -0xb5,0xd2,0xcc,0x33,0x3c,0x3d,0x4a,0xdf,0x6f,0x51,0x18,0xfa,0x5e,0xbc,0xf6,0xbd, -0xf0,0xe0,0xbb,0xf2,0x63,0x55,0x0a,0x9e,0x6f,0x0a,0xf4,0xab,0x4e,0x87,0xc9,0x31, -0xb1,0x6c,0xef,0x39,0x96,0x7d,0x83,0x5b,0xff,0x3e,0xf6,0x56,0x7b,0xe7,0x6f,0x52, -0x39,0x66,0x55,0x83,0xa9,0x57,0x10,0x3c,0xf2,0x32,0x13,0xcd,0x0f,0x50,0x26,0x0a, -0x9c,0x8d,0x94,0x54,0x53,0xba,0xa4,0xea,0x78,0x49,0xd5,0x36,0xa9,0x3a,0x78,0xa6, -0xf1,0x8f,0x95,0x1b,0xbd,0xc1,0x6b,0x76,0x71,0x87,0x0e,0xf6,0x3d,0xdc,0x45,0x1b, -0x57,0x1b,0x3c,0xdd,0x7f,0x83,0x2e,0xbb,0xa0,0x7d,0x72,0x75,0x9d,0x6d,0xf8,0x2e, -0xe6,0xad,0x7f,0xd8,0xfd,0x94,0x8c,0x2b,0x37,0x0e,0xdc,0xdd,0xa6,0x99,0xd8,0x47, -0x04,0xab,0xcd,0xdb,0xc0,0xf3,0x89,0xdc,0x63,0x13,0x6d,0xf4,0xd0,0x7a,0x1b,0x5a, -0xff,0x4f,0xa0,0x8d,0x36,0xb4,0xd1,0x1b,0x7a,0xa0,0xf3,0xac,0x73,0x40,0x98,0x23, -0xde,0x71,0x7a,0x17,0x74,0xe8,0x93,0xec,0x8d,0x6b,0xb7,0x73,0x45,0x2c,0xba,0x91, -0x06,0x02,0x89,0x2c,0x0d,0xc9,0x73,0xaf,0x05,0xfb,0x7a,0x88,0xb6,0xad,0x0a,0xaf, -0x03,0x9e,0x13,0x50,0x7b,0x59,0xb3,0x8b,0xef,0xb8,0x77,0x47,0x27,0x9b,0x65,0xaf, -0xe5,0xd6,0x8b,0x37,0xba,0x8b,0x37,0xfe,0xfd,0x47,0x5f,0x47,0xaa,0xd9,0xc5,0xbd, -0x2c,0x3a,0x6b,0x76,0xa9,0x19,0x5f,0xca,0xca,0x96,0xf0,0x52,0x57,0x5a,0xeb,0x33, -0x72,0x39,0x3b,0xbf,0xff,0x41,0x92,0x25,0x70,0x23,0x5a,0xb3,0x76,0xb1,0x2b,0x85, -0xdf,0x3b,0xb6,0x57,0x86,0x35,0x0b,0x00,0x00 -}; -const EmbedControlFlashedForm formData_MobileFriendly { - "Mobile Friendly", - formData_MobileFriendly_d8, - 521 -}; - -const EmbedControlFlashedForm* tcMenuAllEmbeddedForms[] { &formData_MobileFriendly, nullptr }; diff --git a/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.h b/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.h index d0b0fbda..82cb9785 100644 --- a/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.h +++ b/examples/arduino32/stm32DuinoDemo/generated/stm32DuinoDemo_menu.h @@ -68,6 +68,12 @@ extern AnalogMenuItem menuStatusMotor; extern AnalogMenuItem menuStatusCurrent; extern BackMenuItem menuBackStatus; extern SubMenuItem menuStatus; +extern ActionMenuItem menuStatusCardsDmnd; +extern ActionMenuItem menuStatusCardsHrts; +extern ActionMenuItem menuStatusCardsClub; +extern ActionMenuItem menuStatusCardsAce; +extern BackMenuItem menuBackStatusCards; +extern SubMenuItem menuStatusCards; extern ActionMenuItem menu78; extern ActionMenuItem menu45; extern ActionMenuItem menu33; @@ -85,6 +91,4 @@ void CALLBACK_FUNCTION largeNumDidChange(int id); void CALLBACK_FUNCTION onDecimalStepChange(int id); void CALLBACK_FUNCTION saveWasPressed(int id); -extern const EmbedControlFlashedForm* tcMenuAllEmbeddedForms[]; - #endif // MENU_GENERATED_CODE_H diff --git a/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.emf b/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.emf index 0ce168ba..7d9a8cd2 100644 --- a/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.emf +++ b/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.emf @@ -45,6 +45,77 @@ "staticDataInRAM": false } }, + { + "parentId": 0, + "type": "subMenu", + "item": { + "secured": false, + "name": "Cards", + "variableName": "StatusCards", + "id": 32, + "eepromAddress": -1, + "readOnly": false, + "localOnly": false, + "visible": true, + "staticDataInRAM": false + } + }, + { + "parentId": 32, + "type": "actionMenu", + "item": { + "name": "Ace", + "variableName": "StatusCardsAce", + "id": 33, + "eepromAddress": -1, + "readOnly": false, + "localOnly": false, + "visible": true, + "staticDataInRAM": false + } + }, + { + "parentId": 32, + "type": "actionMenu", + "item": { + "name": "Club", + "variableName": "StatusCardsClub", + "id": 34, + "eepromAddress": -1, + "readOnly": false, + "localOnly": false, + "visible": true, + "staticDataInRAM": false + } + }, + { + "parentId": 32, + "type": "actionMenu", + "item": { + "name": "Hrts", + "variableName": "StatusCardsHrts", + "id": 35, + "eepromAddress": -1, + "readOnly": false, + "localOnly": false, + "visible": true, + "staticDataInRAM": false + } + }, + { + "parentId": 32, + "type": "actionMenu", + "item": { + "name": "Dmnd", + "variableName": "StatusCardsDmnd", + "id": 36, + "eepromAddress": -1, + "readOnly": false, + "localOnly": false, + "visible": true, + "staticDataInRAM": false + } + }, { "parentId": 0, "type": "subMenu", @@ -511,7 +582,7 @@ "lastRemoteUuids": [ "0877131c-e03e-426b-8eaf-228e01f5e7f1" ], - "lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0", + "lastThemeUuid": "396ED4DF-AD7B-4951-A848-A9E5838A549B", "applicationUUID": "ecd5607f-55eb-4252-a512-aab769452dd3", "applicationName": "TcTT PSU", "lastProperties": [ @@ -685,9 +756,7 @@ }, "packageNamespace": "", "appIsModular": false, - "listOfEmbeddedForms": [ - "Mobile Friendly" - ] + "listOfEmbeddedForms": [] }, "stringLists": [] } \ No newline at end of file diff --git a/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.ino b/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.ino index c9887c21..8dcdcf2b 100644 --- a/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.ino +++ b/examples/arduino32/stm32DuinoDemo/stm32DuinoDemo.ino @@ -3,6 +3,10 @@ * are available. By default it is setup for an OLED screen and a rotary encoder, although it could be moved to use * many other different display and input technologies. * + * It demonstrates the use of the card menu layout, where items are shown one at a time as you scroll through them, + * configuring some items to use larger than usual fonts, and other items to render as icons. It also has an ethernet + * network remote included too. + * * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ */ @@ -16,6 +20,7 @@ #include "RawCustomDrawing.h" #include "app_icondata.h" #include +#include // We added a RAM based scroll choice item, and this references a fixed width array variable. // This variable is the RAM data for scroll choice item Scroll @@ -29,49 +34,122 @@ const uint8_t myManualIp[] = { 192, 168, 0, 202 }; const uint8_t myManualMac[] = { 0xde, 0xed, 0xbe, 0xef, 0xfe, 0xed }; const uint8_t standardNetMask[] = { 255, 255, 255, 0 }; - -// here we provide two title widgets, for ethernet connection, and client connection -TitleWidget widgetConnection(iconsConnection, 2, 16, 12, nullptr); -TitleWidget widgetEthernet(iconsEthernetConnection, 2, 16, 12, &widgetConnection); - - // -// We use a card layout to present the items, here we demonstrate how to set it up and prepare custom menu items that -// have different layouts and fonts. +// We use a card layout to present the items, card layout means that only one item will be displayed at once on the +// display with a left and right icon on the edges showing in which direction you can move between items. Below is a +// somewhat rough ASCII-art example of how it may look on the display. +// +// / __ \ the left and right icons show when you can move in each direction +// | | | | one item (whatever is actively selected) is drawn in the middle +// \ -- / it is recommended that the title be disabled during card-layout menus +// +// This demonstrates how to set up card layout for both the root menu and also an additional sub menu, preparing +// custom drawing using icons or larger fonts for those items. // // START card layout and custom layout code -// first we need to define both a left and right button, we use the ones from stockIcons/directionalIcons.h -DrawableIcon iconLeft(-1, Coord(11, 22), tcgfx::DrawableIcon::ICON_XBITMAP, ArrowHoriz11x22BitmapLeft, nullptr); -DrawableIcon iconRight(-1, Coord(11, 22), tcgfx::DrawableIcon::ICON_XBITMAP, ArrowHoriz11x22BitmapRight, nullptr); +// Some helpful guides for working with card layouts and theme builder: +// 1. https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/creating-and-using-bitmaps-menu/ +// 2. https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ -color_t defaultCardPalette[] = {1, 0, 1, 1}; +// here we provide two title widgets, for ethernet connection, and client connection +TitleWidget widgetConnection(iconsConnection, 2, 16, 12); +TitleWidget widgetEthernet(iconsEthernetConnection, 2, 16, 12); -void setupGridLayoutForCardView() { - auto & factory = renderer.getGraphicsPropertiesFactory(); +color_t defaultCardPalette[] = {1, 0, 1, 1}; - // Now we define the grid layouts for the 33, 45 and 78 action items, each one has custom font size and therefore a - // custom height as well. It avoids the use of icons for the speed selectors. - factory.setDrawingPropertiesForItem(tcgfx::ItemDisplayProperties::COMPTYPE_ACTION, menu33.getId(), defaultCardPalette, - MenuPadding(2), u8g2_font_inr33_mn, 1, 2, 44, tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE, MenuBorder()); - factory.setDrawingPropertiesForItem(tcgfx::ItemDisplayProperties::COMPTYPE_ACTION, menu45.getId(), defaultCardPalette, - MenuPadding(2), u8g2_font_inr33_mn, 1, 2, 44, tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE, MenuBorder()); - factory.setDrawingPropertiesForItem(tcgfx::ItemDisplayProperties::COMPTYPE_ACTION, menu78.getId(), defaultCardPalette, - MenuPadding(2), u8g2_font_inr33_mn, 1, 2, 44, tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE, MenuBorder()); +void overrideDrawingForMainMenu(TcThemeBuilder& themeBuilder) { + // now we make the two settings and status menus use icons instead of regular drawing, and the numbered menu items + // 33,45,78 to use a larger font so it takes the entire screen. - // now we make the two settings and status menus use icons instead of regular drawing. + // we're going to use this a few times so declare once const Coord iconSize(APPICONS_WIDTH, APPICONS_HEIGHT); - factory.addImageToCache(DrawableIcon(menuSettings.getId(), iconSize, DrawableIcon::ICON_XBITMAP, settingsIcon40Bits)); - factory.addImageToCache(DrawableIcon(menuStatus.getId(), iconSize, DrawableIcon::ICON_XBITMAP, statusIcon40Bits)); - factory.addGridPosition(&menuSettings, GridPosition(GridPosition::DRAW_AS_ICON_ONLY, GridPosition::JUSTIFY_CENTER_NO_VALUE, 4, 40)); - factory.addGridPosition(&menuStatus, GridPosition(GridPosition::DRAW_AS_ICON_ONLY, GridPosition::JUSTIFY_CENTER_NO_VALUE, 5, 40)); - // after adding things to the drawing properties, we must refresh it. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); + // override menu33 to draw text centered in a large font with more padding + themeBuilder.menuItemOverride(menu33) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .withNativeFont(u8g2_font_inr33_mn, 1) + .withPadding(MenuPadding(2)) + .onRow(0) + .apply(); + + // override menu45 to draw text centered in a large font with more padding + themeBuilder.menuItemOverride(menu45) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .withNativeFont(u8g2_font_inr33_mn, 1) + .withPadding(MenuPadding(2)) + .onRow(1) + .apply(); + + // override menu78 to draw text centered in a large font with more padding + themeBuilder.menuItemOverride(menu78) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .withNativeFont(u8g2_font_inr33_mn, 1) + .withPadding(MenuPadding(2)) + .onRow(2) + .apply(); + + // override settings to draw as an icon only + themeBuilder.menuItemOverride(menuSettings) + .withImageXbmp(iconSize, settingsIcon40Bits) + .withPalette(defaultCardPalette) + .onRow(3) + .withDrawingMode(tcgfx::GridPosition::DRAW_AS_ICON_ONLY).apply(); + + // override status to draw as an icon only + themeBuilder.menuItemOverride(menuStatus) + .withImageXbmp(iconSize, statusIcon40Bits) + .withPalette(defaultCardPalette) + .onRow(4) + .withDrawingMode(tcgfx::GridPosition::DRAW_AS_ICON_ONLY).apply(); + + themeBuilder.menuItemOverride(menuStatusCards) + .withImageXbmp(Coord(32, 32), cardIconBitmap) + .onRow(5) + .withPalette(defaultCardPalette) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .apply(); +} + +void overrideDrawingForCardMenu(TcThemeBuilder& themeBuilder) { + // override back button on the card menu to be the default 32x32 back icon + themeBuilder.menuItemOverride(menuBackStatusCards) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withPadding(MenuPadding(2)) + .withPalette(defaultCardPalette) + .withImageXbmp(Coord(32, 32), defaultBackIconBitmap) + .onRow(0) // <== if you prefer that the back item is not first, you can change its order here + .apply(); + + // override every single item on the card sub menu to have larger font and different padding/justification + themeBuilder.submenuPropertiesActionOverride(menuStatusCards) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .withNativeFont(u8g2_font_inb16_mf, 1) + .withPadding(MenuPadding(2)) + .apply(); +} + +void setupCardLayoutAndWidgets() { + // create a theme builder to help us configure how to draw. + TcThemeBuilder themeBuilder(renderer); + + // enable card layout providing the left and right icons. This enables for root menu + themeBuilder.enableCardLayoutWithXbmImages(Coord(11, 22), ArrowHoriz11x22BitmapLeft, ArrowHoriz11x22BitmapRight, true) + .setMenuAsCard(menuStatusCards, true); - // and now we set the title widgets that appear on the top right, for the link status we check the ethernet library + // these two functions, defined directly above this one configure the icons and special text arrangements for + // the items in the card layouts. + overrideDrawingForMainMenu(themeBuilder); + overrideDrawingForCardMenu(themeBuilder); + + themeBuilder.addingTitleWidget(widgetEthernet) + .addingTitleWidget(widgetConnection); + + // You must always call apply after doing anything with theme builder. + themeBuilder.apply(); + + // now we set the title widgets that appear on the top right, for the link status we check the ethernet library // status every half second and update the widget to represent that status. - renderer.setFirstWidget(&widgetEthernet); taskManager.scheduleFixedRate(500, [] { widgetEthernet.setCurrentState(Ethernet.linkStatus() == LinkON ? 1 : 0); }); @@ -89,17 +167,18 @@ using namespace tcremote; void setup() { // This example logs using IoLogging, see the following guide to enable - // https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/ + // https://tcmenu.github.io/documentation/arduino-libraries//io-abstraction/arduino-logging-with-io-logging/ IOLOG_START_SERIAL serEnableLevel(SER_NETWORK_DEBUG, true); + serEnableLevel(SER_TCMENU_DEBUG, true); - // Start up serial and prepare the correct SPI, your pins may differ + // Start up serial and prepare the correct SPI, your pins or method of doing this may differ SPI.setMISO(PB4); SPI.setMOSI(PB5); SPI.setSCLK(PB3); - // - // Here we start up the Stm32Ethernet library for STM32 boards/chips with built-in ethernet + // Here we start up the Stm32Ethernet library for STM32 boards/chips with built-in ethernet, again you could + // easily change this for your own boards network arrangements Ethernet.begin(); Serial.print("My IP address is "); Ethernet.localIP().printTo(Serial); @@ -108,13 +187,14 @@ void setup() { // and then run the menu setup setupMenu(); - // now load back values from EEPROM, but only when we can read the confirmatory magic key, see EEPROM loading in the docs + // now load back values from EEPROM, but only when we can read the confirmatory magic key, see EEPROM docs: + // https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-eeprom-integrations/ menuMgr.load(0xd00d, [] { // this gets called when the menu hasn't been saved before, to initialise the first time. menuDecimal.setCurrentValue(4); }); - // here we register the custom drawing we created earlier with the renderer + // here we register the custom drawing created in `RawCustomDrawing.h` myCustomDrawing.registerWithRenderer(); // We can set a callback for when the title item is pressed on the main menu, here we just take over the display @@ -122,12 +202,11 @@ void setup() { renderer.takeOverDisplay(); }); - // lastly, we set the card layout for the main "root" menu. The last parameter is an optional touch screen interface - // that the card layout will interact with, to "flip" between cards. Set to null when no touch screen available. - renderer.enableCardLayout(iconLeft, iconRight, nullptr, true); + // set the list to have 10 rows, for each row the custom callback further down will be called to get the value. + menuRuntimesCustomList.setNumberOfRows(10); // now we set up the layouts to make the card view look right. - setupGridLayoutForCardView(); + setupCardLayoutAndWidgets(); } void loop() { diff --git a/examples/arduino32/stm32DuinoOneButton/ThemeMonoInverse.h b/examples/arduino32/stm32DuinoOneButton/ThemeMonoInverse.h deleted file mode 100644 index 02a68d3d..00000000 --- a/examples/arduino32/stm32DuinoOneButton/ThemeMonoInverse.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TCMENU_THEME_MONO_INVERSE -#define TCMENU_THEME_MONO_INVERSE - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; -color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; - -#define TITLE_PADDING 1 -#define TITLE_SPACING 0 - -void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 2); - - MenuPadding titlePadding(TITLE_PADDING); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_INVERSE \ No newline at end of file diff --git a/examples/arduino32/stm32DuinoOneButton/ThemeMonoInverseBuilder.h b/examples/arduino32/stm32DuinoOneButton/ThemeMonoInverseBuilder.h new file mode 100644 index 00000000..1ef2d8a6 --- /dev/null +++ b/examples/arduino32/stm32DuinoOneButton/ThemeMonoInverseBuilder.h @@ -0,0 +1,60 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; +color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; + +#define TITLE_PADDING 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoInverseTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 2) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(defaultTitlePaletteMono) + .withPadding(MenuPadding(TITLE_PADDING)) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/arduino32/stm32DuinoOneButton/generated/EthernetTransport.cpp b/examples/arduino32/stm32DuinoOneButton/generated/EthernetTransport.cpp deleted file mode 100644 index 1000724a..00000000 --- a/examples/arduino32/stm32DuinoOneButton/generated/EthernetTransport.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * Ethernet remote capability plugin. This file is a plugin file and should not be directly edited, - * it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - */ - -#include "EthernetTransport.h" -#include - -using namespace tcremote; - -#if ETHERNET_BUFFER_SIZE > 0 // we need buffering when dealing with Ethernet2 - -bool EthernetTagValTransport::available() { - return client && client.connected(); -} - -bool EthernetTagValTransport::connected() { - return client && client.connected(); -} - -void EthernetTagValTransport::flush() { - if(!client || writeBufferPos == 0) return; - - if((int)client.write(writeBuffer, writeBufferPos) == writeBufferPos) { - serdebugF2("Buffer written ", writeBufferPos); - writeBufferPos = 0; - client.flush(); - } - else { - writeBufferPos = 0; - close(); - } -} - -int EthernetTagValTransport::fillReadBuffer(uint8_t* dataBuffer, int maxData) { - if(client && client.connected() && client.available()) { - auto amt = client.read(dataBuffer, maxData); - if(amt <= 0) { - close(); - return 0; - } - serdebugF2("read to buffer ", amt); - return amt; - } - return 0; -} - -void EthernetTagValTransport::close() { - serdebugF("socket close"); - BaseBufferedRemoteTransport::close(); - client.stop(); -} - -#else // unbuffed client - requires library to support Nagle algorythm. - -bool EthernetTagValTransport::available() { - return client && client.connected(); -} - -bool EthernetTagValTransport::connected() { - return client && client.connected(); -} - -int EthernetTagValTransport::writeChar(char data) { - // only uncomment below for worst case debugging.. -// serdebug2("writing ", data); - return client.write(data); -} - -int EthernetTagValTransport::writeStr(const char* data) { - // only uncomment below for worst case debugging.. -// serdebug2("writing ", data); - return client.write(data); -} - -void EthernetTagValTransport::flush() { - if(client) client.flush(); -} - -uint8_t EthernetTagValTransport::readByte() { - return client.read(); -} - -bool EthernetTagValTransport::readAvailable() { - return client && client.connected() && client.available(); -} - -void EthernetTagValTransport::close() { - serdebugF("socket close"); - client.stop(); - currentField.msgType = UNKNOWN_MSG_TYPE; - currentField.fieldType = FVAL_PROCESSING_AWAITINGMSG; -} - -#endif - -bool EthernetInitialisation::attemptInitialisation() { -#ifdef ARDUINO_ARCH_STM32 - // we'll keep checking if the link is up before trying to initialise further - if(Ethernet.linkStatus() == LinkOFF) return false; -#endif - serdebugF("Initialising server "); - this->server->begin(); - initialised = true; - return initialised; -} - -bool EthernetInitialisation::attemptNewConnection(BaseRemoteServerConnection *remoteServerConnection) { - auto client = server->available(); - if(client) { - serdebugF("Client found"); - auto* tvCon = reinterpret_cast(remoteServerConnection); - reinterpret_cast(tvCon->transport())->setClient(client); - return true; - } - return false; -} diff --git a/examples/arduino32/stm32DuinoOneButton/generated/EthernetTransport.h b/examples/arduino32/stm32DuinoOneButton/generated/EthernetTransport.h deleted file mode 100644 index 31485777..00000000 --- a/examples/arduino32/stm32DuinoOneButton/generated/EthernetTransport.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * @file EthernetTransport.h - * - * Ethernet remote capability plugin. This file is a plugin file and should not be directly edited, - * it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - */ - -#ifndef TCMENU_ETHERNETTRANSPORT_H_ -#define TCMENU_ETHERNETTRANSPORT_H_ - -#include -#include -#include -#include -#include - -#ifndef ETHERNET_BUFFER_SIZE -#define ETHERNET_BUFFER_SIZE 0 -#endif - -#if ETHERNET_BUFFER_SIZE > 0 -#include -#endif - -namespace tcremote { - -#if ETHERNET_BUFFER_SIZE > 0 - -/** - * An implementation of TagValueTransport that is able to read and write via a buffer to sockets. - */ - class EthernetTagValTransport : public tcremote::BaseBufferedRemoteTransport { - private: - EthernetClient client; - public: - EthernetTagValTransport() : BaseBufferedRemoteTransport(BUFFER_MESSAGES_TILL_FULL, ETHERNET_BUFFER_SIZE, MAX_VALUE_LEN) { } - ~EthernetTagValTransport() override = default; - void setClient(EthernetClient cl) { this->client = cl; } - - int fillReadBuffer(uint8_t* data, int maxSize) override; - void flush() override; - bool available() override; - bool connected() override; - void close() override; - }; - -#else // ethernet buffering not needed - -/** - * An implementation of TagValueTransport that is able to read and write using sockets. - */ -class EthernetTagValTransport : public TagValueTransport { -private: - EthernetClient client; -public: - EthernetTagValTransport() : TagValueTransport(TagValueTransportType::TVAL_UNBUFFERED) {}; - ~EthernetTagValTransport() override = default; - void setClient(EthernetClient client) { this->client = client; } - - int writeChar(char data) override ; - int writeStr(const char* data) override; - void flush() override; - bool available() override; - bool connected() override; - uint8_t readByte() override; - bool readAvailable() override; - void close() override; -}; - -#endif // ethernet buffering check - -/** - * This class provides the initialisation and connection generation logic for ethernet connections. - */ -class EthernetInitialisation : public DeviceInitialisation { -private: - EthernetServer *server; -public: - explicit EthernetInitialisation(EthernetServer* server) : server(server) {} - - bool attemptInitialisation() override; - - bool attemptNewConnection(BaseRemoteServerConnection *transport) override; -}; - -/** - * This function converts from a RSSI (Radio Strength indicator) - * measurement into a series of icons (of the ones we have defined - * in the stock icons. The input is the RSSI figure in dB as an - * integer. - * @param strength the signal strength (usually negative) as an int - * @return a state that can be used with the standard wifi TitleWidget - */ -int fromWiFiRSSITo4StateIndicator(int strength); - -} // namespace tcremote - -#ifndef TC_MANUAL_NAMESPACING -using namespace tcremote; -#endif // TC_MANUAL_NAMESPACING - -#endif /* TCMENU_ETHERNETTRANSPORT_H_ */ diff --git a/examples/arduino32/stm32DuinoOneButton/generated/SerialTransport.cpp b/examples/arduino32/stm32DuinoOneButton/generated/SerialTransport.cpp new file mode 100644 index 00000000..9dbc27d7 --- /dev/null +++ b/examples/arduino32/stm32DuinoOneButton/generated/SerialTransport.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). + * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. + */ + +/** + * Serial remote capability plugin. This file is a plugin file and should not be directly edited, + * it will be replaced each time the project is built. If you want to edit this file in place, + * make sure to rename it first. + */ + +// we'll wait 100 times this amount in a loop when serial is not available +#ifndef MICROS_TO_WAIT_FOR_SERIAL +#define MICROS_TO_WAIT_FOR_SERIAL 10000 +#endif //MICROS_TO_WAIT_FOR_SERIAL + +#include "SerialTransport.h" +#include + +SerialTagValueTransport::SerialTagValueTransport(Stream* thePort) : TagValueTransport(TVAL_UNBUFFERED) { + this->serialPort = thePort; +} + +void SerialTagValueTransport::close() { + currentField.msgType = UNKNOWN_MSG_TYPE; + currentField.fieldType = FVAL_PROCESSING_AWAITINGMSG; +} + +// DO NOT replace this with the standard char* write method on serial. +// It cannot handle large volumes of data going through at once and often +// overflows the buffer causing data errors. +int SerialTagValueTransport::writeChar(char ch) { + if(available()) { + serialPort->write(ch); + } + else { + int tries = 100; + while(tries && !available()) { + --tries; + serialPort->flush(); + taskManager.yieldForMicros(MICROS_TO_WAIT_FOR_SERIAL); + } + + // if it's not available now, it probably will timeout anyway. + if(!available()) { + return 0; + } + + serialPort->write(ch); + } + return 1; +} + +int SerialTagValueTransport::writeStr(const char* str) { + int i=0; + bool lastWriteOk = true; + while(str[i] && lastWriteOk) { + lastWriteOk = writeChar(str[i]); + i++; + } + return i; +} + diff --git a/examples/arduino32/stm32DuinoOneButton/generated/SerialTransport.h b/examples/arduino32/stm32DuinoOneButton/generated/SerialTransport.h new file mode 100644 index 00000000..fe46d6a7 --- /dev/null +++ b/examples/arduino32/stm32DuinoOneButton/generated/SerialTransport.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). + * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. + */ + +/** + * @file SerialTransport.h + * + * Serial remote capability plugin. This file is a plugin file and should not be directly edited, + * it will be replaced each time the project is built. If you want to edit this file in place, + * make sure to rename it first. + */ + +#ifndef TCMENU_SERIALTRANSPORT_H_ +#define TCMENU_SERIALTRANSPORT_H_ + +#include +#include +#include +#include +#include +#include + +namespace tcremote { + + /** + * Serial transport is an implementation of TagValueTransport that works over a serial port + */ + class SerialTagValueTransport : public TagValueTransport { + private: + Stream* serialPort; + public: + explicit SerialTagValueTransport(Stream* thePort); + ~SerialTagValueTransport() override = default; + + void flush() override {serialPort->flush();} + int writeChar(char data) override; + int writeStr(const char* data) override; + + uint8_t readByte() override { return serialPort->read(); } + bool readAvailable() override { return serialPort->available(); } + bool available() override { return serialPort->availableForWrite() != 0;} + bool connected() override { return true;} + + void close() override; + }; +} + +#ifndef TC_MANUAL_NAMESPACING +using namespace tcremote; +#endif // TC_MANUAL_NAMESPACING + +#endif /* TCMENU_SERIALTRANSPORT_H_ */ diff --git a/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.cpp b/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.cpp index 9fd12d2e..a171d3a1 100644 --- a/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.cpp +++ b/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.cpp @@ -8,21 +8,24 @@ use elsewhere. */ -// Generated for STM32Duino by TcMenu 4.3.0-SNAPSHOT on 2024-07-27T07:53:35.721721700Z. +// Generated for STM32Duino by TcMenu 4.4.0-SNAPSHOT on 2024-10-19T08:59:45.395538500Z. #include #include "stm32DuinoOneButton_menu.h" -#include "../ThemeMonoInverse.h" +#include "../ThemeMonoInverseBuilder.h" #include // Global variable declarations const ConnectorLocalInfo applicationInfo = { "One Button", "4fe6e85d-2bbd-4d19-84e5-5d6746883028" }; +TcMenuRemoteServer remoteServer(applicationInfo); HalStm32EepromAbstraction glBspRom; -EepromAuthenticatorManager authManager(4); U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI gfx(U8G2_R0, PF13, PD15, PF12); U8g2Drawable gfxDrawable(&gfx); GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); TcOneButtonHandler oneButtonHandler(USER_BTN, 250); +NoInitialisationNeeded serialInitializer; +SerialTagValueTransport serialTransport(&Serial); +TagValueRemoteServerConnection serialConnection(serialTransport, serialInitializer); // Global Menu Item declarations const char enumStrSettingsEnumProp_0[] = "Item1"; @@ -48,17 +51,13 @@ void setupMenu() { setSizeBasedEEPROMStorageEnabled(false); glBspRom.initialise(0); menuMgr.setEepromRef(&glBspRom); - authManager.initialise(menuMgr.getEepromAbstraction(), 150); - menuMgr.setAuthenticator(&authManager); // Code generated by plugins and new operators. gfx.begin(); renderer.setUpdatesPerSecond(5); switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, false); menuMgr.initWithoutInput(&renderer, &menuPressMe); oneButtonHandler.start(); - renderer.setTitleMode(BaseGraphicalRenderer::NO_TITLE); - renderer.setUseSliderForAnalog(false); - renderer.enableTcUnicode(); - installMonoInverseTitleTheme(renderer, MenuFontDef(&OpenSansRegular8pt, 0), MenuFontDef(&OpenSansRegular8pt, 0), true); + remoteServer.addConnection(&serialConnection); + installMonoInverseTitleTheme(renderer, MenuFontDef(&OpenSansRegular8pt, 0), MenuFontDef(&OpenSansRegular8pt, 0), true, BaseGraphicalRenderer::NO_TITLE, true); } diff --git a/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.h b/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.h index 461f3fe8..9ffd75f5 100644 --- a/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.h +++ b/examples/arduino32/stm32DuinoOneButton/generated/stm32DuinoOneButton_menu.h @@ -16,13 +16,15 @@ #include #include "tcMenuU8g2.h" #include +#include +#include "SerialTransport.h" #include #include #include -#include // variables we declare that you may need to access extern const PROGMEM ConnectorLocalInfo applicationInfo; +extern TcMenuRemoteServer remoteServer; extern U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI gfx; extern U8g2Drawable gfxDrawable; extern GraphicsDeviceRenderer renderer; diff --git a/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.emf b/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.emf index 824af15f..00a6a4be 100644 --- a/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.emf +++ b/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.emf @@ -115,9 +115,9 @@ "lastDisplayUuid": "fd998437-c4b2-4386-ba88-d0ae7c20620b", "lastInputUuid": "4F92CBC0-D13A-4090-9B86-C1952FE42D9B", "lastRemoteUuids": [ - "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" + "1e38dc42-672d-4c1c-a393-2c7632bf6c5c" ], - "lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0", + "lastThemeUuid": "396ED4DF-AD7B-4951-A848-A9E5838A549B", "applicationUUID": "4fe6e85d-2bbd-4d19-84e5-5d6746883028", "applicationName": "One Button", "lastProperties": [ @@ -201,6 +201,11 @@ "latestValue": "250", "subsystem": "INPUT" }, + { + "name": "SERIAL_PORT", + "latestValue": "Serial", + "subsystem": "REMOTE" + }, { "name": "ITEM_FONT", "latestValue": "ada:OpenSansRegular8pt,0", @@ -237,7 +242,7 @@ "saveLocation": "PROJECT_TO_CURRENT_WITH_GENERATED", "usingSizedEEPROMStorage": false, "eepromDefinition": "bsp:0", - "authenticatorDefinition": "rom:150:4", + "authenticatorDefinition": "", "projectIoExpanders": [ "deviceIO:" ], @@ -245,8 +250,7 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] + "appIsModular": false }, "stringLists": [] } \ No newline at end of file diff --git a/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.ino b/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.ino index dc7282a3..3a8f754a 100644 --- a/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.ino +++ b/examples/arduino32/stm32DuinoOneButton/stm32DuinoOneButton.ino @@ -4,17 +4,15 @@ // // You configure the single pin in code generator, and away you go. // -// Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ +// Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ // #include "generated/stm32DuinoOneButton_menu.h" #include void setup() { - // This example logs using IoLogging, see the following guide to enable - // https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/arduino-logging-with-io-logging/ - IOLOG_START_SERIAL - serEnableLevel(SER_NETWORK_DEBUG, true); + // Start the serial port so that we can use the remote connectivity + Serial.begin(115200); // Start up serial and prepare the correct SPI, your pins may differ SPI.setMISO(PB4); diff --git a/examples/avr/adafruitST7735Mega/ThemeCoolBlueTraditional.h b/examples/avr/adafruitST7735Mega/ThemeCoolBlueTraditional.h deleted file mode 100644 index 7c249b90..00000000 --- a/examples/avr/adafruitST7735Mega/ThemeCoolBlueTraditional.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -// -// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() -// - -// tcMenu drawing properties take a 4 color palette for items, titles and actions. -// this renderer shares the color configuration for items and actions. -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; - -void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // first we keep a reference to the screen size, and set the dimensions on the renderer. - auto width = bgr.getDeviceDrawable()->getDisplayDimensions().x; - auto height = bgr.getDeviceDrawable()->getDisplayDimensions().y; - bgr.setDisplayDimensions(width, height); - - // get hold of the item display factory that holds the drawing configuration. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // when an item is active, it will show in these colours instead of the default. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // here we calculate the item padding and row heights based on the resolution of the display - bool medResOrBetter = width > 160; - MenuPadding titlePadding(medResOrBetter ? 4 : 2); - MenuPadding itemPadding(medResOrBetter ? 2 : 1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - // we set the editing and selected icons here based on the row height. - if(needEditingIcons && itemHeight > 12) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defActiveIcon)); - } - else if(needEditingIcons) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - } - - // we tell the library how to draw titles, items and actions by default. - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, titlePadding, titleFont.fontData, titleFont.fontMag, - medResOrBetter ? 3 : 1, titleHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - - // after adjusting the drawing configuration, we must always refresh the cache. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE diff --git a/examples/avr/adafruitST7735Mega/adafruitST7735Mega.emf b/examples/avr/adafruitST7735Mega/adafruitST7735Mega.emf deleted file mode 100644 index d81b732a..00000000 --- a/examples/avr/adafruitST7735Mega/adafruitST7735Mega.emf +++ /dev/null @@ -1,281 +0,0 @@ -{ - "version": "1.00", - "projectName": "Project description", - "author": "dave", - "items": [ - { - "parentId": 0, - "type": "analogItem", - "defaultValue": "0", - "item": { - "maxValue": 255, - "offset": 0, - "divisor": 1, - "unitName": "Unit", - "step": 1, - "name": "Analog", - "variableName": "Analog", - "id": 1, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "boolItem", - "defaultValue": "false", - "item": { - "naming": "YES_NO", - "name": "Bool", - "variableName": "Bool", - "id": 2, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "largeNumItem", - "defaultValue": "0", - "item": { - "digitsAllowed": 5, - "decimalPlaces": 2, - "negativeAllowed": true, - "name": "Lge", - "variableName": "Lge", - "id": 3, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "subMenu", - "item": { - "secured": false, - "name": "Sub", - "variableName": "Sub", - "id": 4, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "actionMenu", - "item": { - "name": "Press me", - "variableName": "SubPressMe", - "id": 5, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "floatItem", - "defaultValue": "0.0", - "item": { - "numDecimalPlaces": 3, - "name": "Flt", - "variableName": "Flt", - "id": 6, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - } - ], - "codeOptions": { - "embeddedPlatform": "ARDUINO", - "lastDisplayUuid": "4dcb12ec-13d8-4466-b8b6-bd575eae4612", - "lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87", - "lastRemoteUuids": [ - "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" - ], - "lastThemeUuid": "03c6b25f-db63-402a-8447-a5ce1484c14d", - "applicationUUID": "0b2b11cf-0567-4173-9fbc-80d56674cbb3", - "applicationName": "adaAvrTest", - "lastProperties": [ - { - "name": "DISPLAY_VARIABLE", - "latestValue": "gfx", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_TYPE", - "latestValue": "Adafruit_ST7735", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_WIDTH", - "latestValue": "160", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_HEIGHT", - "latestValue": "128", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_RESET_PIN", - "latestValue": "-1", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_CS_PIN", - "latestValue": "6", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_RS_PIN", - "latestValue": "7", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_DATA_PIN", - "latestValue": "-1", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_CLOCK_PIN", - "latestValue": "-1", - "subsystem": "DISPLAY" - }, - { - "name": "ST7735_TAB_TYPE", - "latestValue": "INITR_BLACKTAB", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_ROTATION", - "latestValue": "3", - "subsystem": "DISPLAY" - }, - { - "name": "UPDATES_PER_SEC", - "latestValue": "4", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_BUFFER_SIZE", - "latestValue": "20", - "subsystem": "DISPLAY" - }, - { - "name": "SW_POLLING_MODE", - "latestValue": "SWITCHES_NO_POLLING", - "subsystem": "INPUT" - }, - { - "name": "SWITCH_IODEVICE", - "latestValue": "mcp23017", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_PIN_A", - "latestValue": "6", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_PIN_B", - "latestValue": "7", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_PIN_OK", - "latestValue": "5", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_BACK_PIN", - "latestValue": "-1", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_NEXT_PIN", - "latestValue": "-1", - "subsystem": "INPUT" - }, - { - "name": "PULLUP_LOGIC", - "latestValue": "true", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_IS_QUARTER_CYCLE", - "latestValue": "false", - "subsystem": "INPUT" - }, - { - "name": "ITEM_FONT", - "latestValue": "ada:OpenSansCyrillicLatin12,0", - "subsystem": "THEME" - }, - { - "name": "TITLE_FONT", - "latestValue": "ada:OpenSansCyrillicLatin12,0", - "subsystem": "THEME" - }, - { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", - "subsystem": "THEME" - }, - { - "name": "TITLE_SHOW_MODE", - "latestValue": "TITLE_FIRST_ROW", - "subsystem": "THEME" - }, - { - "name": "USE_TC_UNICODE", - "latestValue": "true", - "subsystem": "THEME" - }, - { - "name": "USE_SLIDER_ANALOG", - "latestValue": "true", - "subsystem": "THEME" - }, - { - "name": "NEED_EDITING_ICONS", - "latestValue": "true", - "subsystem": "THEME" - } - ], - "namingRecursive": true, - "useCppMain": false, - "saveLocation": "ALL_TO_CURRENT", - "usingSizedEEPROMStorage": false, - "eepromDefinition": "", - "authenticatorDefinition": "", - "projectIoExpanders": [ - "mcp23017:mcp23017:32:2", - "deviceIO:" - ], - "menuInMenuCollection": { - "menuDefinitions": [] - }, - "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] - }, - "stringLists": [] -} \ No newline at end of file diff --git a/examples/avr/adafruitST7735Mega/adafruitST7735Mega.ino b/examples/avr/adafruitST7735Mega/adafruitST7735Mega.ino deleted file mode 100644 index 52c371c2..00000000 --- a/examples/avr/adafruitST7735Mega/adafruitST7735Mega.ino +++ /dev/null @@ -1,27 +0,0 @@ -/** - * This example shows the use of an ST7735 and MCP23017 IO expander with a MEGA2560. It is configured out of the box - * to work with a MEGA2560, ST7735 display and a rotary encoder connected on an MCP23017 IO expander. Other than this - * it is a relatively simple demonstration of features. - * - * It uses the display buffering to reduce flicker, but this does use a little extra of the MEGA's RAM - ~1600 bytes. - * - * For the MCP23017: - * - device interrupt pin wired to Arduino on pin 2. - * - A and B are wired to the 23017 on pins 6 and 7. - * - Select is wired to the 23017 on 5. - * Display: - * - Display CS is on 6 and RS on 7. - * - Don't forget the display is not 5V tolerant, all lines must be shifted. - */ -#include "adafruitST7735Mega_menu.h" - -void setup() { - IOLOG_START_SERIAL - - Wire.begin(); - setupMenu(); -} - -void loop() { - taskManager.runLoop(); -} diff --git a/examples/avr/adafruitST7735Mega/adafruitST7735Mega_menu.cpp b/examples/avr/adafruitST7735Mega/adafruitST7735Mega_menu.cpp deleted file mode 100644 index b04f2eb9..00000000 --- a/examples/avr/adafruitST7735Mega/adafruitST7735Mega_menu.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#include -#include "adafruitST7735Mega_menu.h" -#include "ThemeCoolBlueTraditional.h" -#include - -// Global variable declarations -const PROGMEM ConnectorLocalInfo applicationInfo = { "adaAvrTest", "0b2b11cf-0567-4173-9fbc-80d56674cbb3" }; -IoAbstractionRef ioexp_mcp23017 = ioFrom23017(0x20, ACTIVE_LOW_OPEN, 2); -Adafruit_ST7735 gfx(6, 7, -1); -AdafruitDrawable gfxDrawable(&gfx, 20); -GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); - -// Global Menu Item declarations -const PROGMEM FloatMenuInfo minfoFlt = { "Flt", 6, 0xffff, 3, NO_CALLBACK }; -FloatMenuItem menuFlt(&minfoFlt, 0.0, nullptr, INFO_LOCATION_PGM); -const PROGMEM AnyMenuInfo minfoSubPressMe = { "Press me", 5, 0xffff, 0, NO_CALLBACK }; -ActionMenuItem menuSubPressMe(&minfoSubPressMe, &menuFlt, INFO_LOCATION_PGM); -const PROGMEM SubMenuInfo minfoSub = { "Sub", 4, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackSub(&minfoSub, &menuSubPressMe, INFO_LOCATION_PGM); -SubMenuItem menuSub(&minfoSub, &menuBackSub, nullptr, INFO_LOCATION_PGM); -const PROGMEM AnyMenuInfo minfoLge = { "Lge", 3, 0xffff, 0, NO_CALLBACK }; -EditableLargeNumberMenuItem menuLge(&minfoLge, LargeFixedNumber(5, 2, 0U, 0U, false), true, &menuSub, INFO_LOCATION_PGM); -const PROGMEM BooleanMenuInfo minfoBool = { "Bool", 2, 0xffff, 1, NO_CALLBACK, NAMING_YES_NO }; -BooleanMenuItem menuBool(&minfoBool, false, &menuLge, INFO_LOCATION_PGM); -const PROGMEM AnalogMenuInfo minfoAnalog = { "Analog", 1, 0xffff, 255, NO_CALLBACK, 0, 1, "Unit" }; -AnalogMenuItem menuAnalog(&minfoAnalog, 0, &menuBool, INFO_LOCATION_PGM); - -void setupMenu() { - // First we set up eeprom and authentication (if needed). - setSizeBasedEEPROMStorageEnabled(false); - // Code generated by plugins and new operators. - gfx.initR(INITR_BLACKTAB); - gfx.setRotation(3); - renderer.setUpdatesPerSecond(4); - switches.init(ioexp_mcp23017, SWITCHES_NO_POLLING, true); - menuMgr.initForEncoder(&renderer, &menuAnalog, 6, 7, 5); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(true); - renderer.enableTcUnicode(); - installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin12, 0), MenuFontDef(&OpenSansCyrillicLatin12, 0), true); -} - diff --git a/examples/avr/adafruitST7735Mega/adafruitST7735Mega_menu.h b/examples/avr/adafruitST7735Mega/adafruitST7735Mega_menu.h deleted file mode 100644 index e3671eee..00000000 --- a/examples/avr/adafruitST7735Mega/adafruitST7735Mega_menu.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#ifndef MENU_GENERATED_CODE_H -#define MENU_GENERATED_CODE_H - -#include -#include -#include -#include "tcMenuAdaFruitGfx.h" -#include -#include -#include -#include -#include - -// variables we declare that you may need to access -extern const PROGMEM ConnectorLocalInfo applicationInfo; -extern Adafruit_ST7735 gfx; -extern AdafruitDrawable gfxDrawable; -extern GraphicsDeviceRenderer renderer; -extern const UnicodeFont OpenSansCyrillicLatin12[]; - -// Any externals needed by IO expanders, EEPROMs etc -extern IoAbstractionRef ioexp_mcp23017; - -// Global Menu Item exports -extern FloatMenuItem menuFlt; -extern ActionMenuItem menuSubPressMe; -extern BackMenuItem menuBackSub; -extern SubMenuItem menuSub; -extern EditableLargeNumberMenuItem menuLge; -extern BooleanMenuItem menuBool; -extern AnalogMenuItem menuAnalog; - -// Provide a wrapper to get hold of the root menu item and export setupMenu -inline MenuItem& rootMenuItem() { return menuAnalog; } -void setupMenu(); - -// Callback functions must always include CALLBACK_FUNCTION after the return type -#define CALLBACK_FUNCTION - - -#endif // MENU_GENERATED_CODE_H diff --git a/examples/avr/analogDfRobot/analogDfRobot.emf b/examples/avr/analogDfRobot/analogDfRobot.emf index d8de83ad..3cf90a9a 100644 --- a/examples/avr/analogDfRobot/analogDfRobot.emf +++ b/examples/avr/analogDfRobot/analogDfRobot.emf @@ -220,8 +220,7 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] + "appIsModular": false }, "stringLists": [] } \ No newline at end of file diff --git a/examples/avr/analogDfRobot/analogDfRobot_menu.cpp b/examples/avr/analogDfRobot/analogDfRobot_menu.cpp index 44d9f70b..f52d7991 100644 --- a/examples/avr/analogDfRobot/analogDfRobot_menu.cpp +++ b/examples/avr/analogDfRobot/analogDfRobot_menu.cpp @@ -8,6 +8,8 @@ use elsewhere. */ +// Generated for Arduino AVR/Uno/Mega by TcMenu 4.3.1 on 2024-10-12T11:23:21.762740700Z. + #include #include "analogDfRobot_menu.h" diff --git a/examples/avr/analogJoystick1306Ascii/SpaceJunkGame.h b/examples/avr/analogJoystick1306Ascii/SpaceJunkGame.h deleted file mode 100644 index 6c9d6158..00000000 --- a/examples/avr/analogJoystick1306Ascii/SpaceJunkGame.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef TCLIBRARYDEV_SPACEJUNKGAME_H -#define TCLIBRARYDEV_SPACEJUNKGAME_H - -#include -#include "analogJoystick1306Ascii_menu.h" -#include - -#define DISPLAY_HEIGHT_ROWS 8 -#define DISPLAY_WIDTH_MINUS_ONE 110 -#define ANALOG_PIN A0 - -enum SpaceJunkType: uint8_t { - ROCK = '*', SATELLITE = '%', SPACE_STATION = '@', OFF_SCREEN = 0 -}; - -class SpaceJunkItem { - uint8_t xPosition = 0; - uint8_t yPosition = 0; - uint8_t speed = 1; - SpaceJunkType junkType = ROCK; - -public: - void init(uint8_t xpos, uint8_t ypos, SpaceJunkType type, uint8_t sp = 1) { - Serial.print("junk ");Serial.print(xpos);Serial.print(' ');Serial.print(ypos); Serial.print(' '); Serial.println(type); - xPosition = xpos; - yPosition = ypos; - junkType = type; - speed = sp; - } - - bool isShipInRange(uint8_t row) { - return !isOffscreen() && (xPosition < (speed + 20) && yPosition == row); - } - - void tick() { - xPosition = xPosition - speed; - if(xPosition > DISPLAY_WIDTH_MINUS_ONE) { - junkType = OFF_SCREEN; - } else { - gfx.setCursor(xPosition, yPosition); - gfx.print((char)junkType); - } - } - - bool isOffscreen() { return junkType == OFF_SCREEN; } -}; - -class SpaceJunkGame { -public: - enum GameMode { GAME_STARTED, GAME_STOPPED, GAME_OVER }; -private: - SpaceJunkItem items[5]; - uint8_t counter=0; - GameMode gameStarted = GAME_STARTED; - int score = 0; -public: - void start() { - for(SpaceJunkItem& item : items) { - item.init(0, 0, OFF_SCREEN); - } - score = 0; - gameStarted = GAME_STARTED; - } - - void stop() { - gameStarted = GAME_STOPPED; - if(score > menuHighScore.getCurrentValue()) { - menuHighScore.setCurrentValue(score); - } - } - - bool isStarted() { return gameStarted == GAME_STARTED || gameStarted == GAME_OVER; } - - SpaceJunkType nextSpaceJunkType() { - counter = rand()%3; - switch(counter) { - case 0: return SPACE_STATION; - case 1: return SATELLITE; - default: - counter = 0; - return ROCK; - } - } - void tick() { - if(gameStarted == GAME_STOPPED || gameStarted == GAME_OVER) return; - - gfx.setFont(System5x7); - - Serial.println("Game"); - score = score + 1; - int level = (score / 50) + 1; - gfx.clear(); - - int row = internalAnalogIo()->getCurrentFloat(ANALOG_PIN) * DISPLAY_HEIGHT_ROWS; - row = min(row, DISPLAY_HEIGHT_ROWS - 1); - gfx.setCursor(0, row); - gfx.print("=>"); - - for(SpaceJunkItem& item : items) { - if(item.isShipInRange(row)) { - gameStarted = GAME_OVER; - gfx.setCursor(10, 1); - gfx.print("Game Over"); - return; - } - item.tick(); - if(item.isOffscreen()) { - item.init(DISPLAY_WIDTH_MINUS_ONE, rand() % DISPLAY_HEIGHT_ROWS, nextSpaceJunkType(), (rand() % 20) + level); - } - } - } -}; - -#endif //TCLIBRARYDEV_SPACEJUNKGAME_H diff --git a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii.emf b/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii.emf deleted file mode 100644 index 14efed84..00000000 --- a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii.emf +++ /dev/null @@ -1,276 +0,0 @@ -{ - "version": "1.00", - "projectName": "A very simple analog game written with the library stack.", - "author": "dave", - "items": [ - { - "parentId": 0, - "type": "actionMenu", - "item": { - "name": "Instructions", - "variableName": "Instructions", - "id": 1, - "eepromAddress": -1, - "functionName": "onInstructions", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "actionMenu", - "item": { - "name": "Start Game", - "variableName": "StartGame", - "id": 2, - "eepromAddress": -1, - "functionName": "onStartGame", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "analogItem", - "defaultValue": "0", - "item": { - "maxValue": 10000, - "offset": 0, - "divisor": 1, - "unitName": "", - "step": 1, - "name": "High Score", - "variableName": "HighScore", - "id": 3, - "eepromAddress": 2, - "readOnly": true, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 0, - "type": "subMenu", - "item": { - "secured": false, - "name": "Settings", - "variableName": "Settings", - "id": 4, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "analogItem", - "defaultValue": "5", - "item": { - "maxValue": 10, - "offset": 0, - "divisor": 1, - "unitName": "fps", - "step": 1, - "name": "Frame Rate", - "variableName": "SettingsFrameRate", - "id": 5, - "eepromAddress": 4, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "enumItem", - "defaultValue": "0", - "item": { - "enumEntries": [ - "Easy", - "Medium", - "Hard" - ], - "name": "Difficulty", - "variableName": "SettingsDifficulty", - "id": 6, - "eepromAddress": 6, - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - }, - { - "parentId": 4, - "type": "actionMenu", - "item": { - "name": "Save All", - "variableName": "SettingsSaveAll", - "id": 7, - "eepromAddress": -1, - "functionName": "onSave", - "readOnly": false, - "localOnly": false, - "visible": true, - "staticDataInRAM": false - } - } - ], - "codeOptions": { - "embeddedPlatform": "ARDUINO", - "lastDisplayUuid": "5EED8D08-CF04-420E-A190-E40743FEA20F", - "lastInputUuid": "20409bb8-b8a1-4d1d-b632-2cf9b57353e3", - "lastRemoteUuids": [ - "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" - ], - "lastThemeUuid": "2026a7f2-0d5b-43f5-9f98-4f0eacac4c0e", - "applicationUUID": "5049a016-0d7e-4004-a183-cabe4e9cf6b8", - "applicationName": "Space Junk", - "lastProperties": [ - { - "name": "DISPLAY_VARIABLE", - "latestValue": "gfx", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_TYPE", - "latestValue": "SSD1306AsciiAvrI2c", - "subsystem": "DISPLAY" - }, - { - "name": "DEVICE_CONFIGURATION", - "latestValue": "SH1106_128x64", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_I2C_ADDR", - "latestValue": "0x3C", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_SPI_CS", - "latestValue": "-1", - "subsystem": "DISPLAY" - }, - { - "name": "DISPLAY_SPI_DC", - "latestValue": "-1", - "subsystem": "DISPLAY" - }, - { - "name": "CHAR_WIDTH", - "latestValue": "20", - "subsystem": "DISPLAY" - }, - { - "name": "TITLE_FONT", - "latestValue": "System5x7", - "subsystem": "DISPLAY" - }, - { - "name": "ITEM_FONT", - "latestValue": "System5x7", - "subsystem": "DISPLAY" - }, - { - "name": "SW_POLLING_MODE", - "latestValue": "SWITCHES_POLL_EVERYTHING", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_PIN", - "latestValue": "A0", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_Y_CENTRE_VALUE", - "latestValue": "0.5", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_THRESHOLD_Y", - "latestValue": "0.05", - "subsystem": "INPUT" - }, - { - "name": "BUTTON_PIN", - "latestValue": "A2", - "subsystem": "INPUT" - }, - { - "name": "PULLUP_LOGIC", - "latestValue": "true", - "subsystem": "INPUT" - }, - { - "name": "SEPARATOR", - "latestValue": "", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_NEED_X", - "latestValue": "true", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_PINX", - "latestValue": "A1", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_PINX_LEFT", - "latestValue": "200", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_PINX_RIGHT", - "latestValue": "201", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_X_CENTRE_VALUE", - "latestValue": "0.5", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_CUSTOM_ACCEL", - "latestValue": "true", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_ACCEL_INITIAL", - "latestValue": "550", - "subsystem": "INPUT" - }, - { - "name": "JOYSTICK_ACCEL_DIVISOR", - "latestValue": "4", - "subsystem": "INPUT" - } - ], - "namingRecursive": true, - "useCppMain": false, - "saveLocation": "ALL_TO_CURRENT", - "usingSizedEEPROMStorage": false, - "eepromDefinition": "avr:", - "authenticatorDefinition": "", - "projectIoExpanders": [ - "deviceIO:" - ], - "menuInMenuCollection": { - "menuDefinitions": [] - }, - "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] - }, - "stringLists": [] -} \ No newline at end of file diff --git a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii.ino b/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii.ino deleted file mode 100644 index 4c2278f1..00000000 --- a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii.ino +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Space Junk, the game for Uno:) - * - * This game shows the use of the SSD1306ASCII library written by greiman, it combines that with the analog joystick - * support built into tcMenu. - * - * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ - * - * Hardware: - * * I2C OLED display that is suitable for use with SSD1306ASCII - * * Analog Joystick with X and Y axis (A0-Y axis, A1-X axis, A2-button). - */ - -#include "analogJoystick1306Ascii_menu.h" -// default CPP main file for sketch -#include -#include "SpaceJunkGame.h" -#include - -void setup() { - Serial.begin(115200); - setupMenu(); - - // turn off the reset behaviour, no going back to main during the game! - renderer.turnOffResetLogic(); - - menuMgr.load(); -} - -void loop() { - taskManager.runLoop(); -} - -bool instructionsStarting; -void instructionsRenderer(unsigned int value, RenderPressMode mode) { - if(instructionsStarting) { - gfx.clear(); - gfx.setFont(System5x7); - gfx.println("Space Junk"); - gfx.println("Dodge junk!"); - gfx.println("in space"); - gfx.println("Press OK!"); - instructionsStarting = false; - } else if(mode == RPRESS_PRESSED) { - renderer.giveBackDisplay(); - } -} - -void CALLBACK_FUNCTION onInstructions(int id) { - instructionsStarting = true; - renderer.takeOverDisplay(instructionsRenderer); -} - -SpaceJunkGame game; -void gameRenderer(unsigned int value, RenderPressMode mode) { - if(!game.isStarted()) { - game.start(); - } - - if(mode == RPRESS_PRESSED) { - game.stop(); - renderer.giveBackDisplay(); - } else { - game.tick(); - } -} - -void CALLBACK_FUNCTION onStartGame(int id) { - renderer.takeOverDisplay(gameRenderer); -} - -const char pgmSaved[] PROGMEM = "Saved to ROM"; -void CALLBACK_FUNCTION onSave(int id) { - menuMgr.save(); - auto dlg = renderer.getDialog(); - if(dlg && !dlg->isInUse()) { - dlg->setButtons(BTNTYPE_CLOSE, BTNTYPE_NONE); - dlg->show(pgmSaved, true); - dlg->copyIntoBuffer("Settings"); - } -} diff --git a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii_menu.cpp b/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii_menu.cpp deleted file mode 100644 index da54b9ac..00000000 --- a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii_menu.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#include -#include "analogJoystick1306Ascii_menu.h" - -// Global variable declarations -const PROGMEM ConnectorLocalInfo applicationInfo = { "Space Junk", "5049a016-0d7e-4004-a183-cabe4e9cf6b8" }; -AvrEeprom glAvrRom; -SSD1306AsciiAvrI2c gfx; -SSD1306AsciiRenderer renderer(20, System5x7, System5x7); -MultiIoAbstraction joystickMultiIo(200); -AnalogJoystickToButtons joystickIoXAxis(internalAnalogIo(), A1, 0.5); - -// Global Menu Item declarations -const PROGMEM AnyMenuInfo minfoSettingsSaveAll = { "Save All", 7, 0xffff, 0, onSave }; -ActionMenuItem menuSettingsSaveAll(&minfoSettingsSaveAll, nullptr, INFO_LOCATION_PGM); -const char enumStrSettingsDifficulty_0[] PROGMEM = "Easy"; -const char enumStrSettingsDifficulty_1[] PROGMEM = "Medium"; -const char enumStrSettingsDifficulty_2[] PROGMEM = "Hard"; -const char* const enumStrSettingsDifficulty[] PROGMEM = { enumStrSettingsDifficulty_0, enumStrSettingsDifficulty_1, enumStrSettingsDifficulty_2 }; -const PROGMEM EnumMenuInfo minfoSettingsDifficulty = { "Difficulty", 6, 6, 2, NO_CALLBACK, enumStrSettingsDifficulty }; -EnumMenuItem menuSettingsDifficulty(&minfoSettingsDifficulty, 0, &menuSettingsSaveAll, INFO_LOCATION_PGM); -const PROGMEM AnalogMenuInfo minfoSettingsFrameRate = { "Frame Rate", 5, 4, 10, NO_CALLBACK, 0, 1, "fps" }; -AnalogMenuItem menuSettingsFrameRate(&minfoSettingsFrameRate, 5, &menuSettingsDifficulty, INFO_LOCATION_PGM); -const PROGMEM SubMenuInfo minfoSettings = { "Settings", 4, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackSettings(&minfoSettings, &menuSettingsFrameRate, INFO_LOCATION_PGM); -SubMenuItem menuSettings(&minfoSettings, &menuBackSettings, nullptr, INFO_LOCATION_PGM); -const PROGMEM AnalogMenuInfo minfoHighScore = { "High Score", 3, 2, 10000, NO_CALLBACK, 0, 1, "" }; -AnalogMenuItem menuHighScore(&minfoHighScore, 0, &menuSettings, INFO_LOCATION_PGM); -const PROGMEM AnyMenuInfo minfoStartGame = { "Start Game", 2, 0xffff, 0, onStartGame }; -ActionMenuItem menuStartGame(&minfoStartGame, &menuHighScore, INFO_LOCATION_PGM); -const PROGMEM AnyMenuInfo minfoInstructions = { "Instructions", 1, 0xffff, 0, onInstructions }; -ActionMenuItem menuInstructions(&minfoInstructions, &menuStartGame, INFO_LOCATION_PGM); - -void setupMenu() { - // First we set up eeprom and authentication (if needed). - setSizeBasedEEPROMStorageEnabled(false); - menuMgr.setEepromRef(&glAvrRom); - // Now add any readonly, non-remote and visible flags. - menuHighScore.setReadOnly(true); - - // Code generated by plugins and new operators. - gfx.begin(&SH1106_128x64, 0x3C); - renderer.setGraphicsDevice(&gfx); - multiIoAddExpander(&joystickMultiIo, &joystickIoXAxis, 5); - switches.init(&joystickMultiIo, SWITCHES_POLL_EVERYTHING, true); - switches.addSwitch(A2, NULL); - switches.onRelease(A2, [](pinid_t /*key*/, bool held) { - menuMgr.onMenuSelect(held); - }); - switches.addSwitch(200, [](pinid_t /*key*/, bool held) { - menuMgr.performDirectionMove(true); - }); - switches.addSwitch(201, [](pinid_t /*key*/, bool held) { - menuMgr.performDirectionMove(false); - }); - setupAnalogJoystickEncoder(internalAnalogIo(), A0, [](int val) { - menuMgr.valueChanged(val); - }); - reinterpret_cast(switches.getEncoder())->setTolerance(0.5, 0.05); - reinterpret_cast(switches.getEncoder())->setAccelerationParameters(550.0F, 4.0F); - menuMgr.initWithoutInput(&renderer, &menuInstructions); -} - diff --git a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii_menu.h b/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii_menu.h deleted file mode 100644 index 968d6313..00000000 --- a/examples/avr/analogJoystick1306Ascii/analogJoystick1306Ascii_menu.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#ifndef MENU_GENERATED_CODE_H -#define MENU_GENERATED_CODE_H - -#include -#include -#include -#include -#include "ssd1306asciiRenderer.h" -#include -#include -#include -#include - -// variables we declare that you may need to access -extern const PROGMEM ConnectorLocalInfo applicationInfo; -extern SSD1306AsciiAvrI2c gfx; -extern SSD1306AsciiRenderer renderer; -extern MultiIoAbstraction joystickMultiIo; -extern AnalogJoystickToButtons joystickIoXAxis; - -// Any externals needed by IO expanders, EEPROMs etc - - -// Global Menu Item exports -extern ActionMenuItem menuSettingsSaveAll; -extern EnumMenuItem menuSettingsDifficulty; -extern AnalogMenuItem menuSettingsFrameRate; -extern BackMenuItem menuBackSettings; -extern SubMenuItem menuSettings; -extern AnalogMenuItem menuHighScore; -extern ActionMenuItem menuStartGame; -extern ActionMenuItem menuInstructions; - -// Provide a wrapper to get hold of the root menu item and export setupMenu -inline MenuItem& rootMenuItem() { return menuInstructions; } -void setupMenu(); - -// Callback functions must always include CALLBACK_FUNCTION after the return type -#define CALLBACK_FUNCTION - -void CALLBACK_FUNCTION onInstructions(int id); -void CALLBACK_FUNCTION onSave(int id); -void CALLBACK_FUNCTION onStartGame(int id); - -#endif // MENU_GENERATED_CODE_H diff --git a/examples/avr/analogJoystick1306Ascii/ssd1306asciiRenderer.cpp b/examples/avr/analogJoystick1306Ascii/ssd1306asciiRenderer.cpp deleted file mode 100644 index 51c2765e..00000000 --- a/examples/avr/analogJoystick1306Ascii/ssd1306asciiRenderer.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - * - * NOTE: Be aware that the underlying SSD1306ascii library is GPL and linking with it will essentially make your code GPL - * - */ - -/** - * @file ssd1306ascii.h - * - * ssd1306ascii renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - * - * This plugin allows rendering to the Ssd1306Ascii library. It is a low memory ascii renderer that - * provides text based functions. - * - * LIBRARY REQUIREMENT - * This renderer is designed for use with this library: https://github.com/greiman/SSD1306Ascii - */ -#include "ssd1306asciiRenderer.h" - -extern const ConnectorLocalInfo applicationInfo; - -SSD1306AsciiRenderer::SSD1306AsciiRenderer(uint8_t dimX, const uint8_t* titleFont, const uint8_t* itemFont) : BaseMenuRenderer(dimX) { - this->backChar = '<'; - this->forwardChar = '>'; - this->editChar = '='; - this->ssd1306 = nullptr; - this->fontTitle = titleFont; - this->fontItem = itemFont; -} - -SSD1306AsciiRenderer::~SSD1306AsciiRenderer() { - delete this->buffer; - delete dialog; -} - -void SSD1306AsciiRenderer::setEditorChars(char back, char forward, char edit) { - backChar = back; - forwardChar = forward; - editChar = edit; -} - -void SSD1306AsciiRenderer::renderList(uint8_t titleRows) { - auto runList = reinterpret_cast(menuMgr.getCurrentMenu()); - - uint8_t maxY = min((ssd1306->displayRows() - titleRows), runList->getNumberOfParts()); - uint8_t currentActive = runList->getActiveIndex(); - - uint8_t offset = 0; - if (currentActive >= maxY) { - offset = (currentActive+1) - maxY; - } - - for (int i = 0; i < maxY; i++) { - uint8_t current = offset + i; - RuntimeMenuItem* toDraw = (current==0) ? runList->asBackMenu() : runList->getChildItem(current - 1); - renderMenuItem(i + titleRows, toDraw); - } - - // reset the list item to a normal list again. - runList->asParent(); -} - -void SSD1306AsciiRenderer::renderTitle() { - if(menuMgr.getCurrentMenu() == menuMgr.getRoot()) { - safeProgCpy(buffer, applicationInfo.name, bufferSize); - } - else { - menuMgr.getCurrentMenu()->copyNameToBuffer(buffer, bufferSize); - } - serdebugF2("print app name", buffer); - size_t bufSz = bufferSize; - size_t last = min(bufSz, strlen(buffer)); - for(uint8_t i = last; i < bufSz; i++) { - buffer[i] = ' '; - } - buffer[bufSz] = 0; - ssd1306->setFont(fontTitle); - ssd1306->setInvertMode(true); - ssd1306->setCursor(0,0); - ssd1306->print(buffer); - ssd1306->setInvertMode(false); -} - -void SSD1306AsciiRenderer::render() { - uint8_t locRedrawMode = redrawMode; - redrawMode = MENUDRAW_NO_CHANGE; - - countdownToDefaulting(); - - ssd1306->setFont(fontTitle); - int titleRows = ssd1306->fontRows(); - if (locRedrawMode == MENUDRAW_COMPLETE_REDRAW) { - ssd1306->clear(); - renderTitle(); - taskManager.yieldForMicros(0); - } - - if (menuMgr.getCurrentMenu()->getMenuType() == MENUTYPE_RUNTIME_LIST ) { - if (menuMgr.getCurrentMenu()->isChanged() || locRedrawMode != MENUDRAW_NO_CHANGE) { - renderList(titleRows); - } - } else { - int cnt = titleRows; - MenuItem* item = menuMgr.getCurrentMenu(); - - // first we find the first currently active item in our single linked list - int activeOffs = offsetOfCurrentActive(item); - - int rowsAvailable = ssd1306->displayRows() - titleRows; - if (activeOffs >= rowsAvailable) { - uint8_t toOffsetBy = (activeOffs - rowsAvailable) + 1; - - if (lastOffset != toOffsetBy) locRedrawMode = MENUDRAW_COMPLETE_REDRAW; - lastOffset = toOffsetBy; - - while (item != nullptr && toOffsetBy) { - if(item->isVisible()) toOffsetBy = toOffsetBy - 1; - item = item->getNext(); - } - } else { - if (lastOffset != 0xff) locRedrawMode = MENUDRAW_COMPLETE_REDRAW; - lastOffset = 0xff; - } - - // and then we start drawing items until we run out of screen or items - while (item && cnt < ssd1306->displayRows()) { - if(item->isVisible()) - { - if (locRedrawMode != MENUDRAW_NO_CHANGE || item->isChanged()) { - renderMenuItem(cnt, item); - } - ++cnt; - } - item = item->getNext(); - } - } -} - -void SSD1306AsciiRenderer::renderMenuItem(uint8_t row, MenuItem* item) { - if (item == nullptr || row > ssd1306->displayRows()) return; - - item->setChanged(false); - ssd1306->setCursor(0, row); - - int offs; - if (item->getMenuType() == MENUTYPE_BACK_VALUE) { - buffer[0] = item == activeItem ? (char)backChar : ' '; - buffer[1] = (char)backChar; - offs = 2; - } - else { - buffer[0] = char(item == menuMgr.getCurrentEditor() ? editChar : (item == activeItem ? forwardChar : ' ')); - offs = 1; - } - uint8_t finalPos = item->copyNameToBuffer(buffer, offs, bufferSize); - for(uint8_t i = finalPos; i < bufferSize; ++i) buffer[i] = 32; - buffer[bufferSize] = 0; - - ssd1306->setFont(fontItem); - - if (isItemActionable(item)) { - buffer[bufferSize - 2] = (char)forwardChar; - buffer[bufferSize - 1] = 0; - ssd1306->print(buffer); - } - else { - char sz[20]; - copyMenuItemValue(item, sz, sizeof sz); - uint8_t count = strlen(sz); - if(count < 0 || count > bufferSize) { - return; - } - int cpy = (bufferSize - count) - 1; - - auto hints = menuMgr.getEditorHints(); - if(menuMgr.getCurrentEditor() && hints.getEditorRenderingType() != CurrentEditorRenderingHints::EDITOR_REGULAR && item==menuMgr.getCurrentEditor()) { - int startIndex = min(count, hints.getStartIndex()); - int endIndex = min(count, hints.getEndIndex()); - Serial.print("0"); - strncpy(buffer + cpy, sz, startIndex); - Serial.print("00"); - buffer[cpy + startIndex] = 0; - Serial.print("1"); - ssd1306->print(buffer); - Serial.print("2"); - if(startIndex != endIndex) { - ssd1306->setInvertMode(true); - Serial.print("3"); - strncpy(buffer, &sz[startIndex], endIndex - startIndex); - Serial.print("4"); - buffer[endIndex - startIndex] = 0; - ssd1306->print(buffer); - ssd1306->setInvertMode(false); - Serial.print("5"); - } - strncpy(buffer, &sz[endIndex], bufferSize); - Serial.print("6"); - buffer[bufferSize-1]=0; - ssd1306->print(buffer); - Serial.print("7"); - } else { - strcpy(buffer + cpy, sz); - buffer[bufferSize - 1] = 0; - serdebugF3("Buffer: ", row, buffer); - ssd1306->print(buffer); - } - } -} - -BaseDialog* SSD1306AsciiRenderer::getDialog() { - if(dialog == nullptr) { - dialog = new SSD1306AsciiDialog(this); - } - return dialog; -} - -// dialog - -void SSD1306AsciiDialog::internalRender(int currentValue) { - SSD1306AsciiRenderer* lcdRender = ((SSD1306AsciiRenderer*)MenuRenderer::getInstance()); - SSD1306Ascii* display = lcdRender->getDisplay(); - - if(needsDrawing == MENUDRAW_COMPLETE_REDRAW) { - display->clear(); - } - - char data[20]; - strncpy_P(data, headerPgm, sizeof(data)); - data[sizeof(data)-1]=0; - display->setFont(lcdRender->getTitleFont()); - display->setCursor(0,0); - display->print(data); - display->setCursor(0, display->fontRows()); - - display->setFont(lcdRender->getItemFont()); - display->print(lcdRender->getBuffer()); - - if(button1 != BTNTYPE_NONE) { - copyButtonText(data, 0, currentValue); - display->setCursor(0, display->displayRows() - display->fontRows()); - display->setInvertMode(currentValue == 0); - display->print(data); - display->setInvertMode(false); - } - if(button2 != BTNTYPE_NONE) { - copyButtonText(data, 1, currentValue); - display->setInvertMode(currentValue == 1); - int startX = int(lcdRender->getBufferSize() - strlen(data)) * display->fontWidth(); - display->setCursor(startX, display->displayRows() - display->fontRows()); - display->print(data); - display->setInvertMode(false); - } -} diff --git a/examples/avr/analogJoystick1306Ascii/ssd1306asciiRenderer.h b/examples/avr/analogJoystick1306Ascii/ssd1306asciiRenderer.h deleted file mode 100644 index 83ec6ac0..00000000 --- a/examples/avr/analogJoystick1306Ascii/ssd1306asciiRenderer.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - * - * NOTE: Be aware that the underlying SSD1306ascii library is GPL and linking with it will essentially make your code GPL - * - */ - -/** - * @file ssd1306ascii.h - * - * ssd1306ascii renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - * - * This plugin allows rendering to the Ssd1306Ascii library. It is a low memory ascii renderer that - * provides text based functions. - * - * LIBRARY REQUIREMENT - * This renderer is designed for use with this library: https://github.com/greiman/SSD1306Ascii - */ - -#ifndef _TCMENU_SSD1306ASCII_DRIVER -#define _TCMENU_SSD1306ASCII_DRIVER - -#include "tcMenu.h" -#include "BaseRenderers.h" -#include -#include - -/** - * A renderer that can renderer onto a LiquidCrystal display and supports the concept of single level - * sub menus, active items and editing. - */ -class SSD1306AsciiRenderer : public BaseMenuRenderer { -private: - SSD1306Ascii* ssd1306; - uint8_t backChar; - uint8_t forwardChar; - uint8_t editChar; - const uint8_t* fontTitle; - const uint8_t* fontItem; -public: - - SSD1306AsciiRenderer(uint8_t dimX, const uint8_t* titleFont, const uint8_t* itemFont); - ~SSD1306AsciiRenderer() override; - void setGraphicsDevice(SSD1306Ascii* ssd1306) { this->ssd1306 = ssd1306; } - - void render() override; - void setEditorChars(char back, char forward, char edit); - - SSD1306Ascii* getDisplay() {return ssd1306;} - BaseDialog* getDialog() override; - - const uint8_t* getItemFont() { return fontItem; } - const uint8_t* getTitleFont() { return fontTitle; } -private: - void renderTitle(); - void renderMenuItem(uint8_t row, MenuItem* item); - void renderList(uint8_t titleHeight); -}; - -class SSD1306AsciiDialog : public BaseDialog { -public: - explicit SSD1306AsciiDialog(SSD1306AsciiRenderer* renderer) { - bitWrite(flags, DLG_FLAG_SMALLDISPLAY, 0); - } -protected: - void internalRender(int currentValue) override; -}; - - -#endif // _TCMENU_SSD1306ASCII_DRIVER diff --git a/examples/avr/keyboardEthernetShield/keyboardEthernetShield.emf b/examples/avr/keyboardEthernetShield/keyboardEthernetShield.emf index 0dee4398..76399bb9 100644 --- a/examples/avr/keyboardEthernetShield/keyboardEthernetShield.emf +++ b/examples/avr/keyboardEthernetShield/keyboardEthernetShield.emf @@ -796,15 +796,14 @@ "eepromDefinition": "avr:", "authenticatorDefinition": "rom:100:6", "projectIoExpanders": [ - "mcp23017:io23017:32:2", - "deviceIO:" + "deviceIO:", + "mcp23017:io23017:32:2" ], "menuInMenuCollection": { "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] + "appIsModular": false }, "stringLists": [] } \ No newline at end of file diff --git a/examples/avr/keyboardEthernetShield/keyboardEthernetShield.ino b/examples/avr/keyboardEthernetShield/keyboardEthernetShield.ino index a2267b9a..2c50bc7f 100644 --- a/examples/avr/keyboardEthernetShield/keyboardEthernetShield.ino +++ b/examples/avr/keyboardEthernetShield/keyboardEthernetShield.ino @@ -5,9 +5,9 @@ * However, you can take the ideas from this sketch and apply them in your own designs. * * More information about matrix keyboard support: - * https://www.thecoderscorner.com/products/arduino-libraries/io-abstraction/matrix-keyboard-keypad-manager/ + * https://tcmenu.github.io/documentation/arduino-libraries//io-abstraction/matrix-keyboard-keypad-manager/ * - * Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ + * Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ */ #include "keyboardEthernetShield_menu.h" #include @@ -153,7 +153,7 @@ const char pgmPinTooShort[] PROGMEM = "Pin too short"; void CALLBACK_FUNCTION onChangePin(int /*id*/) { // Here we check if the pin that's just been entered is too short. - // Diallowing setting and showing a dialog if it is. + // Disallowing setting and showing a dialog if it is. const char* newPin = menuConnectivityChangePin.getTextValue(); if(strlen(newPin) < 4) { BaseDialog* dlg = renderer.getDialog(); diff --git a/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.cpp b/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.cpp index 766c5ef1..d7936a94 100644 --- a/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.cpp +++ b/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.cpp @@ -8,6 +8,8 @@ use elsewhere. */ +// Generated for Arduino AVR/Uno/Mega by TcMenu 4.3.1 on 2024-10-12T10:53:14.650442600Z. + #include #include "keyboardEthernetShield_menu.h" @@ -114,8 +116,8 @@ void setupMenu() { authManager.initialise(menuMgr.getEepromAbstraction(), 100); menuMgr.setAuthenticator(&authManager); // Now add any readonly, non-remote and visible flags. - menuConnectivityAuthenticator.setLocalOnly(true); menuConnectivityIoTMonitor.setLocalOnly(true); + menuConnectivityAuthenticator.setLocalOnly(true); menuConnectivity.setLocalOnly(true); menuConnectivity.setSecured(true); menuHiddenItem.setVisible(false); diff --git a/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.h b/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.h index b4d9e04f..ee3485de 100644 --- a/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.h +++ b/examples/avr/keyboardEthernetShield/keyboardEthernetShield_menu.h @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/examples/avr/nokia5110/ThemeMonoInverse.h b/examples/avr/nokia5110/ThemeMonoInverse.h deleted file mode 100644 index 5a6e694a..00000000 --- a/examples/avr/nokia5110/ThemeMonoInverse.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TCMENU_THEME_MONO_INVERSE -#define TCMENU_THEME_MONO_INVERSE - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; -color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; - -#define TITLE_PADDING 1 -#define TITLE_SPACING 1 - -void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 2); - - MenuPadding titlePadding(TITLE_PADDING); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_INVERSE \ No newline at end of file diff --git a/examples/avr/nokia5110/ThemeMonoInverseBuilder.h b/examples/avr/nokia5110/ThemeMonoInverseBuilder.h new file mode 100644 index 00000000..1ef2d8a6 --- /dev/null +++ b/examples/avr/nokia5110/ThemeMonoInverseBuilder.h @@ -0,0 +1,60 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; +color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; + +#define TITLE_PADDING 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoInverseTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 2) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(defaultTitlePaletteMono) + .withPadding(MenuPadding(TITLE_PADDING)) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/avr/nokia5110/nokia5110_menu.cpp b/examples/avr/nokia5110/nokia5110_menu.cpp index ce28171c..8a5bc55a 100644 --- a/examples/avr/nokia5110/nokia5110_menu.cpp +++ b/examples/avr/nokia5110/nokia5110_menu.cpp @@ -8,9 +8,11 @@ use elsewhere. */ +// Generated for Arduino AVR/Uno/Mega by TcMenu 4.3.1 on 2024-10-12T11:00:32.353851500Z. + #include #include "nokia5110_menu.h" -#include "ThemeMonoInverse.h" +#include "ThemeMonoInverseBuilder.h" // Global variable declarations const PROGMEM ConnectorLocalInfo applicationInfo = { "Security App", "0e68e7f6-2932-43f0-aae3-d4f885b7561d" }; @@ -77,7 +79,7 @@ void setupMenu() { menuConnectivity.setLocalOnly(true); menuConnectivity.setSecured(true); - // Code generated by plugins. + // Code generated by plugins and new operators. gfx.begin(); gfx.setRotation(0); renderer.setUpdatesPerSecond(4); @@ -85,9 +87,7 @@ void setupMenu() { switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); menuMgr.initForEncoder(&renderer, &menuHall, 2, 3, 4); remoteServer.addConnection(ðernetConnection); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(false); - installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true); + installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true, BaseGraphicalRenderer::TITLE_FIRST_ROW, false); // We have an IoT monitor, register the server menuIoTMonitor.setRemoteServer(remoteServer); diff --git a/examples/avr/nokia5110/securitySystem.emf b/examples/avr/nokia5110/securitySystem.emf index 47919f5f..06513800 100644 --- a/examples/avr/nokia5110/securitySystem.emf +++ b/examples/avr/nokia5110/securitySystem.emf @@ -299,7 +299,7 @@ "lastRemoteUuids": [ "0877131c-e03e-426b-8eaf-228e01f5e7f1" ], - "lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0", + "lastThemeUuid": "396ED4DF-AD7B-4951-A848-A9E5838A549B", "applicationUUID": "0e68e7f6-2932-43f0-aae3-d4f885b7561d", "applicationName": "Security App", "lastProperties": [ diff --git a/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.cpp b/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.cpp index 53c5871a..fb0d42eb 100644 --- a/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.cpp +++ b/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.cpp @@ -26,7 +26,6 @@ void AdafruitDrawable::transaction(bool isStarting, bool redrawNeeded) { } void AdafruitDrawable::internalDrawText(const Coord &where, const void *font, int mag, const char *sz) { - graphics->setTextWrap(false); int baseline=0; Coord exts = textExtents(font, mag, "(;y", &baseline); int yCursor = font ? (where.y + (exts.y - baseline)) : where.y; diff --git a/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.h b/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.h index d18be3c1..186e5d81 100644 --- a/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.h +++ b/examples/avr/nokia5110/tcMenuAdaFruitGfxMono.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -93,6 +92,7 @@ class AdafruitDrawable : public DeviceDrawable { int16_t computedBaseline = 0; int16_t computedHeight = 0; public: + explicit AdafruitDrawable() : graphics(nullptr) {} explicit AdafruitDrawable(Adafruit_GFX* graphics, int spriteHeight = 0) : graphics(graphics) { setSubDeviceType(NO_SUB_DEVICE); } @@ -113,11 +113,9 @@ class AdafruitDrawable : public DeviceDrawable { Coord internalTextExtents(const void *font, int mag, const char *text, int *baseline) override; void drawPixel(uint16_t x, uint16_t y) override; Adafruit_GFX* getGfx() { return graphics; } + void setGraphics(Adafruit_GFX* gfx) { graphics = gfx; } protected: void computeBaselineIfNeeded(const GFXfont* font); - explicit AdafruitDrawable() : graphics(nullptr) {} - void setGraphics(Adafruit_GFX* gfx) { graphics = gfx; } - UnicodeFontHandler *createFontHandler() override; }; diff --git a/examples/esp/esp32Amplifier/ClientEthernetTransport.h b/examples/esp/esp32Amplifier/ClientEthernetTransport.h index 13c132a3..986e90b4 100644 --- a/examples/esp/esp32Amplifier/ClientEthernetTransport.h +++ b/examples/esp/esp32Amplifier/ClientEthernetTransport.h @@ -25,7 +25,7 @@ #endif // ETHERNET_BUFFER_SIZE #ifndef DEFAULT_BACKOFF_PERIOD -#define DEFAULT_BACKOFF_PERIOD (4 * (1000 / TICK_INTERVAL)) +#define DEFAULT_BACKOFF_PERIOD HEARTBEAT_INTERVAL #endif // DEFAULT_BACKOFF_PERIOD #include diff --git a/examples/esp/esp32Amplifier/esp32Amplifier.emf b/examples/esp/esp32Amplifier/esp32Amplifier.emf index e19c8b12..0643c8cd 100644 --- a/examples/esp/esp32Amplifier/esp32Amplifier.emf +++ b/examples/esp/esp32Amplifier/esp32Amplifier.emf @@ -612,17 +612,22 @@ "subsystem": "INPUT" }, { - "name": "ETH_LIBRARY_TYPE", + "name": "CLIP_ETH_LIBRARY_TYPE", "latestValue": "ESP32_WIFI", "subsystem": "REMOTE" }, { - "name": "REMOTE_IP_ADDRESS", - "latestValue": "192.168.0.37", + "name": "CLIP_ADDR_TYPE", + "latestValue": "variable", "subsystem": "REMOTE" }, { - "name": "REMOTE_PORT", + "name": "CLIP_REMOTE_ADDRESS", + "latestValue": "myIpAddress", + "subsystem": "REMOTE" + }, + { + "name": "CLIP_REMOTE_PORT", "latestValue": "3333", "subsystem": "REMOTE" }, @@ -675,8 +680,7 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] + "appIsModular": false }, "stringLists": [] } \ No newline at end of file diff --git a/examples/esp/esp32Amplifier/esp32Amplifier.ino b/examples/esp/esp32Amplifier/esp32Amplifier.ino index bf4bdedf..389adbfc 100644 --- a/examples/esp/esp32Amplifier/esp32Amplifier.ino +++ b/examples/esp/esp32Amplifier/esp32Amplifier.ino @@ -9,7 +9,7 @@ * * Screen setup for 320x240 LANDSCAPE. * - * https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ + * https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/tcmenu-overview-quick-start/ */ #include @@ -30,12 +30,16 @@ using namespace tcremote; using namespace iotouch; +//define the address for the remote connection +const char* myIpAddress = "192.168.0.99"; + const char pgmVersionHeader[] PROGMEM = "tcMenu Version"; bool connectedToWifi = false; TitleWidget wifiWidget(iconsWifi, 5, 16, 12, nullptr); AmplifierController controller; +// we create a runtime list menu item further down and it uses these as the possible values to display. const char* simFilesForList[] = { "SuperFile1.txt", "CustomFile.cpp", "SuperDuper.h", "File303.cpp", "File123443.h", "Another.file", "TestMe.txt", "Program.txt" }; #define SIM_FILES_ARRAY_SIZE 8 @@ -43,15 +47,15 @@ const char* simFilesForList[] = { "SuperFile1.txt", "CustomFile.cpp", "SuperDup void prepareWifiForUse(); void setup() { + // Start up the devices and services that we need, these may change depending on board etc. SPI.setFrequency(20000000); SPI.begin(); Serial.begin(115200); EEPROM.begin(512); + // if needed you can enable extra logging //serEnableLevel(SER_TCMENU_DEBUG, true); - renderer.setFirstWidget(&wifiWidget); - setupMenu(); menuMgr.load(MENU_MAGIC_KEY, [] { @@ -136,9 +140,13 @@ void setup() { .withBorder(MenuBorder(2)) .apply(); + // now we add our title widget for the wifi strength + themeBuilder.addingTitleWidget(wifiWidget); + // whenever adjusting themes, we should always apply them themeBuilder.apply(); + // and finally provide a dialog that appears upon selecting the title setTitlePressedCallback([](int) { BaseDialog* dlg = MenuRenderer::getInstance()->getDialog(); if(!dlg || dlg->isInUse()) return; diff --git a/examples/esp/esp32Amplifier/esp32Amplifier_menu.cpp b/examples/esp/esp32Amplifier/esp32Amplifier_menu.cpp index 11124734..46bff69c 100644 --- a/examples/esp/esp32Amplifier/esp32Amplifier_menu.cpp +++ b/examples/esp/esp32Amplifier/esp32Amplifier_menu.cpp @@ -8,7 +8,7 @@ use elsewhere. */ -// Generated for Arduino ESP32 by TcMenu 4.3.1-SNAPSHOT on 2024-08-31T08:17:44.237948Z. +// Generated for Arduino ESP32 by TcMenu 4.3.1 on 2024-09-28T08:52:55.511970600Z. #include #include "esp32Amplifier_menu.h" @@ -26,7 +26,7 @@ iotouch::ResistiveTouchInterrogator touchInterrogator(2, 33, 32, 0); iotouch::TouchOrientationSettings touchOrientation(true, false, true); MenuTouchScreenManager touchScreen(&touchInterrogator, &renderer, touchOrientation); tcextras::IoaTouchScreenCalibrator touchCalibrator(&touchScreen, &renderer, 400); -ClientEthernetInitialisation clientEthInit("192.168.0.37", 3333); +ClientEthernetInitialisation clientEthInit(myIpAddress, 3333); ClientEthernetTagValTransport clientEthTransport; TagValueRemoteServerConnection clientConnection(clientEthTransport, clientEthInit); @@ -103,8 +103,8 @@ void setupMenu() { menuMgr.setAuthenticator(&authManager); // Now add any readonly, non-remote and visible flags. menuConnectivityIPAddress.setReadOnly(true); - menuConnectivityIoTMonitor.setLocalOnly(true); menuConnectivityAuthenticator.setLocalOnly(true); + menuConnectivityIoTMonitor.setLocalOnly(true); // Code generated by plugins and new operators. tft.begin(); diff --git a/examples/esp/esp32Amplifier/esp32Amplifier_menu.h b/examples/esp/esp32Amplifier/esp32Amplifier_menu.h index 0690c9e1..5e1fc676 100644 --- a/examples/esp/esp32Amplifier/esp32Amplifier_menu.h +++ b/examples/esp/esp32Amplifier/esp32Amplifier_menu.h @@ -35,6 +35,7 @@ extern GraphicsDeviceRenderer renderer; extern iotouch::ResistiveTouchInterrogator touchInterrogator; extern MenuTouchScreenManager touchScreen; extern tcextras::IoaTouchScreenCalibrator touchCalibrator; +extern const char* myIpAddress; extern ClientEthernetInitialisation clientEthInit; extern ClientEthernetTagValTransport clientEthTransport; diff --git a/examples/esp/esp32SimHub/generated/SimhubConnector.cpp b/examples/esp/esp32SimHub/SimhubConnector.cpp similarity index 100% rename from examples/esp/esp32SimHub/generated/SimhubConnector.cpp rename to examples/esp/esp32SimHub/SimhubConnector.cpp diff --git a/examples/esp/esp32SimHub/generated/SimhubConnector.h b/examples/esp/esp32SimHub/SimhubConnector.h similarity index 100% rename from examples/esp/esp32SimHub/generated/SimhubConnector.h rename to examples/esp/esp32SimHub/SimhubConnector.h diff --git a/examples/esp/esp32SimHub/ThemeCoolBlueTraditionalBuilder.h b/examples/esp/esp32SimHub/ThemeCoolBlueTraditionalBuilder.h new file mode 100644 index 00000000..8553b9ed --- /dev/null +++ b/examples/esp/esp32SimHub/ThemeCoolBlueTraditionalBuilder.h @@ -0,0 +1,79 @@ +/** + * Cool blue traditional theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. + * This file will not be updated by the designer, you can edit. + * See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/themes/rendering-with-themes-icons-grids/ + */ + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE + +#include + +// +// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() +// + +// tcMenu drawing properties take a 4 color palette for items, titles and actions. +// this renderer shares the color configuration for items and actions. +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + * @param titleMode the way that the title should be drawn (choose from the enum values) + * @param useUnicode if using tcUnicode drawing functions + */ +void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + bool medResOrBetter = gr.getWidth() > 160; + MenuPadding titlePadding(medResOrBetter ? 4 : 2); + MenuPadding itemPadding(medResOrBetter ? 2 : 1); + + themeBuilder.dimensionsFromRenderer() + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) + .withItemPadding(itemPadding) + .withTitlePadding(titlePadding) + .withRenderingSettings(titleMode, false) + .withPalette(coolBlueItemPalette) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + if(medResOrBetter) { + themeBuilder.withStandardMedResCursorIcons(); + } else { + themeBuilder.withStandardLowResCursorIcons(); + } + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultItemProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.defaultTitleProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(coolBlueTitlePalette) + .withSpacing(medResOrBetter ? 3 : 1) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //THEME_COOL_BLUE diff --git a/examples/esp/esp32SimHub/appTheme.cpp b/examples/esp/esp32SimHub/appTheme.cpp index e5a0c559..a3d10b41 100644 --- a/examples/esp/esp32SimHub/appTheme.cpp +++ b/examples/esp/esp32SimHub/appTheme.cpp @@ -1,7 +1,7 @@ // To use palette and size constants we need to use tcgfx types #include #include -#include "generated/esp32SimHub_menu.h" +#include "esp32SimHub_menu.h" using namespace tcgfx; @@ -115,46 +115,12 @@ const uint8_t engineBitmap0[] PROGMEM = { }; void setupTheme() { - /** - * In the event that we want to modify how menu items are drawn, the easiest way is to use TcThemeBuilder. - * Here we use it to modify the drawing of certain menu items, we want three of the main menu items to render - * using icons, to do so we call `menuItemOverride` on the builder, and it returns a "properties builder" that is - * pre-prepared to adjust the menu item. - * - * See https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ - */ - color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; - color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; TcThemeBuilder themeBuilder(renderer); - themeBuilder.withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) - .dimensionsFromRenderer() - .withRenderingSettings(tcgfx::BaseGraphicalRenderer::TITLE_FIRST_ROW, true) - .enablingTcUnicode() - .withItemPadding(MenuPadding(2)) - .withTitlePadding(MenuPadding(1)) - .withStandardMedResCursorIcons() - .withPalette(coolBlueItemPalette) - .withAdaFont(&FreeSans9pt7b) - .withSpacing(1); - - themeBuilder.defaultTitleProperties() - .withPalette(coolBlueTitlePalette) - .withAdaFont(&FreeSans12pt7b) - .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) - .apply(); - themeBuilder.defaultItemProperties() - .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) - .apply(); - themeBuilder.defaultActionProperties() - .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) - .apply(); - themeBuilder.menuItemOverride(menuEngine) .onRowCol(3, 1, 1) .withImage4bpp(Coord(64, 64), engineBitmap_palette0, engineBitmap0) .apply(); themeBuilder.apply(); - } \ No newline at end of file diff --git a/examples/esp/esp32SimHub/dashboardSetup.cpp b/examples/esp/esp32SimHub/dashboardSetup.cpp index 60d9b235..f08e7ce0 100644 --- a/examples/esp/esp32SimHub/dashboardSetup.cpp +++ b/examples/esp/esp32SimHub/dashboardSetup.cpp @@ -1,7 +1,13 @@ - +/* + * This file demonstrates the full use of the dashboard support built into TcMenu core, you can easily create and layout + * your own dashboards. + * + * https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/renderer-take-over-display/#3-using-the-drawabledashboard-to-draw-a-dashboard + */ #include "dashboardSetup.h" #include "Fonts/RobotoMonoBold60pt.h" #include +#include DrawableDashboard* dashCustomDrawing; CustomDashboardDelegate dashboardDelegate; diff --git a/examples/esp/esp32SimHub/dashboardSetup.h b/examples/esp/esp32SimHub/dashboardSetup.h index a8059131..0d715652 100644 --- a/examples/esp/esp32SimHub/dashboardSetup.h +++ b/examples/esp/esp32SimHub/dashboardSetup.h @@ -2,7 +2,7 @@ #define TCLIBRARYDEV_DASHBOARDSETUP_H #include -#include "generated/esp32SimHub_menu.h" +#include "esp32SimHub_menu.h" #include #define LED_STATES 10 diff --git a/examples/esp/esp32SimHub/esp32SimHub.emf b/examples/esp/esp32SimHub/esp32SimHub.emf index 0ade9f97..ddfa6806 100644 --- a/examples/esp/esp32SimHub/esp32SimHub.emf +++ b/examples/esp/esp32SimHub/esp32SimHub.emf @@ -355,7 +355,7 @@ "lastRemoteUuids": [ "4123dfc3-5271-4727-81f0-1a21d06b666b" ], - "lastThemeUuid": "03c6b25f-db63-402a-8447-a5ce1484c14d", + "lastThemeUuid": "57945787-0A04-447B-BBA2-6461FC505397", "applicationUUID": "4db9fbfe-9fab-4759-b8ff-3e0c6700f475", "applicationName": "SimHub Link", "lastProperties": [ @@ -496,22 +496,17 @@ }, { "name": "ITEM_FONT", - "latestValue": "ada:FreeSans9pt7b,1", + "latestValue": "ada:OpenSansCyrillicLatin14,0", "subsystem": "THEME" }, { "name": "TITLE_FONT", - "latestValue": "ada:FreeSans12pt7b,1", - "subsystem": "THEME" - }, - { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", + "latestValue": "ada:OpenSansCyrillicLatin18,0", "subsystem": "THEME" }, { "name": "TITLE_SHOW_MODE", - "latestValue": "TITLE_FIRST_ROW", + "latestValue": "TITLE_ALWAYS", "subsystem": "THEME" }, { @@ -519,11 +514,6 @@ "latestValue": "true", "subsystem": "THEME" }, - { - "name": "USE_SLIDER_ANALOG", - "latestValue": "true", - "subsystem": "THEME" - }, { "name": "NEED_EDITING_ICONS", "latestValue": "true", @@ -532,7 +522,7 @@ ], "namingRecursive": true, "useCppMain": false, - "saveLocation": "PROJECT_TO_CURRENT_WITH_GENERATED", + "saveLocation": "ALL_TO_CURRENT", "usingSizedEEPROMStorage": false, "eepromDefinition": "", "authenticatorDefinition": "", @@ -543,7 +533,8 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false + "appIsModular": false, + "listOfEmbeddedForms": [] }, "stringLists": [] } \ No newline at end of file diff --git a/examples/esp/esp32SimHub/esp32SimHub.ino b/examples/esp/esp32SimHub/esp32SimHub.ino index d45bfe7d..74e3e137 100644 --- a/examples/esp/esp32SimHub/esp32SimHub.ino +++ b/examples/esp/esp32SimHub/esp32SimHub.ino @@ -31,7 +31,7 @@ */ #include -#include "generated/esp32SimHub_menu.h" +#include "esp32SimHub_menu.h" #include #include #include @@ -223,9 +223,6 @@ void CALLBACK_FUNCTION onShowDialogs(int id) { } } - - void CALLBACK_FUNCTION onEngineHasChanged(int id) { // TODO - your menu change code } - diff --git a/examples/esp/esp32SimHub/generated/esp32SimHub_menu.cpp b/examples/esp/esp32SimHub/esp32SimHub_menu.cpp similarity index 93% rename from examples/esp/esp32SimHub/generated/esp32SimHub_menu.cpp rename to examples/esp/esp32SimHub/esp32SimHub_menu.cpp index df0b936e..ec0c5735 100644 --- a/examples/esp/esp32SimHub/generated/esp32SimHub_menu.cpp +++ b/examples/esp/esp32SimHub/esp32SimHub_menu.cpp @@ -8,10 +8,13 @@ use elsewhere. */ +// Generated for Arduino ESP32 by TcMenu 4.3.1 on 2024-09-28T16:58:40.173767400Z. + #include #include "esp32SimHub_menu.h" -#include -#include +#include "ThemeCoolBlueTraditionalBuilder.h" +#include +#include // Global variable declarations const PROGMEM ConnectorLocalInfo applicationInfo = { "SimHub Link", "4db9fbfe-9fab-4759-b8ff-3e0c6700f475" }; @@ -79,7 +82,7 @@ void setupMenu() { menuTyreTemp.setReadOnly(true); menuRPM.setReadOnly(true); - // Code generated by plugins. + // Code generated by plugins and new operators. gfx.begin(); gfx.setRotation(1); renderer.setUpdatesPerSecond(5); @@ -88,6 +91,7 @@ void setupMenu() { menuMgr.initFor4WayJoystick(&renderer, &menuSpeed, 7, 5, 2, 6, -1, 35); esp32Touch.ensureInterruptRegistered(); remoteServer.addConnection(&simhubConnection); + installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin14, 0), MenuFontDef(&OpenSansCyrillicLatin18, 0), true, BaseGraphicalRenderer::TITLE_ALWAYS, true); // We have an IoT monitor, register the server menuSettingsIoTMonitor.setRemoteServer(remoteServer); diff --git a/examples/esp/esp32SimHub/generated/esp32SimHub_menu.h b/examples/esp/esp32SimHub/esp32SimHub_menu.h similarity index 96% rename from examples/esp/esp32SimHub/generated/esp32SimHub_menu.h rename to examples/esp/esp32SimHub/esp32SimHub_menu.h index 354792ba..119224a5 100644 --- a/examples/esp/esp32SimHub/generated/esp32SimHub_menu.h +++ b/examples/esp/esp32SimHub/esp32SimHub_menu.h @@ -30,8 +30,8 @@ extern Adafruit_ILI9341 gfx; extern AdafruitDrawable gfxDrawable; extern GraphicsDeviceRenderer renderer; extern ESP32TouchKeysAbstraction esp32Touch; -extern const GFXfont FreeSans9pt7b; -extern const GFXfont FreeSans12pt7b; +extern const UnicodeFont OpenSansCyrillicLatin14[]; +extern const UnicodeFont OpenSansCyrillicLatin18[]; // Any externals needed by IO expanders, EEPROMs etc diff --git a/examples/esp/esp32SimHub/generated/tcMenuAdaFruitGfx.cpp b/examples/esp/esp32SimHub/tcMenuAdaFruitGfx.cpp similarity index 99% rename from examples/esp/esp32SimHub/generated/tcMenuAdaFruitGfx.cpp rename to examples/esp/esp32SimHub/tcMenuAdaFruitGfx.cpp index 208f2944..ca30a823 100644 --- a/examples/esp/esp32SimHub/generated/tcMenuAdaFruitGfx.cpp +++ b/examples/esp/esp32SimHub/tcMenuAdaFruitGfx.cpp @@ -100,6 +100,7 @@ void AdafruitDrawable::drawBitmapNbpp(const Coord& where, const uint8_t* data, c asTft->writePixels(memBuffer, next); next = 0; } + byteIteration = bitsInByte; // always need a new byte in this case } asTft->endWrite(); @@ -622,5 +623,6 @@ void AdafruitCanvasDrawable2bpp::drawBitmapNbpp(const Coord& where, const uint8_ byteIteration++; canvas->drawPixel(x, y, idx); } + byteIteration = bitsInByte; // always need a new byte in this case } } \ No newline at end of file diff --git a/examples/esp/esp32SimHub/generated/tcMenuAdaFruitGfx.h b/examples/esp/esp32SimHub/tcMenuAdaFruitGfx.h similarity index 99% rename from examples/esp/esp32SimHub/generated/tcMenuAdaFruitGfx.h rename to examples/esp/esp32SimHub/tcMenuAdaFruitGfx.h index 6a00433a..9366022c 100644 --- a/examples/esp/esp32SimHub/generated/tcMenuAdaFruitGfx.h +++ b/examples/esp/esp32SimHub/tcMenuAdaFruitGfx.h @@ -213,7 +213,7 @@ class AdafruitCanvasDrawable2bpp : public AdafruitDrawable { void transaction(bool isStarting, bool redrawNeeded) override; color_t getUnderlyingColor(color_t col) override; DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord &size, const color_t *palette, int paletteSize) override; - void drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const uint16_t* palette) override; + void drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette) override; }; #endif /* _TCMENU_TCMENUADAFRUITGFX_H_ */ diff --git a/examples/esp/esp32s2Saola/esp32s2Saola.ino b/examples/esp/esp32s2Saola/esp32s2Saola.ino index 31975823..0c083da9 100644 --- a/examples/esp/esp32s2Saola/esp32s2Saola.ino +++ b/examples/esp/esp32s2Saola/esp32s2Saola.ino @@ -2,7 +2,7 @@ // ESP32 S2 example based on Saola board with a dashboard configuration onto an OLED display // I2C on standard pin, 8 and 9 with an SH1106 display // encoder on 5, 6 with button on 7 -// Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ +// Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ // #include "generated/esp32s2Saola_menu.h" @@ -22,11 +22,11 @@ void startWiFiAndListener(); // we add two widgets that show both the connection status and wifi signal strength // these are added to the renderer and rendered upon any change. -// https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/#titlewidget-for-presenting-state-in-icon-form +// https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/rendering-with-tcmenu-lcd-tft-oled TitleWidget wifiWidget(iconsWifi, 5, 16, 12); void setup() { - // before proceeding we must start wire and serial, then call setup menu. + // before proceeding, we must start wire and serial, then call setup menu. Serial.begin(115200); serdebugF("Starting ESP32-S2 example"); Wire.begin(); @@ -110,8 +110,8 @@ void CALLBACK_FUNCTION pressMeActionRun(int id) { // This callback needs to be implemented by you, see the below docs: -// 1. List Docs - https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/list-menu-item/ -// 2. ScrollChoice Docs - https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/menu-item-types/scrollchoice-menu-item/ +// 1. List Docs - https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/menu-item-types/list-menu-item/ +// 2. ScrollChoice Docs - https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/menu-item-types/scrollchoice-menu-item/ int CALLBACK_FUNCTION fnExtrasMyListRtCall(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize) { if(mode == RENDERFN_VALUE && row != LIST_PARENT_ITEM_POS) { strncpy(buffer, "Val", bufferSize); diff --git a/examples/esp/esp32s2Saola/generated/esp32s2Saola_menu.cpp b/examples/esp/esp32s2Saola/generated/esp32s2Saola_menu.cpp index cfeadb83..983fce7f 100644 --- a/examples/esp/esp32s2Saola/generated/esp32s2Saola_menu.cpp +++ b/examples/esp/esp32s2Saola/generated/esp32s2Saola_menu.cpp @@ -8,7 +8,7 @@ use elsewhere. */ -// Generated for Arduino ESP32 by TcMenu 4.3.1-SNAPSHOT on 2024-08-26T12:55:56.108558600Z. +// Generated for Arduino ESP32 by TcMenu 4.3.1 on 2024-09-28T18:27:34.834990800Z. #include #include "esp32s2Saola_menu.h" diff --git a/examples/esp/esp32s3TftEncoder/ThemeCoolBlueTraditional.h b/examples/esp/esp32s3TftEncoder/ThemeCoolBlueTraditional.h deleted file mode 100644 index 7c249b90..00000000 --- a/examples/esp/esp32s3TftEncoder/ThemeCoolBlueTraditional.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -// -// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() -// - -// tcMenu drawing properties take a 4 color palette for items, titles and actions. -// this renderer shares the color configuration for items and actions. -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; - -void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // first we keep a reference to the screen size, and set the dimensions on the renderer. - auto width = bgr.getDeviceDrawable()->getDisplayDimensions().x; - auto height = bgr.getDeviceDrawable()->getDisplayDimensions().y; - bgr.setDisplayDimensions(width, height); - - // get hold of the item display factory that holds the drawing configuration. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // when an item is active, it will show in these colours instead of the default. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // here we calculate the item padding and row heights based on the resolution of the display - bool medResOrBetter = width > 160; - MenuPadding titlePadding(medResOrBetter ? 4 : 2); - MenuPadding itemPadding(medResOrBetter ? 2 : 1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - // we set the editing and selected icons here based on the row height. - if(needEditingIcons && itemHeight > 12) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defActiveIcon)); - } - else if(needEditingIcons) { - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - } - - // we tell the library how to draw titles, items and actions by default. - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, titlePadding, titleFont.fontData, titleFont.fontMag, - medResOrBetter ? 3 : 1, titleHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); - - // after adjusting the drawing configuration, we must always refresh the cache. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE diff --git a/examples/esp/esp32s3TftEncoder/ThemeCoolBlueTraditionalBuilder.h b/examples/esp/esp32s3TftEncoder/ThemeCoolBlueTraditionalBuilder.h new file mode 100644 index 00000000..8553b9ed --- /dev/null +++ b/examples/esp/esp32s3TftEncoder/ThemeCoolBlueTraditionalBuilder.h @@ -0,0 +1,79 @@ +/** + * Cool blue traditional theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. + * This file will not be updated by the designer, you can edit. + * See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/themes/rendering-with-themes-icons-grids/ + */ + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE + +#include + +// +// Note only include this file ONCE, in a CPP file. We do this automatically when using a Theme by adding to setupMenu() +// + +// tcMenu drawing properties take a 4 color palette for items, titles and actions. +// this renderer shares the color configuration for items and actions. +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + * @param titleMode the way that the title should be drawn (choose from the enum values) + * @param useUnicode if using tcUnicode drawing functions + */ +void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + bool medResOrBetter = gr.getWidth() > 160; + MenuPadding titlePadding(medResOrBetter ? 4 : 2); + MenuPadding itemPadding(medResOrBetter ? 2 : 1); + + themeBuilder.dimensionsFromRenderer() + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) + .withItemPadding(itemPadding) + .withTitlePadding(titlePadding) + .withRenderingSettings(titleMode, false) + .withPalette(coolBlueItemPalette) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + if(medResOrBetter) { + themeBuilder.withStandardMedResCursorIcons(); + } else { + themeBuilder.withStandardLowResCursorIcons(); + } + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultItemProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.defaultTitleProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(coolBlueTitlePalette) + .withSpacing(medResOrBetter ? 3 : 1) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //THEME_COOL_BLUE diff --git a/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.emf b/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.emf index 8b2c9b6c..b53bb4f8 100644 --- a/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.emf +++ b/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.emf @@ -233,12 +233,12 @@ ], "codeOptions": { "embeddedPlatform": "ARDUINO32", - "lastDisplayUuid": "e6342680-6fab-4d1b-ac08-ce8dbfc0974c", + "lastDisplayUuid": "4dcb12ec-13d8-4466-b8b6-bd575eae4612", "lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87", "lastRemoteUuids": [ "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" ], - "lastThemeUuid": "03c6b25f-db63-402a-8447-a5ce1484c14d", + "lastThemeUuid": "57945787-0A04-447B-BBA2-6461FC505397", "applicationUUID": "c035e186-32cc-45e4-ac28-773f57e108ee", "applicationName": "ESP32 S3 Tiny", "lastProperties": [ @@ -248,78 +248,63 @@ "subsystem": "DISPLAY" }, { - "name": "DISPLAY_ROTATION", - "latestValue": "1", - "subsystem": "DISPLAY" - }, - { - "name": "DOUBLE_BUFFER_ROWS", - "latestValue": "64", - "subsystem": "DISPLAY" - }, - { - "name": "UPDATES_PER_SEC", - "latestValue": "15", - "subsystem": "DISPLAY" - }, - { - "name": "TOUCH_SEPARATOR", - "latestValue": "", + "name": "DISPLAY_TYPE", + "latestValue": "Adafruit_ST7735", "subsystem": "DISPLAY" }, { - "name": "TFT_TOUCH_SCREEN_REQUIRED", - "latestValue": "false", + "name": "DISPLAY_WIDTH", + "latestValue": "128", "subsystem": "DISPLAY" }, { - "name": "TOUCH_CALIB_WIDTH", - "latestValue": "240", + "name": "DISPLAY_HEIGHT", + "latestValue": "128", "subsystem": "DISPLAY" }, { - "name": "TOUCH_CALIB_HEIGHT", - "latestValue": "320", + "name": "DISPLAY_RESET_PIN", + "latestValue": "6", "subsystem": "DISPLAY" }, { - "name": "TOUCH_USE_RAW_TFT_FUNCTION", - "latestValue": "true", + "name": "DISPLAY_CS_PIN", + "latestValue": "34", "subsystem": "DISPLAY" }, { - "name": "ORIENTATION_SEPARATOR", - "latestValue": "", + "name": "DISPLAY_RS_PIN", + "latestValue": "7", "subsystem": "DISPLAY" }, { - "name": "TFT_TOUCH_SWAP_XY", - "latestValue": "false", + "name": "DISPLAY_DATA_PIN", + "latestValue": "-1", "subsystem": "DISPLAY" }, { - "name": "TFT_TOUCH_X_INVERTED", - "latestValue": "false", + "name": "DISPLAY_CLOCK_PIN", + "latestValue": "-1", "subsystem": "DISPLAY" }, { - "name": "TFT_TOUCH_Y_INVERTED", - "latestValue": "false", + "name": "ST7735_TAB_TYPE", + "latestValue": "INITR_GREENTAB", "subsystem": "DISPLAY" }, { - "name": "CALIB_SEPARATOR", - "latestValue": "", + "name": "DISPLAY_ROTATION", + "latestValue": "0", "subsystem": "DISPLAY" }, { - "name": "TFT_TOUCH_SCREEN_CALIBRATE", - "latestValue": "true", + "name": "UPDATES_PER_SEC", + "latestValue": "15", "subsystem": "DISPLAY" }, { - "name": "TFT_TOUCH_CALIBRATION_STORAGE_LOC", - "latestValue": "400", + "name": "DISPLAY_BUFFER_SIZE", + "latestValue": "40", "subsystem": "DISPLAY" }, { @@ -369,17 +354,12 @@ }, { "name": "ITEM_FONT", - "latestValue": "ada:OpenSansCyrillicLatin12,0", + "latestValue": "ada:OpenSansRegular8pt,0", "subsystem": "THEME" }, { "name": "TITLE_FONT", - "latestValue": "ada:OpenSansCyrillicLatin12,0", - "subsystem": "THEME" - }, - { - "name": "BORDER_FOR_ACTIONS", - "latestValue": "0", + "latestValue": "ada:OpenSansRegular10pt,0", "subsystem": "THEME" }, { @@ -392,11 +372,6 @@ "latestValue": "true", "subsystem": "THEME" }, - { - "name": "USE_SLIDER_ANALOG", - "latestValue": "true", - "subsystem": "THEME" - }, { "name": "NEED_EDITING_ICONS", "latestValue": "true", diff --git a/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.ino b/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.ino index 1e4c399f..9e86e358 100644 --- a/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.ino +++ b/examples/esp/esp32s3TftEncoder/esp32s3TftEncoder.ino @@ -1,7 +1,11 @@ // This example shows a simple menu structure with a card layout for the root menu on a TFT. Very simple case of -// TFT_eSPI for the display, encoder directly connected to device pins. +// Adafruit GFX ST7735 driver for the display, encoder directly connected to device pins. +// We have connected the following way, you can adjust as needed in code generator / sketch +// TFT_DC: 7 MISO: 37 PIN_A: 3 +// TFT_CS: 34 MOSI: 35 PIN_B: 4 +// TFT_RST: 6 SCLK: 36 PIN_OK: 5 // -// Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ +// Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ #include "generated/esp32s3TftEncoder_menu.h" #include "stockIcons/directionalIcons.h" @@ -9,6 +13,8 @@ #include "tcMenuVersion.h" #include #include +#include +#include // // We use a card layout to present the items, here we demonstrate how to set it up and prepare custom menu items that @@ -16,42 +22,55 @@ // // START card layout and custom layout code -// first we need to define both a left and right button, we use the ones from stockIcons/directionalIcons.h -DrawableIcon iconLeft(-1, Coord(11, 22), tcgfx::DrawableIcon::ICON_XBITMAP, ArrowHoriz11x22BitmapLeft, nullptr); -DrawableIcon iconRight(-1, Coord(11, 22), tcgfx::DrawableIcon::ICON_XBITMAP, ArrowHoriz11x22BitmapRight, nullptr); - TitleWidget titleWidget(iconsEthernetConnection, 2, 16, 12); +// +// This example uses card layout for the main menu, this means that one item shows at a time, as we scroll through +// the items, the item is replaced on display. We also override the menu items to render as icons using XBMP icons. +// For each item in the card layout, we override how it is drawn and what row it is drawn on. See: +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ +// void setupGridLayoutForCardView() { - auto & factory = renderer.getGraphicsPropertiesFactory(); - - // now we make the two settings and status menus use icons instead of regular drawing. const Coord iconSize(APPICONS_WIDTH, APPICONS_HEIGHT); - factory.addImageToCache(DrawableIcon(menuSettings.getId(), iconSize, DrawableIcon::ICON_XBITMAP, settingsIcon40Bits)); - factory.addImageToCache(DrawableIcon(menuMute.getId(), iconSize, DrawableIcon::ICON_XBITMAP, muteOffIcon40Bits, muteOnIcon40Bits)); - const Coord iconBatSize(BATTERY_WIDTH, BATTERY_HEIGHT); - factory.addImageToCache(DrawableIcon(menuBattery.getId(), iconBatSize, DrawableIcon::ICON_XBITMAP, batteryIcon40Bits)); - - factory.addGridPosition(&menuSettings, GridPosition(GridPosition::DRAW_AS_ICON_TEXT, GridPosition::JUSTIFY_CENTER_NO_VALUE, 0, 60)); - factory.addGridPosition(&menuMute, GridPosition(GridPosition::DRAW_AS_ICON_TEXT, GridPosition::JUSTIFY_CENTER_NO_VALUE, 1, 60)); - factory.addGridPosition(&menuBattery, GridPosition(GridPosition::DRAW_AS_ICON_TEXT, GridPosition::JUSTIFY_CENTER_NO_VALUE, 2, 60)); - - // after adding things to the drawing properties, we must refresh it. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); + TcThemeBuilder themeBuilder(renderer); + themeBuilder.enableCardLayoutWithXbmImages(Coord(11, 22), ArrowHoriz11x22BitmapLeft, ArrowHoriz11x22BitmapRight, false) + .addingTitleWidget(titleWidget) + .manualDimensions(128, 128); + + themeBuilder.menuItemOverride(menuSettings) + .withImageXbmp(iconSize, settingsIcon40Bits) + .withDrawingMode(tcgfx::GridPosition::DRAW_AS_ICON_TEXT) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .onRow(0) + .apply(); + + themeBuilder.menuItemOverride(menuMute) + .withImageXbmp(iconSize, muteOffIcon40Bits, muteOnIcon40Bits) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .onRow(1) + .apply(); + + themeBuilder.menuItemOverride(menuBattery) + .withImageXbmp(Coord(BATTERY_WIDTH, BATTERY_HEIGHT), batteryIcon40Bits) + .withDrawingMode(tcgfx::GridPosition::DRAW_AS_ICON_TEXT) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .onRow(2) + .apply(); + + // after doing anything with theme builder always call apply. + themeBuilder.apply(); } // END card / custom layouts void setup() { + setupMenu(); + // here we set up the devices and services that we are going to use. Serial.begin(115200); - serEnableLevel(SER_TCMENU_DEBUG, true); - renderer.setFirstWidget(&titleWidget); - setupMenu(); + SPI.begin(36, 37, 35); - // Here we enable the card layout mode for the main menu by first enabling support, then adding the root menu. - // We also set up the item layout for card view by calling our setup function, defined above. - renderer.enableCardLayout(iconLeft, iconRight, nullptr, false); + // Now we enable the card layout mode for the main menu by first enabling support, then adding the root menu. setupGridLayoutForCardView(); // We can set a callback for when the title item is pressed on the main menu, here we show the app version diff --git a/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.cpp b/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.cpp index bbb549d5..8a6b0e33 100644 --- a/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.cpp +++ b/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.cpp @@ -8,16 +8,19 @@ use elsewhere. */ +// Generated for Arduino 32bit ARM by TcMenu 4.3.1 on 2024-09-28T16:12:56.028366200Z. + #include #include "esp32s3TftEncoder_menu.h" -#include "../ThemeCoolBlueTraditional.h" -#include +#include "../ThemeCoolBlueTraditionalBuilder.h" +#include +#include // Global variable declarations const ConnectorLocalInfo applicationInfo = { "ESP32 S3 Tiny", "c035e186-32cc-45e4-ac28-773f57e108ee" }; -TFT_eSPI gfx; -TfteSpiDrawable gfxDrawable(&gfx, 64); +Adafruit_ST7735 gfx(34, 7, 6); +AdafruitDrawable gfxDrawable(&gfx, 40); GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); // Global Menu Item declarations @@ -66,14 +69,11 @@ void setupMenu() { menuBatteryCharge.setReadOnly(true); // Code generated by plugins and new operators. - gfx.begin(); - gfx.setRotation(1); + gfx.initR(INITR_GREENTAB); + gfx.setRotation(0); renderer.setUpdatesPerSecond(15); switches.init(internalDigitalIo(), SWITCHES_NO_POLLING, true); menuMgr.initForEncoder(&renderer, &menuSettings, 3, 4, 5); - renderer.setTitleMode(BaseGraphicalRenderer::NO_TITLE); - renderer.setUseSliderForAnalog(true); - renderer.enableTcUnicode(); - installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin12, 0), MenuFontDef(&OpenSansCyrillicLatin12, 0), true); + installCoolBlueTraditionalTheme(renderer, MenuFontDef(&OpenSansRegular8pt, 0), MenuFontDef(&OpenSansRegular10pt, 0), true, BaseGraphicalRenderer::NO_TITLE, true); } diff --git a/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.h b/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.h index 4ffa166f..0fedb61f 100644 --- a/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.h +++ b/examples/esp/esp32s3TftEncoder/generated/esp32s3TftEncoder_menu.h @@ -14,7 +14,7 @@ #include #include #include -#include "tcMenuTfteSpi.h" +#include "tcMenuAdaFruitGfx.h" #include #include #include @@ -23,10 +23,11 @@ // variables we declare that you may need to access extern const PROGMEM ConnectorLocalInfo applicationInfo; -extern TFT_eSPI gfx; -extern TfteSpiDrawable gfxDrawable; +extern Adafruit_ST7735 gfx; +extern AdafruitDrawable gfxDrawable; extern GraphicsDeviceRenderer renderer; -extern const UnicodeFont OpenSansCyrillicLatin12[]; +extern const UnicodeFont OpenSansRegular8pt[]; +extern const UnicodeFont OpenSansRegular10pt[]; // Any externals needed by IO expanders, EEPROMs etc diff --git a/examples/arduino32/colorTftEthernet32/tcMenuAdaFruitGfx.cpp b/examples/esp/esp32s3TftEncoder/generated/tcMenuAdaFruitGfx.cpp similarity index 86% rename from examples/arduino32/colorTftEthernet32/tcMenuAdaFruitGfx.cpp rename to examples/esp/esp32s3TftEncoder/generated/tcMenuAdaFruitGfx.cpp index 64088990..24cb82dd 100644 --- a/examples/arduino32/colorTftEthernet32/tcMenuAdaFruitGfx.cpp +++ b/examples/esp/esp32s3TftEncoder/generated/tcMenuAdaFruitGfx.cpp @@ -34,6 +34,8 @@ using namespace tcgfx; #endif // AVR reduced size buffer #endif // COOKIE_CUT_MEMBUFFER_SIZE +uint16_t memBuffer[COOKIE_CUT_MEMBUFFER_SIZE]; + void AdafruitDrawable::transaction(bool isStarting, bool redrawNeeded) { if(!isStarting) refreshDisplayIfNeeded(graphics, redrawNeeded); } @@ -52,15 +54,58 @@ void AdafruitDrawable::drawBitmap(const Coord &where, const DrawableIcon *icon, if(icon->getIconType() == DrawableIcon::ICON_XBITMAP) { graphics->fillRect(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, backgroundColor); graphics->drawXBitmap(where.x, where.y, icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y, drawColor); - } - else if(icon->getIconType() == DrawableIcon::ICON_NATIVE) { + } else if(icon->getIconType() == DrawableIcon::ICON_NATIVE) { graphics->drawRGBBitmap(where.x, where.y, (const uint16_t*)icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y); - } - else if(icon->getIconType() == DrawableIcon::ICON_MONO) { + } else if(icon->getIconType() == DrawableIcon::ICON_MONO) { graphics->drawBitmap(where.x, where.y, icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y, drawColor, backgroundColor); + } else if(icon->getPalette() != nullptr){ + auto bpp = icon->getIconType() == tcgfx::DrawableIcon::ICON_PALLETE_2BPP ? 2 : 4; + drawBitmapNbpp(where, icon->getIcon(selected), icon->getDimensions(), bpp, icon->getPalette()); } } +void AdafruitDrawable::drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette) { + auto* asTft = reinterpret_cast(graphics); + auto yTot = int16_t(where.y + size.y); + auto xTot = int16_t(where.x + size.x); + int bitsInByte = bpp == 2 ? 4 : 2; + uint8_t downShift = bpp == 2 ? 6 : 4; + + uint16_t next = 0; + uint8_t byteIteration = bitsInByte; + uint8_t current; + + asTft->startWrite(); + + for(int16_t y = where.y; ysetAddrWindow(where.x, y, size.x, 1); + for(int16_t x = where.x; x> downShift; + current = current << bpp; + byteIteration++; + + memBuffer[next] = palette[idx]; + next = next + 1; + if(next == COOKIE_CUT_MEMBUFFER_SIZE) { + asTft->writePixels(memBuffer, next); + next = 0; + } + } + if(next != 0) { + asTft->writePixels(memBuffer, next); + next = 0; + } + byteIteration = bitsInByte; // always need a new byte in this case + } + + asTft->endWrite(); +} + void AdafruitDrawable::drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) { graphics->fillRect(where.x, where.y, size.x, size.y, backgroundColor); graphics->drawXBitmap(where.x, where.y, data, size.x, size.y, drawColor); @@ -69,8 +114,7 @@ void AdafruitDrawable::drawXBitmap(const Coord &where, const Coord &size, const void AdafruitDrawable::drawBox(const Coord &where, const Coord &size, bool filled) { if(filled) { graphics->fillRect(where.x, where.y, size.x, size.y, drawColor); - } - else { + } else { graphics->drawRect(where.x, where.y, size.x, size.y, drawColor); } } @@ -157,8 +201,6 @@ UnicodeFontHandler *AdafruitDrawable::createFontHandler() { // helper functions // -uint16_t memBuffer[COOKIE_CUT_MEMBUFFER_SIZE]; - void drawCookieCutBitmap(Adafruit_SPITFT* gfx, int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, int16_t totalWidth, int16_t xStart, int16_t yStart, uint16_t fgColor, uint16_t bgColor) { @@ -519,7 +561,7 @@ DeviceDrawable *AdafruitDrawable::getSubDeviceFor(const Coord &where, const Coor } AdafruitCanvasDrawable2bpp::AdafruitCanvasDrawable2bpp(AdafruitDrawable *root, int width, int height) : root(root), - sizeMax({width, height}), sizeCurrent(), palette{} { + sizeMax({width, height}), sizeCurrent(), palette{} { canvas = new TcGFXcanvas2(width, height); setGraphics(canvas); } @@ -561,3 +603,26 @@ DeviceDrawable *AdafruitCanvasDrawable2bpp::getSubDeviceFor(const Coord&, const return nullptr; // don't allow further nesting. } +void AdafruitCanvasDrawable2bpp::drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const uint16_t* palette) { + auto yTot = int16_t(where.y + size.y); + auto xTot = int16_t(where.x + size.x); + int bitsInByte = bpp == 2 ? 4 : 2; + uint8_t downShift = bpp == 2 ? 6 : 4; + + uint8_t byteIteration = bitsInByte; + uint8_t current; + for(int16_t y = where.y; y> downShift; + current = current << bitsInByte; + byteIteration++; + canvas->drawPixel(x, y, idx); + } + byteIteration = bitsInByte; // always need a new byte in this case + } +} \ No newline at end of file diff --git a/examples/arduino32/colorTftEthernet32/tcMenuAdaFruitGfx.h b/examples/esp/esp32s3TftEncoder/generated/tcMenuAdaFruitGfx.h similarity index 97% rename from examples/arduino32/colorTftEthernet32/tcMenuAdaFruitGfx.h rename to examples/esp/esp32s3TftEncoder/generated/tcMenuAdaFruitGfx.h index 018eeed8..86e7199d 100644 --- a/examples/arduino32/colorTftEthernet32/tcMenuAdaFruitGfx.h +++ b/examples/esp/esp32s3TftEncoder/generated/tcMenuAdaFruitGfx.h @@ -176,6 +176,7 @@ class AdafruitDrawable : public DeviceDrawable { void internalDrawText(const Coord &where, const void *font, int mag, const char *text) override; void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override; void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override; + virtual void drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette); void drawBox(const Coord &where, const Coord &size, bool filled) override; void drawCircle(const Coord& where, int radius, bool filled) override; void drawPolygon(const Coord points[], int numPoints, bool filled) override; @@ -212,6 +213,7 @@ class AdafruitCanvasDrawable2bpp : public AdafruitDrawable { void transaction(bool isStarting, bool redrawNeeded) override; color_t getUnderlyingColor(color_t col) override; DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord &size, const color_t *palette, int paletteSize) override; + void drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette) override; }; #endif /* _TCMENU_TCMENUADAFRUITGFX_H_ */ diff --git a/examples/esp/esp32s3TftEncoder/generated/tcMenuTfteSpi.cpp b/examples/esp/esp32s3TftEncoder/generated/tcMenuTfteSpi.cpp deleted file mode 100644 index 3cab2292..00000000 --- a/examples/esp/esp32s3TftEncoder/generated/tcMenuTfteSpi.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * TFT_eSPI renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - * - * LIBRARY REQUIREMENT - * This library requires the AdaGfx library along with a suitable driver. - */ - -#include "tcMenuTfteSpi.h" -#include "tcUnicodeTFT_eSPI.h" -#include - -using namespace iotouch; -using namespace tcgfx; - -TfteSpiDrawable::TfteSpiDrawable(TFT_eSPI *tft, int spriteHeight) : tft(tft), spriteWithConfig(nullptr), spriteHeight(spriteHeight) {} - -DeviceDrawable *TfteSpiDrawable::getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) { - if(paletteSize > SPRITE_PALETTE_SIZE) return nullptr; // cant exceed color palette size - - if(spriteWithConfig == nullptr) spriteWithConfig = new TftSpriteAndConfig(this, tft->width(), spriteHeight); - if(!spriteWithConfig) return nullptr; - - if(spriteWithConfig->initSprite(where, size, palette, paletteSize)) { - return spriteWithConfig; - } - else return nullptr; -} - -void TfteSpiDrawable::internalDrawText(const Coord &where, const void *font, int mag, const char *text) { - fontPtrToNum(font, mag); - tft->setTextColor(drawColor, drawColor); // transparent background - tft->drawString(text, where.x, where.y); -} - -void TfteSpiDrawable::drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) { - if(icon->getIconType() == DrawableIcon::ICON_XBITMAP) { - tft->drawXBitmap(where.x, where.y, icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y, drawColor, backgroundColor); - } else if(icon->getIconType() == DrawableIcon::ICON_MONO) { - tft->drawBitmap(where.x, where.y, icon->getIcon(selected), icon->getDimensions().x, icon->getDimensions().y, drawColor, backgroundColor); - } else if(icon->getIconType() == DrawableIcon::ICON_NATIVE) { - tft->pushImage(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, (const uint16_t*)icon->getIcon(selected)); - } else if(icon->getPalette() != nullptr) { - auto bpp = icon->getIconType() == tcgfx::DrawableIcon::ICON_PALLETE_2BPP ? 2 : 4; - drawBitmapNbpp(where, icon->getIcon(selected), icon->getDimensions(), bpp, icon->getPalette()); - } -} - -void TfteSpiDrawable::drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) { - tft->drawXBitmap(where.x, where.y, data, size.x, size.y, drawColor, backgroundColor); -} - -void TfteSpiDrawable::drawBox(const Coord &where, const Coord &size, bool filled) { - if(filled) { - tft->fillRect(where.x, where.y, size.x, size.y, drawColor); - } - else { - tft->drawRect(where.x, where.y, size.x, size.y, drawColor); - } -} - -void TfteSpiDrawable::drawCircle(const Coord &where, int radius, bool filled) { - if(filled) { - tft->fillCircle(where.x, where.y, radius, drawColor); - } - else { - tft->drawCircle(where.x, where.y, radius, drawColor); - } -} - -void TfteSpiDrawable::drawPolygon(const Coord *points, int numPoints, bool filled) { - if(numPoints == 2) { - tft->drawLine(points[0].x, points[0].y, points[1].x, points[1].y, drawColor); - } - else if(numPoints == 3) { - if(filled) { - tft->fillTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, drawColor); - } - else { - tft->drawTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, drawColor); - } - } -} - -void TfteSpiDrawable::transaction(bool isStarting, bool redrawNeeded) { - if(isStarting) tft->setTextDatum(TL_DATUM); -} - -Coord TfteSpiDrawable::internalTextExtents(const void *font, int mag, const char *text, int *baseline) { - if(baseline) *baseline = 0; - fontPtrToNum(font, mag); - return Coord(tft->textWidth(text), tft->fontHeight()); -} - -void TfteSpiDrawable::drawPixel(uint16_t x, uint16_t y) { - tft->drawPixel(x, y, drawColor); -} - -void TfteSpiDrawable::fontPtrToNum(const void* font, int mag) { - if(font == nullptr) { - tft->setTextFont((uint8_t) mag); - } - else { - tft->setFreeFont(static_cast(font)); - } -} - -UnicodeFontHandler *TfteSpiDrawable::createFontHandler() { - return fontHandler = new UnicodeFontHandler(newTFT_eSPITextPipeline(tft), tccore::ENCMODE_UTF8); -} - -// -// Sprite object -// - -TftSpriteAndConfig::TftSpriteAndConfig(TfteSpiDrawable *root, int width, int height) : TfteSpiDrawable(&sprite, 0), - root(root), sprite(root->getTFT()), where(0,0), currentSize(0, 0), size(width, height), currentColorsDefined(0) { -} - -bool TftSpriteAndConfig::initSprite(const Coord &spriteWhere, const Coord &spriteSize, const color_t* palette, int palEntries) { - // if the area is too big, or the sprite is in use, don't proceed. - if(spriteSize.x > size.x || spriteSize.y > size.y) return false; - - if(root->isTcUnicodeEnabled() && fontHandler == nullptr) { - fontHandler = new UnicodeFontHandler(newTFT_eSPITextPipeline(&sprite), tccore::ENCMODE_UTF8); - } - - // create the sprite if needed - if(!sprite.created()) { - sprite.createSprite(size.x, size.y); - sprite.setColorDepth(4); - } - for(int i=0; i> downShift; - current = current << bitsInByte; - byteIteration++; - sprite.drawPixel(x, y, idx); - } - byteIteration = bitsInByte; // always need a new byte in this case - } -} - -#ifndef COOKIE_CUT_MEMBUFFER_SIZE -#define COOKIE_CUT_MEMBUFFER_SIZE 32 -#endif -uint16_t memBuffer[COOKIE_CUT_MEMBUFFER_SIZE]; - -void TfteSpiDrawable::drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette) { - auto yTot = int16_t(where.y + size.y); - auto xTot = int16_t(where.x + size.x); - int bitsInByte = bpp == 2 ? 4 : 2; - uint8_t downShift = bpp == 2 ? 6 : 4; - - uint16_t next = 0; - uint8_t byteIteration = bitsInByte; - uint8_t current; - - tft->startWrite(); - - for(int16_t y = where.y; ysetAddrWindow(where.x, y, size.x, 1); - for(int16_t x = where.x; x> downShift; - current = current << bpp; - byteIteration++; - - memBuffer[next] = palette[idx]; - next = next + 1; - if(next == COOKIE_CUT_MEMBUFFER_SIZE) { - tft->pushColors(memBuffer, next); - next = 0; - } - } - if(next != 0) { - tft->pushColors(memBuffer, next); - next = 0; - } - byteIteration = bitsInByte; // always need a new byte in this case - } - - tft->endWrite(); -} - - -#if TC_TFT_ESPI_NEEDS_TOUCH == true - -TouchState TftSpiTouchInterrogator::internalProcessTouch(float *ptrX, float *ptrY, const TouchOrientationSettings& rotation, const iotouch::CalibrationHandler& calib) { - - uint16_t touchX=0, touchY=0; - bool pressed; - if(usingRawTouch) { - tft->getTouchRaw(&touchX, &touchY); - pressed = tft->getTouchRawZ() > 600; - *ptrX = calib.calibrateX(float(touchX) / XPT_2046_MAX, rotation.isXInverted()); - *ptrY = calib.calibrateY(float(touchY) / XPT_2046_MAX, rotation.isYInverted()); - } else { - pressed = tft->getTouch(&touchX, &touchY); - *ptrX = calib.calibrateX(float(touchX) / maxWidthDim, rotation.isXInverted()); - *ptrY = calib.calibrateY(float(touchY) / maxHeightDim, rotation.isYInverted()); - } - - if(!pressed) return iotouch::NOT_TOUCHED; - //serdebugF3("point at ", touchX, touchY); - - return iotouch::TOUCHED; -} -#endif // TC_TFT_ESPI_NEEDS_TOUCH == true diff --git a/examples/esp/esp32s3TftEncoder/generated/tcMenuTfteSpi.h b/examples/esp/esp32s3TftEncoder/generated/tcMenuTfteSpi.h deleted file mode 100644 index 67ec5e54..00000000 --- a/examples/esp/esp32s3TftEncoder/generated/tcMenuTfteSpi.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * TFT_eSPI renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - */ - -#ifndef TCMENU_PLUGIN_TCMENUTFTESPI_H -#define TCMENU_PLUGIN_TCMENUTFTESPI_H - -#include -#include -#include -#include -#include - -#define TFT_SPRITE_BITS 4 -#define SPRITE_PALETTE_SIZE (1 << TFT_SPRITE_BITS) - -using namespace tcgfx; - -class TftSpriteAndConfig; - -class TfteSpiDrawable : public DeviceDrawable { -private: - TFT_eSPI* tft; - TftSpriteAndConfig* spriteWithConfig; - uint16_t spriteHeight; -public: - TfteSpiDrawable(TFT_eSPI *tft, int maxSpriteHeight); - - DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) override; - - void internalDrawText(const Coord &where, const void *font, int mag, const char *text) override; - - void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override; - - void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override; - - virtual void drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette); - - void drawBox(const Coord &where, const Coord &size, bool filled) override; - - void drawCircle(const Coord &where, int radius, bool filled) override; - - void drawPolygon(const Coord *points, int numPoints, bool filled) override; - - void drawPixel(uint16_t x, uint16_t y) override; - - void transaction(bool isStarting, bool redrawNeeded) override; - - Coord internalTextExtents(const void *font, int mag, const char *text, int *baseline) override; - Coord getDisplayDimensions() override { return Coord(tft->width(), tft->height());} - TFT_eSPI* getTFT() { return tft; } -protected: - UnicodeFontHandler* createFontHandler() override; -private: - void fontPtrToNum(const void* font, int mag); -}; - -class TftSpriteAndConfig : public TfteSpiDrawable { -private: - TfteSpiDrawable* root; - TFT_eSprite sprite; - Coord where; - Coord currentSize; - const Coord size; - uint8_t currentColorsDefined; -public: - TftSpriteAndConfig(TfteSpiDrawable *root, int width, int height); - - bool initSprite(const Coord& spriteWhere, const Coord& spriteSize, const color_t* palette, int paletteEntries); - DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) override { return nullptr; } - void transaction(bool isStarting, bool redrawNeeded) override; - color_t getUnderlyingColor(color_t col) override; - void drawBitmapNbpp(const Coord& where, const uint8_t* data, const Coord& size, int bpp, const color_t* palette) override; - TFT_eSprite& getTftSprite() { return sprite; } -}; - -#define TC_TFT_ESPI_NEEDS_TOUCH false -#if TC_TFT_ESPI_NEEDS_TOUCH == true - -#define XPT_2046_MAX 4096 - -namespace iotouch { - - /** - * Implements the touch interrogator class, this purely gets the current reading from the device when requested. This - * implementation works with the TFT_eSPI touch functions providing tcMenu support for it. It is your responsibility - * to have run whatever calibration is needed before calling this function. The X and Y values to the constructor - * are the maximum values that can be returned by calling getTouch. - */ - class TftSpiTouchInterrogator : public iotouch::TouchInterrogator { - private: - TFT_eSPI* tft; - float maxWidthDim; - float maxHeightDim; - bool usingRawTouch; - public: - TftSpiTouchInterrogator(TFT_eSPI* tft, uint16_t xMax, uint16_t yMax, bool rawTouch) - : tft(tft), maxWidthDim(xMax), maxHeightDim(yMax), usingRawTouch(rawTouch) { } - - iotouch::TouchState internalProcessTouch(float *ptrX, float *ptrY, const TouchOrientationSettings& touchOrientationSettings, - const iotouch::CalibrationHandler& calib) override; - }; - -} -#endif // TC_TFT_ESPI_NEEDS_TOUCH == true - -#endif //TCMENU_PLUGIN_TCMENUTFTESPI_H diff --git a/examples/esp/esp8266WifiOled/Greenhouse.emf b/examples/esp/esp8266WifiOled/Greenhouse.emf index c1129c1f..df184a51 100644 --- a/examples/esp/esp8266WifiOled/Greenhouse.emf +++ b/examples/esp/esp8266WifiOled/Greenhouse.emf @@ -309,7 +309,7 @@ "lastRemoteUuids": [ "46c30011-cac6-4598-a7b8-b0630d55daab" ], - "lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0", + "lastThemeUuid": "396ED4DF-AD7B-4951-A848-A9E5838A549B", "applicationUUID": "01b9cb76-c108-4be3-a133-6159f8f1c9c1", "applicationName": "ESP8266 Greenhouse", "lastProperties": [ @@ -476,14 +476,15 @@ "eepromDefinition": "eeprom:", "authenticatorDefinition": "rom:100:6", "projectIoExpanders": [ - "deviceIO:", - "pcf8574:io8574:32:12:false" + "pcf8574:io8574:32:12:false", + "deviceIO:" ], "menuInMenuCollection": { "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false + "appIsModular": false, + "listOfEmbeddedForms": [] }, "stringLists": [] } \ No newline at end of file diff --git a/examples/esp/esp8266WifiOled/ThemeMonoInverse.h b/examples/esp/esp8266WifiOled/ThemeMonoInverse.h deleted file mode 100644 index 1d689400..00000000 --- a/examples/esp/esp8266WifiOled/ThemeMonoInverse.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TCMENU_THEME_MONO_INVERSE -#define TCMENU_THEME_MONO_INVERSE - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; -color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; - -#define TITLE_PADDING 2 -#define TITLE_SPACING 2 - -void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 2); - - MenuPadding titlePadding(TITLE_PADDING); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_INVERSE \ No newline at end of file diff --git a/examples/esp/esp8266WifiOled/ThemeMonoInverseBuilder.h b/examples/esp/esp8266WifiOled/ThemeMonoInverseBuilder.h new file mode 100644 index 00000000..1ef2d8a6 --- /dev/null +++ b/examples/esp/esp8266WifiOled/ThemeMonoInverseBuilder.h @@ -0,0 +1,60 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; +color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; + +#define TITLE_PADDING 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoInverseTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 2) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(defaultTitlePaletteMono) + .withPadding(MenuPadding(TITLE_PADDING)) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/esp/esp8266WifiOled/esp8266WifiOled.ino b/examples/esp/esp8266WifiOled/esp8266WifiOled.ino index 7ef88ca8..2b9bb77f 100644 --- a/examples/esp/esp8266WifiOled/esp8266WifiOled.ino +++ b/examples/esp/esp8266WifiOled/esp8266WifiOled.ino @@ -25,6 +25,7 @@ #include #include #include "appicons.h" +#include // contains the graphical widget title components. #include "stockIcons/wifiAndConnectionIcons16x12.h" @@ -39,9 +40,9 @@ char fileChoicesArray[255]{}; // we add two widgets that show both the connection status and wifi signal strength // these are added to the renderer and rendered upon any change. -// https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/#titlewidget-for-presenting-state-in-icon-form +// https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/rendering-with-tcmenu-lcd-tft-oled/#drawing-bitmaps-and-presenting-state-with-titlewidget TitleWidget connectedWidget(iconsConnection, 2, 16, 12); -TitleWidget wifiWidget(iconsWifi, 5, 16, 12, &connectedWidget); +TitleWidget wifiWidget(iconsWifi, 5, 16, 12); // state used by the sketch @@ -88,9 +89,6 @@ void setup() { //Wire.setClock(400000); EEPROM.begin(512); // set up the inbuilt ESP rom to use for load and store. - // here we set the first widget that will be displayed in the title area. - renderer.setFirstWidget(&wifiWidget); - // initialise the menu. setupMenu(); @@ -100,21 +98,36 @@ void setup() { startWiFi(); menuIoTMonitor.registerCommsNotification(onCommsChange); - // now we add three icons into the icon cache, we should add one for each menu item that we give a grid position - // that draws as an image. - auto& props = static_cast(renderer.getDisplayPropertiesFactory()); - props.addImageToCache(DrawableIcon(menuElectricHeater.getId(), Coord(APPICON_HEAT_WIDTH, APPICON_HEAT_HEIGHT), DrawableIcon::ICON_XBITMAP, appIconHeatOff, appIconHeatOn)); - props.addImageToCache(DrawableIcon(menuLockDoor.getId(), Coord(APPICON_LOCK_WIDTH, APPICON_LOCK_HEIGHT), DrawableIcon::ICON_XBITMAP, appIconLockOpen, appIconLockClosed)); - props.addImageToCache(DrawableIcon(menuSetup.getId(), Coord(APPICON_SETTINGS_WIDTH, APPICON_SETTINGS_HEIGHT), DrawableIcon::ICON_XBITMAP, appIconSettings)); - - // here we override the drawing grid for some menu items, we tell the renderer to draw as icons in a three position - // grid, with a fixed height. - props.addGridPosition(&menuElectricHeater, GridPosition(GridPosition::DRAW_AS_ICON_ONLY, GridPosition::JUSTIFY_CENTER_NO_VALUE,3, 2, 3, 26)); - props.addGridPosition(&menuLockDoor, GridPosition(GridPosition::DRAW_AS_ICON_ONLY, GridPosition::JUSTIFY_CENTER_NO_VALUE, 3, 3, 3, 26)); - props.addGridPosition(&menuSetup, GridPosition(GridPosition::DRAW_AS_ICON_ONLY, GridPosition::JUSTIFY_CENTER_NO_VALUE, 3, 1, 3, 26)); - - // after changing the drawing properties, always refresh the cache to ensure it draws properly. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); + // Here we create a theme builder to add title widgets to the top right, and also to override drawing of some + // menu items to be multi column (IE three items on a row). + // https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + + TcThemeBuilder themeBuilder(renderer); + themeBuilder.addingTitleWidget(wifiWidget) + .addingTitleWidget(connectedWidget); + + // override the electric heater to be in column 1 on row 3 drawn with an icon + themeBuilder.menuItemOverride(menuElectricHeater) + .withImageXbmp(Coord(APPICON_HEAT_WIDTH, APPICON_HEAT_HEIGHT), appIconHeatOff, appIconHeatOn) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .onRowCol(3, 1, 3) + .apply(); + + // override the door lock to be in column 2 on row 3 drawn with an icon + themeBuilder.menuItemOverride(menuLockDoor) + .withImageXbmp(Coord(APPICON_LOCK_WIDTH, APPICON_LOCK_HEIGHT), appIconLockOpen, appIconLockClosed) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .onRowCol(3, 2, 3) + .apply(); + + // override the settings menu to be in column 3 on row 3 drawn with an icon + themeBuilder.menuItemOverride(menuSetup) + .withImageXbmp(Coord(APPICON_SETTINGS_WIDTH, APPICON_SETTINGS_HEIGHT), appIconSettings) + .withJustification(tcgfx::GridPosition::JUSTIFY_CENTER_NO_VALUE) + .onRowCol(3, 3, 3) + .apply(); + + themeBuilder.apply(); // now monitor the wifi level every second and report it in a widget. taskManager.scheduleFixedRate(1000, [] { @@ -148,10 +161,10 @@ void setup() { // Now we configure our simulated heater and window.. We use inverse // logic on the 8574 because it's better at pulling down to GND than up. // - ioDevicePinMode(ioexp_io8574, WINDOW_PIN, OUTPUT); - ioDevicePinMode(ioexp_io8574, HEATER_PIN, OUTPUT); - ioDeviceDigitalWrite(ioexp_io8574, WINDOW_PIN, HIGH); - ioDeviceDigitalWriteS(ioexp_io8574, HEATER_PIN, HIGH); + ioexp_io8574->pinMode(WINDOW_PIN, OUTPUT); + ioexp_io8574->pinMode(HEATER_PIN, OUTPUT); + ioexp_io8574->digitalWrite(WINDOW_PIN, HIGH); + ioexp_io8574->digitalWriteS(HEATER_PIN, HIGH); } // @@ -182,7 +195,7 @@ void windowOpenFn() { } else windowOpen = false; - ioDeviceDigitalWriteS(ioexp_io8574, WINDOW_PIN, windowOpen); + ioexp_io8574->digitalWriteS(WINDOW_PIN, windowOpen); } // we are using a simulated low speed PWM to control the heater @@ -199,7 +212,7 @@ void heaterOnFn() { } else heaterOn = false; - ioDeviceDigitalWriteS(ioexp_io8574, HEATER_PIN, heaterOn); + ioexp_io8574->digitalWriteS(HEATER_PIN, heaterOn); } // diff --git a/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.cpp b/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.cpp index cb03ef5b..d8804076 100644 --- a/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.cpp +++ b/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.cpp @@ -8,9 +8,11 @@ use elsewhere. */ +// Generated for Arduino ESP8266 by TcMenu 4.3.1 on 2024-09-28T17:47:54.790577400Z. + #include #include "esp8266WifiOled_menu.h" -#include "ThemeMonoInverse.h" +#include "ThemeMonoInverseBuilder.h" // Global variable declarations const PROGMEM ConnectorLocalInfo applicationInfo = { "ESP8266 Greenhouse", "01b9cb76-c108-4be3-a133-6159f8f1c9c1" }; @@ -88,21 +90,19 @@ void setupMenu() { menuIpAddress.setReadOnly(true); menuCucumberTemp.setReadOnly(true); menuTomatoTemp.setReadOnly(true); - menuPwd.setLocalOnly(true); - menuAuthenticator.setLocalOnly(true); menuSSID.setLocalOnly(true); + menuPwd.setLocalOnly(true); menuIoTMonitor.setLocalOnly(true); + menuAuthenticator.setLocalOnly(true); menuSecretEntry.setVisible(false); - // Code generated by plugins. + // Code generated by plugins and new operators. gfx.begin(); renderer.setUpdatesPerSecond(10); switches.init(internalDigitalIo(), SWITCHES_POLL_KEYS_ONLY, true); menuMgr.initForEncoder(&renderer, &menuTomatoTemp, 12, 13, 14); remoteServer.addConnection(ðernetConnection); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(false); - installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true); + installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true, BaseGraphicalRenderer::TITLE_FIRST_ROW, false); // We have an IoT monitor, register the server menuIoTMonitor.setRemoteServer(remoteServer); diff --git a/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.h b/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.h index cfba4446..21bbb382 100644 --- a/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.h +++ b/examples/esp/esp8266WifiOled/esp8266WifiOled_menu.h @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/examples/esp/espCapTouchTft/ThemeCoolBlueModernBuilder.h b/examples/esp/espCapTouchTft/ThemeCoolBlueModernBuilder.h new file mode 100644 index 00000000..57f352b1 --- /dev/null +++ b/examples/esp/espCapTouchTft/ThemeCoolBlueModernBuilder.h @@ -0,0 +1,70 @@ +/** + * Cool blue modern theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. + * This file will not be updated by the designer, you can edit. + * See https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + */ + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE + +#include + +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; +const color_t coolBlueActionPalette[] = {RGB(255, 255, 255), RGB(0,45,120), RGB(20,133,255), RGB(31,100,178)}; + +#define ACTION_BORDER_WIDTH 0 +#define USE_SLIDER_FOR_ANALOG true + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installCoolBlueModernTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + TcThemeBuilder themeBuilder(gr); + + themeBuilder.dimensionsFromRenderer() + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) + .withItemPadding(MenuPadding(4, 3, 4, 3)) + .withTitlePadding(MenuPadding(4, 3, 4, 3)) + .withRenderingSettings(titleMode, USE_SLIDER_FOR_ANALOG) + .withPalette(coolBlueItemPalette) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(2); + + if(needEditingIcons) { + themeBuilder.withStandardMedResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultItemProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.defaultTitleProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(coolBlueTitlePalette) + .withSpacing(3) + .apply(); + + + themeBuilder.defaultActionProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withPalette(coolBlueActionPalette) + .withBorder(MenuBorder(ACTION_BORDER_WIDTH)) + .apply(); + + themeBuilder.apply(); +} + +#endif //THEME_COOL_BLUE \ No newline at end of file diff --git a/examples/esp/espCapTouchTft/espCapTouchTft.emf b/examples/esp/espCapTouchTft/espCapTouchTft.emf index b9c557f9..8899bda1 100644 --- a/examples/esp/espCapTouchTft/espCapTouchTft.emf +++ b/examples/esp/espCapTouchTft/espCapTouchTft.emf @@ -163,7 +163,7 @@ "lastRemoteUuids": [ "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" ], - "lastThemeUuid": "2F1EAB1E-0469-42C8-A222-BE2DF96D6D81", + "lastThemeUuid": "1947F585-9D36-448C-8A80-B425686107BD", "applicationUUID": "a32450f4-91fc-4747-9e6f-6317dd9e2309", "applicationName": "espCapTouchTft", "lastProperties": [ @@ -312,6 +312,11 @@ "latestValue": "num:,4", "subsystem": "THEME" }, + { + "name": "BORDER_FOR_ACTIONS", + "latestValue": "0", + "subsystem": "THEME" + }, { "name": "TITLE_SHOW_MODE", "latestValue": "TITLE_ALWAYS", @@ -322,6 +327,11 @@ "latestValue": "false", "subsystem": "THEME" }, + { + "name": "USE_SLIDER_ANALOG", + "latestValue": "true", + "subsystem": "THEME" + }, { "name": "NEED_EDITING_ICONS", "latestValue": "true", diff --git a/examples/esp/espCapTouchTft/espCapTouchTft_menu.cpp b/examples/esp/espCapTouchTft/espCapTouchTft_menu.cpp index 0404fbbd..e38a66c6 100644 --- a/examples/esp/espCapTouchTft/espCapTouchTft_menu.cpp +++ b/examples/esp/espCapTouchTft/espCapTouchTft_menu.cpp @@ -8,11 +8,11 @@ use elsewhere. */ -// Generated for Arduino ESP32 by TcMenu 4.3.1-SNAPSHOT on 2024-08-31T09:58:46.844277900Z. +// Generated for Arduino ESP32 by TcMenu 4.3.1 on 2024-09-08T11:36:32.065655600Z. #include #include "espCapTouchTft_menu.h" -#include "ThemeDarkModeTraditionalBuilder.h" +#include "ThemeCoolBlueModernBuilder.h" // Global variable declarations const PROGMEM ConnectorLocalInfo applicationInfo = { "espCapTouchTft", "a32450f4-91fc-4747-9e6f-6317dd9e2309" }; @@ -61,6 +61,6 @@ void setupMenu() { touchInterrogator.init(); touchScreen.start(); menuMgr.initWithoutInput(&renderer, &menuPercentage); - installDarkModeTraditionalTheme(renderer, MenuFontDef(nullptr, 2), MenuFontDef(nullptr, 4), true, BaseGraphicalRenderer::TITLE_ALWAYS, false); + installCoolBlueModernTheme(renderer, MenuFontDef(nullptr, 2), MenuFontDef(nullptr, 4), true, BaseGraphicalRenderer::TITLE_ALWAYS, false); } diff --git a/examples/esp/simpleU8g2/ThemeMonoBordered.h b/examples/esp/simpleU8g2/ThemeMonoBordered.h deleted file mode 100644 index d35c045e..00000000 --- a/examples/esp/simpleU8g2/ThemeMonoBordered.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef TCMENU_THEME_MONO_BORDER -#define TCMENU_THEME_MONO_BORDER - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; - -#define TITLE_BORDER_THICKNESS 2 -#define TITLE_SPACING 2 - -void installMonoBorderedTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 1); - - MenuPadding titlePadding(1); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultItemPaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, - MenuBorder(0, 0, TITLE_BORDER_THICKNESS, 0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_BORDER diff --git a/examples/esp/simpleU8g2/ThemeMonoBorderedBuilder.h b/examples/esp/simpleU8g2/ThemeMonoBorderedBuilder.h new file mode 100644 index 00000000..1dcdff97 --- /dev/null +++ b/examples/esp/simpleU8g2/ThemeMonoBorderedBuilder.h @@ -0,0 +1,58 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {WHITE, BLACK, WHITE, WHITE}; + +#define TITLE_BORDER_THICKNESS 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoBorderTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 1) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .withBorder(MenuBorder(0, 0, TITLE_BORDER_THICKNESS, 0)) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/esp/simpleU8g2/simpleU8g2.emf b/examples/esp/simpleU8g2/simpleU8g2.emf index 20a897a0..ae7a44f7 100644 --- a/examples/esp/simpleU8g2/simpleU8g2.emf +++ b/examples/esp/simpleU8g2/simpleU8g2.emf @@ -246,7 +246,7 @@ "lastRemoteUuids": [ "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" ], - "lastThemeUuid": "815316bb-76c9-436a-8f83-be0bced963df", + "lastThemeUuid": "8D9B49C7-FD28-4533-9B00-21A4184BB0C9", "applicationUUID": "fddaa423-cb5c-4024-8f67-a9742f4457f3", "applicationName": "Simple U8G2 Toaster", "lastProperties": [ @@ -361,8 +361,8 @@ "subsystem": "THEME" }, { - "name": "TITLE_BORDER_WIDTH", - "latestValue": "1", + "name": "TITLE_HEADER_PADDING", + "latestValue": "2", "subsystem": "THEME" }, { diff --git a/examples/esp/simpleU8g2/simpleU8g2_menu.cpp b/examples/esp/simpleU8g2/simpleU8g2_menu.cpp index 256287cd..d4b31571 100644 --- a/examples/esp/simpleU8g2/simpleU8g2_menu.cpp +++ b/examples/esp/simpleU8g2/simpleU8g2_menu.cpp @@ -8,9 +8,11 @@ use elsewhere. */ +// Generated for Arduino ESP8266 by TcMenu 4.3.1 on 2024-09-28T17:02:47.500480100Z. + #include #include "simpleU8g2_menu.h" -#include "ThemeMonoBordered.h" +#include "ThemeMonoBorderedBuilder.h" // Global variable declarations const PROGMEM ConnectorLocalInfo applicationInfo = { "Simple U8G2 Toaster", "fddaa423-cb5c-4024-8f67-a9742f4457f3" }; @@ -64,8 +66,6 @@ void setupMenu() { renderer.setUpdatesPerSecond(10); switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); menuMgr.initForEncoder(&renderer, &menuToasterPower, 13, 12, 14); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(false); - installMonoBorderedTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(u8g2_font_finderskeepers_tf, 1), true); + installMonoBorderTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(u8g2_font_finderskeepers_tf, 1), true, BaseGraphicalRenderer::TITLE_FIRST_ROW, false); } diff --git a/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c.emf b/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c.emf deleted file mode 100644 index 1a2e772c..00000000 --- a/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c.emf +++ /dev/null @@ -1,221 +0,0 @@ -{ - "version": "1.00", - "projectName": "Project description", - "author": "dave", - "items": [ - { - "parentId": 0, - "type": "enumItem", - "defaultValue": "4", - "item": { - "enumEntries": [ - "HeatFan", - "Heater", - "Fan", - "Error", - "Off" - ], - "name": "Status", - "variableName": "Status", - "id": 1, - "eepromAddress": -1, - "readOnly": true, - "localOnly": false, - "visible": true - } - }, - { - "parentId": 0, - "type": "analogItem", - "defaultValue": "0", - "item": { - "maxValue": 1500, - "offset": 0, - "divisor": 10, - "unitName": "C", - "step": 1, - "name": "Temp room", - "variableName": "TempRoom", - "id": 2, - "eepromAddress": -1, - "readOnly": true, - "localOnly": false, - "visible": true - } - }, - { - "parentId": 0, - "type": "analogItem", - "defaultValue": "0", - "item": { - "maxValue": 1500, - "offset": 0, - "divisor": 10, - "unitName": "C", - "step": 1, - "name": "Temp htr", - "variableName": "TempHtr", - "id": 3, - "eepromAddress": -1, - "readOnly": true, - "localOnly": false, - "visible": true - } - }, - { - "parentId": 0, - "type": "subMenu", - "item": { - "secured": false, - "name": "Settings", - "variableName": "Settings", - "id": 4, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true - } - }, - { - "parentId": 4, - "type": "analogItem", - "defaultValue": "0", - "item": { - "maxValue": 100, - "offset": 0, - "divisor": 1, - "unitName": "C", - "step": 1, - "name": "Temp", - "variableName": "SettingsTemp", - "id": 5, - "eepromAddress": 2, - "readOnly": false, - "localOnly": false, - "visible": true - } - }, - { - "parentId": 4, - "type": "boolItem", - "defaultValue": "true", - "item": { - "naming": "TRUE_FALSE", - "name": "Fan", - "variableName": "SettingsFan", - "id": 6, - "eepromAddress": -1, - "readOnly": false, - "localOnly": false, - "visible": true - } - } - ], - "codeOptions": { - "embeddedPlatform": "MBED_RTOS", - "lastDisplayUuid": "d4c84106-fa87-4024-b91e-053e17a52b8f", - "lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87", - "lastRemoteUuid": "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb", - "lastRemoteUuids": [ - "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" - ], - "lastThemeUuid": "2026a7f2-0d5b-43f5-9f98-4f0eacac4c0e", - "applicationUUID": "b04706cc-5acd-477a-81b9-0770e37a9546", - "applicationName": "Space Heater", - "lastProperties": [ - { - "name": "LCD_WIDTH", - "latestValue": "16", - "subsystem": "DISPLAY" - }, - { - "name": "LCD_HEIGHT", - "latestValue": "2", - "subsystem": "DISPLAY" - }, - { - "name": "I2C_ADDRESS", - "latestValue": "0x47", - "subsystem": "DISPLAY" - }, - { - "name": "PIN_LAYOUT", - "latestValue": "EN_RW_RS", - "subsystem": "DISPLAY" - }, - { - "name": "WIRE_VARIABLE", - "latestValue": "i2cDisplay", - "subsystem": "DISPLAY" - }, - { - "name": "UNO_OR_FULL", - "latestValue": "fullLcd", - "subsystem": "DISPLAY" - }, - { - "name": "UPDATES_PER_SEC", - "latestValue": "2", - "subsystem": "DISPLAY" - }, - { - "name": "SW_POLLING_MODE", - "latestValue": "SWITCHES_NO_POLLING", - "subsystem": "INPUT" - }, - { - "name": "SWITCH_IODEVICE", - "latestValue": "devicePins", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_PIN_A", - "latestValue": "PC_8", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_PIN_B", - "latestValue": "PC_10", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_PIN_OK", - "latestValue": "PC_9", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_BACK_PIN", - "latestValue": "-1", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_NEXT_PIN", - "latestValue": "-1", - "subsystem": "INPUT" - }, - { - "name": "PULLUP_LOGIC", - "latestValue": "true", - "subsystem": "INPUT" - }, - { - "name": "ENCODER_IS_QUARTER_CYCLE", - "latestValue": "false", - "subsystem": "INPUT" - } - ], - "namingRecursive": true, - "saveToSrc": false, - "useCppMain": true, - "eepromDefinition": "", - "authenticatorDefinition": "", - "projectIoExpanders": [ - "deviceIO:" - ], - "menuInMenuCollection": { - "menuDefinitions": [] - }, - "packageNamespace": "", - "appIsModular": false - } -} \ No newline at end of file diff --git a/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c_menu.cpp b/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c_menu.cpp deleted file mode 100644 index 4561cbe1..00000000 --- a/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c_menu.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#include -#include "stm32EncoderLcdI2c_menu.h" - -// Global variable declarations -const ConnectorLocalInfo applicationInfo = { "Space Heater", "b04706cc-5acd-477a-81b9-0770e37a9546" }; - -LiquidCrystal lcd(2, 1, 0, 4, 5, 6, 7); -LiquidCrystalRenderer renderer(lcd, 16, 2); - -// Global Menu Item declarations -const BooleanMenuInfo minfoSettingsFan = { "Fan", 6, 0xffff, 1, NO_CALLBACK, NAMING_TRUE_FALSE }; -BooleanMenuItem menuSettingsFan(&minfoSettingsFan, true, NULL); -const AnalogMenuInfo minfoSettingsTemp = { "Temp", 5, 2, 100, NO_CALLBACK, 0, 1, "C" }; -AnalogMenuItem menuSettingsTemp(&minfoSettingsTemp, 0, &menuSettingsFan); -RENDERING_CALLBACK_NAME_INVOKE(fnSettingsRtCall, backSubItemRenderFn, "Settings", -1, NO_CALLBACK) -const SubMenuInfo minfoSettings = { "Settings", 4, 0xffff, 0, NO_CALLBACK }; -BackMenuItem menuBackSettings(fnSettingsRtCall, &menuSettingsTemp); -SubMenuItem menuSettings(&minfoSettings, &menuBackSettings, NULL); -const AnalogMenuInfo minfoTempHtr = { "Temp htr", 3, 0xffff, 1500, NO_CALLBACK, 0, 10, "C" }; -AnalogMenuItem menuTempHtr(&minfoTempHtr, 0, &menuSettings); -const AnalogMenuInfo minfoTempRoom = { "Temp room", 2, 0xffff, 1500, NO_CALLBACK, 0, 10, "C" }; -AnalogMenuItem menuTempRoom(&minfoTempRoom, 0, &menuTempHtr); -const char enumStrStatus_0[] = "HeatFan"; -const char enumStrStatus_1[] = "Heater"; -const char enumStrStatus_2[] = "Fan"; -const char enumStrStatus_3[] = "Error"; -const char enumStrStatus_4[] = "Off"; -const char* const enumStrStatus[] = { enumStrStatus_0, enumStrStatus_1, enumStrStatus_2, enumStrStatus_3, enumStrStatus_4 }; -const EnumMenuInfo minfoStatus = { "Status", 1, 0xffff, 4, NO_CALLBACK, enumStrStatus }; -EnumMenuItem menuStatus(&minfoStatus, 4, &menuTempRoom); - -void setupMenu() { - // First we set up eeprom and authentication (if needed). - - // Now add any readonly, non-remote and visible flags. - menuTempHtr.setReadOnly(true); - menuTempRoom.setReadOnly(true); - menuStatus.setReadOnly(true); - - // Code generated by plugins. - lcd.setIoAbstraction(ioFrom8574(0x47, 0xff, &i2cDisplay)); - lcd.begin(16, 2); - renderer.setUpdatesPerSecond(2); - lcd.configureBacklightPin(3); - lcd.backlight(); - switches.init(internalDigitalIo(), SWITCHES_NO_POLLING, true); - menuMgr.initForEncoder(&renderer, &menuStatus, PC_8, PC_10, PC_9); -} - diff --git a/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c_menu.h b/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c_menu.h deleted file mode 100644 index c1ff6121..00000000 --- a/examples/mbed/stm32EncoderLcdI2c/stm32EncoderLcdI2c_menu.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - The code in this file uses open source libraries provided by thecoderscorner - - DO NOT EDIT THIS FILE, IT WILL BE GENERATED EVERY TIME YOU USE THE UI DESIGNER - INSTEAD EITHER PUT CODE IN YOUR SKETCH OR CREATE ANOTHER SOURCE FILE. - - All the variables you may need access to are marked extern in this file for easy - use elsewhere. - */ - -#ifndef MENU_GENERATED_CODE_H -#define MENU_GENERATED_CODE_H - -#include -#include - -#include -#include -#include -#include "tcMenuLiquidCrystal.h" - -// variables we declare that you may need to access -extern const PROGMEM ConnectorLocalInfo applicationInfo; -extern I2C i2cDisplay; -extern LiquidCrystal lcd; -extern LiquidCrystalRenderer renderer; - -// Any externals needed by IO expanders, EEPROMs etc - - -// Global Menu Item exports -extern BooleanMenuItem menuSettingsFan; -extern AnalogMenuItem menuSettingsTemp; -extern BackMenuItem menuBackSettings; -extern SubMenuItem menuSettings; -extern AnalogMenuItem menuTempHtr; -extern AnalogMenuItem menuTempRoom; -extern EnumMenuItem menuStatus; - -// Provide a wrapper to get hold of the root menu item and export setupMenu -inline MenuItem& rootMenuItem() { return menuStatus; } -void setupMenu(); - -// Callback functions must always include CALLBACK_FUNCTION after the return type -#define CALLBACK_FUNCTION - - -#endif // MENU_GENERATED_CODE_H diff --git a/examples/mbed/stm32EncoderLcdI2c/tcMenuLiquidCrystal.cpp b/examples/mbed/stm32EncoderLcdI2c/tcMenuLiquidCrystal.cpp deleted file mode 100644 index ea91c0c4..00000000 --- a/examples/mbed/stm32EncoderLcdI2c/tcMenuLiquidCrystal.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * LiquidCrystalIO renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - * - * LIBRARY REQUIREMENT - * This renderer is designed for use with this library: https://github.com/TcMenu/LiquidCrystalIO - */ - -#include "tcMenuLiquidCrystal.h" -#include "tcUtil.h" - -extern const ConnectorLocalInfo applicationInfo; - -LiquidCrystalRenderer::LiquidCrystalRenderer(LiquidCrystal& lcd, int dimX, int dimY) : BaseGraphicalRenderer(dimX, dimX, dimY, true, applicationInfo.name) { - this->lcd = &lcd; - this->backChar = '<'; - this->forwardChar = '>'; - this->editChar = '='; -} - -void LiquidCrystalRenderer::initialise() { - // first we create the custom characters for any title widget. - // we iterate over each widget then over each each icon. - TitleWidget* wid = firstWidget; - int charNo = 0; - while(wid != nullptr) { - serlogF2(SER_TCMENU_INFO, "Title widget present max=", wid->getMaxValue()); - for(int i = 0; i < wid->getMaxValue(); i++) { - serlogF2(SER_TCMENU_DEBUG, "Creating char ", charNo); - lcd->createCharPgm((uint8_t)charNo, wid->getIcon(i)); - charNo++; - } - wid = wid->getNext(); - } - lcd->clear(); - - BaseGraphicalRenderer::initialise(); -} - -LiquidCrystalRenderer::~LiquidCrystalRenderer() { - delete this->buffer; - delete dialog; -} - -void LiquidCrystalRenderer::setEditorChars(char back, char forward, char edit) { - backChar = back; - forwardChar = forward; - editChar = edit; -} - -void LiquidCrystalRenderer::drawWidget(Coord where, TitleWidget *widget, color_t, color_t) { - char ch = char(widget->getHeight() + widget->getCurrentState()); - serlogF4(SER_TCMENU_DEBUG, "draw widget", where.x, where.y, (int)ch); - lcd->setCursor(where.x, where.y); - widget->setChanged(false); - lcd->write(ch); -} - -int calculateOffset(GridPosition::GridJustification just, int totalLen, const char* sz) { - int len = strlen(sz); - auto actualJust = coreJustification(just); - if(len > totalLen || actualJust == GridPosition::CORE_JUSTIFY_LEFT) return 0; - - if(actualJust == tcgfx::GridPosition::CORE_JUSTIFY_RIGHT) { - return (totalLen - len) - 1; - } - else { - // must be centered in this case. - return (totalLen - len) / 2; - } -} - -void copyIntoBuffer(char* buffer, const char* source, int offset, int bufferLen) { - auto len = strlen(source); - for(size_t i=0; i= bufferLen) return; - buffer[pos] = source[i]; - } -} - -void LiquidCrystalRenderer::drawMenuItem(GridPositionRowCacheEntry* entry, Coord where, Coord areaSize, bool /*ignored*/) { - auto* theItem = entry->getMenuItem(); - theItem->setChanged(false); - char sz[21]; - - if(entry->getPosition().getJustification() == GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) { - buffer[0] = theItem->isEditing() ? editChar : (theItem->isActive() ? forwardChar : ' '); - lcd->setCursor(where.x, where.y); - int offs = 1; - uint8_t finalPos = theItem->copyNameToBuffer(buffer, offs, bufferSize); - for(uint8_t i = finalPos; i < uint8_t(areaSize.x); ++i) buffer[i] = 32; - buffer[bufferSize] = 0; - copyMenuItemValue(theItem, sz, sizeof sz); - uint8_t count = strlen(sz); - int cpy = bufferSize - count; - strcpy(buffer + cpy, sz); - if(theItem == menuMgr.getCurrentEditor() && menuMgr.getEditorHints().getEditorRenderingType() != CurrentEditorRenderingHints::EDITOR_REGULAR) { - setupEditorPlacement(where.x + cpy + menuMgr.getEditorHints().getStartIndex(), where.y); - } - } - else { - for(size_t i = 1; i < (sizeof(sz) - 1); ++i) buffer[i] = 32; - buffer[sizeof(sz)-1] = 0; - uint8_t valueStart = 0; - if(itemNeedsName(entry->getPosition().getJustification())) { - theItem->copyNameToBuffer(sz, sizeof sz); - valueStart += strlen(sz); - } - if(itemNeedsValue(entry->getPosition().getJustification())) { - sz[valueStart] = 32; - valueStart++; - copyMenuItemValue(entry->getMenuItem(), sz + valueStart, sizeof(sz) - valueStart); - serlogF2(SER_TCMENU_DEBUG, "Value ", sz); - } - int position = calculateOffset(entry->getPosition().getJustification(), int(areaSize.x) + 1, sz); - copyIntoBuffer(&buffer[1], sz, position, bufferSize); - buffer[0] = theItem->isEditing() ? editChar : (theItem->isActive() ? forwardChar : ' '); - buffer[min(uint8_t(areaSize.x + 1), bufferSize)] = 0; - lcd->setCursor(where.x, where.y); - if(theItem == menuMgr.getCurrentEditor() && menuMgr.getEditorHints().getEditorRenderingType() != CurrentEditorRenderingHints::EDITOR_REGULAR) { - setupEditorPlacement(where.x + valueStart + menuMgr.getEditorHints().getStartIndex(), where.y); - } - } - serlogF4(SER_TCMENU_DEBUG, "Buffer: ", where.x,where.y, buffer); - lcd->print(buffer); -} - -void LiquidCrystalRenderer::setupEditorPlacement(int32_t x, int32_t y) { - lcdEditorCursorX = min((width - 1), x); - lcdEditorCursorY = y; -} - -void LiquidCrystalRenderer::drawingCommand(RenderDrawingCommand command) { - switch (command) { - case DRAW_COMMAND_CLEAR: - lcd->clear(); - break; - case DRAW_COMMAND_START: - if(lcdEditorCursorX != 0xFF) { - if(menuMgr.getCurrentEditor() == nullptr) { - lcdEditorCursorX = 0xFF; // edit has ended, clear our status - lcdEditorCursorY = 0xFF; - } - lcd->noCursor(); // always turn off the cursor while we draw - } - case DRAW_COMMAND_ENDED: - if(lcdEditorCursorX != 0xFF) { - lcd->setCursor(lcdEditorCursorX, lcdEditorCursorY); - serlogF3(SER_TCMENU_DEBUG, "Editor cursor: ", lcdEditorCursorX, lcdEditorCursorY); - lcd->cursor(); // re-enable the cursor after drawing. - } - break; - default: - break; - } -} - -void LiquidCrystalRenderer::fillWithBackgroundTo(int endPoint) { - for(uint16_t y=endPoint;ysetCursor(0, y); - for(uint16_t x=0;xprint(' '); - } - } -} - -BaseDialog* LiquidCrystalRenderer::getDialog() { - if(dialog == nullptr) { - dialog = new MenuBasedDialog(); - } - return dialog; -} diff --git a/examples/mbed/stm32EncoderLcdI2c/tcMenuLiquidCrystal.h b/examples/mbed/stm32EncoderLcdI2c/tcMenuLiquidCrystal.h deleted file mode 100644 index bd81d06a..00000000 --- a/examples/mbed/stm32EncoderLcdI2c/tcMenuLiquidCrystal.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). - * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. - */ - -/** - * @file tcMenuLiquidCrystal.h - * - * LiquidCrystalIO renderer that renders menus onto this type of display. This file is a plugin file and should not - * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, - * make sure to rename it first. - * - * LIBRARY REQUIREMENT - * This renderer is designed for use with this library: https://github.com/TcMenu/LiquidCrystalIO - */ - -#ifndef _TCMENU_LIQUID_CRYSTAL_H -#define _TCMENU_LIQUID_CRYSTAL_H - -#include "tcMenu.h" -#include -#include -#include - -using namespace tcgfx; - -/** - * A renderer that can renderer onto a LiquidCrystal display and supports the concept of single level - * sub menus, active items and editing. - */ -class LiquidCrystalRenderer : public BaseGraphicalRenderer { -private: - LiquidCrystal* lcd; - NullItemDisplayPropertiesFactory propertiesFactory; - char backChar; - char forwardChar; - char editChar; - uint8_t lcdEditorCursorX = 0xFF; - uint8_t lcdEditorCursorY = 0xFF; -public: - LiquidCrystalRenderer(LiquidCrystal& lcd, int dimX, int dimY); - ~LiquidCrystalRenderer() override; - void initialise() override; - void setTitleRequired(bool titleRequired) { titleMode = (titleRequired) ? TITLE_FIRST_ROW : NO_TITLE; } - void setEditorChars(char back, char forward, char edit); - - uint8_t getRows() {return height;} - LiquidCrystal* getLCD() {return lcd;} - BaseDialog* getDialog() override; - - void drawingCommand(RenderDrawingCommand command) override; - void drawWidget(Coord where, TitleWidget* widget, color_t colorFg, color_t colorBg) override; - void drawMenuItem(GridPositionRowCacheEntry* entry, Coord where, Coord areaSize, bool drawAll) override; - void fillWithBackgroundTo(int endPoint) override; - - ItemDisplayPropertiesFactory &getDisplayPropertiesFactory() override { return propertiesFactory; } - NullItemDisplayPropertiesFactory &getLcdDisplayPropertiesFactory() { return propertiesFactory; } - - void setupEditorPlacement(int32_t x, int32_t y); -}; - -#endif // _TCMENU_LIQUID_CRYSTAL_H diff --git a/examples/mbed/stm32EncoderLcdI2c/tcmenu_main.cpp b/examples/mbed/stm32EncoderLcdI2c/tcmenu_main.cpp deleted file mode 100644 index 640173f7..00000000 --- a/examples/mbed/stm32EncoderLcdI2c/tcmenu_main.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "stm32EncoderLcdI2c_menu.h" - -// Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ - -// -// Set up the logging support in IoAbstraction. For mbed we rely on an MBedLogger being created. -// -BufferedSerial serPort(USBTX, USBRX); -MBedLogger LoggingPort(serPort); - -I2C i2cDisplay(PB_9, PB_8); - -void setup() { - serPort.set_baud(115200); - serdebugF("LCD mbed is starting"); - setupMenu(); -} - -int main() { - setup(); - while(1) { - taskManager.runLoop(); - } -} diff --git a/examples/mbed/stm32OledEncoder/ScreenSaverCustomDrawing.h b/examples/mbed/stm32OledEncoder/ScreenSaverCustomDrawing.h index a6f3df3e..a05bdbbe 100644 --- a/examples/mbed/stm32OledEncoder/ScreenSaverCustomDrawing.h +++ b/examples/mbed/stm32OledEncoder/ScreenSaverCustomDrawing.h @@ -3,7 +3,7 @@ #define TCMENUEXAMPLE_SCREENSAVERCUSTOMDRAWING_H #include "generated/stm32OledEncoder_menu.h" -#include +#include /** * Here we implement the custom drawing class so that we can register for drawing and reset events with it. * When the display times out the reset method is called, where in this case we take over the display. Then @@ -34,9 +34,8 @@ class ScreenSaverCustomDrawing : public CustomDrawing { offsetX = 16; offsetY = 16; - gfx.clearDisplay(); - gfx.setFont(&FreeSans9pt7b); - gfx.setTextSize(1); + gfx->clearDisplay(); + gfx->setFont(OpenSansRegular8pt); } /** @@ -55,22 +54,22 @@ class ScreenSaverCustomDrawing : public CustomDrawing { offsetY = rand() % 25; } - gfx.clearDisplay(); + gfx->clearDisplay(); - gfx.setCursor(offsetX, offsetY + 12); - gfx.print("Mbed demo"); + gfx->setCursor(offsetX, offsetY + 12); + gfx->print("Mbed demo"); - gfx.setFont(nullptr); - gfx.setCursor(5 + offsetX, 20 + offsetY); + gfx->setFont(OpenSansRegular8pt); + gfx->setCursor(5 + offsetX, 20 + offsetY); char sz[32]; menuRTCDate.copyValue(sz, sizeof sz); - gfx.print(sz); + gfx->print(sz); - gfx.setCursor(5 + offsetX, 32 + offsetY); + gfx->setCursor(5 + offsetX, 32 + offsetY); menuRTCTime.copyValue(sz, sizeof sz); - gfx.print(sz); + gfx->print(sz); - gfx.display(); + gfx->display(); renderTickCount++; } diff --git a/examples/mbed/stm32OledEncoder/ThemeMonoInverse.h b/examples/mbed/stm32OledEncoder/ThemeMonoInverse.h deleted file mode 100644 index 1d689400..00000000 --- a/examples/mbed/stm32OledEncoder/ThemeMonoInverse.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef TCMENU_THEME_MONO_INVERSE -#define TCMENU_THEME_MONO_INVERSE - -color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; -color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; - -#define TITLE_PADDING 2 -#define TITLE_SPACING 2 - -void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); - auto& factory = bgr.getGraphicsPropertiesFactory(); - - factory.setSelectedColors(0, 2); - - MenuPadding titlePadding(TITLE_PADDING); - MenuPadding itemPadding(1); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); - - factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); - factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); - - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, - TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, - 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); - - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //TCMENU_THEME_MONO_INVERSE \ No newline at end of file diff --git a/examples/mbed/stm32OledEncoder/ThemeMonoInverseBuilder.h b/examples/mbed/stm32OledEncoder/ThemeMonoInverseBuilder.h new file mode 100644 index 00000000..1ef2d8a6 --- /dev/null +++ b/examples/mbed/stm32OledEncoder/ThemeMonoInverseBuilder.h @@ -0,0 +1,60 @@ +#ifndef TCMENU_THEME_MONO_INVERSE +#define TCMENU_THEME_MONO_INVERSE + +#include + +color_t defaultItemPaletteMono[] = {1, 0, 1, 1}; +color_t defaultTitlePaletteMono[] = {0, 1, 0, 0}; + +#define TITLE_PADDING 2 +#define TITLE_SPACING 2 + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installMonoInverseTitleTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + themeBuilder.withSelectedColors(0, 2) + .dimensionsFromRenderer() + .withItemPadding(MenuPadding(1)) + .withRenderingSettings(titleMode, false) + .withPalette(defaultItemPaletteMono) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(1); + + if(needEditingIcons) { + themeBuilder.withStandardLowResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultTitleProperties() + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(defaultTitlePaletteMono) + .withPadding(MenuPadding(TITLE_PADDING)) + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .withSpacing(TITLE_SPACING) + .apply(); + + themeBuilder.defaultActionProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE) + .apply(); + + themeBuilder.defaultItemProperties() + .withJustification(tcgfx::GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.apply(); +} + +#endif //TCMENU_THEME_MONO_INVERSE diff --git a/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.cpp b/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.cpp index ae429434..91f71fa6 100644 --- a/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.cpp +++ b/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.cpp @@ -8,17 +8,20 @@ use elsewhere. */ +// Generated for mbed RTOS by TcMenu 4.3.1 on 2024-10-12T09:03:47.686418900Z. + #include #include "stm32OledEncoder_menu.h" -#include "../ThemeMonoInverse.h" +#include "../ThemeMonoInverseBuilder.h" +#include // Global variable declarations const ConnectorLocalInfo applicationInfo = { "Demo mbed", "f5325e26-a7f6-40ff-876e-47afa06df532" }; TcMenuRemoteServer remoteServer(applicationInfo); HalStm32EepromAbstraction glBspRom; EepromAuthenticatorManager authManager(6); -Adafruit_SSD1306_Spi gfx(spi, PD_15, PF_12, PF_13, 64, 128, SSD_1306); -AdafruitDrawable gfxDrawable(&gfx); +AdafruitSSD1306Spi* gfx; +AdafruitDrawable gfxDrawable; GraphicsDeviceRenderer renderer(30, applicationInfo.name, &gfxDrawable); MbedEthernetInitialiser mbedEthInitialisation(3333); MBedEthernetTransport ethernetTransport; @@ -83,21 +86,22 @@ void setupMenu() { menuMgr.setAuthenticator(&authManager); // Now add any readonly, non-remote and visible flags. menuEdit.setReadOnly(true); - menuIP.setReadOnly(true); menuCommits.setReadOnly(true); - menuAuthenticator.setLocalOnly(true); + menuIP.setReadOnly(true); menuIoTMonitor.setLocalOnly(true); + menuAuthenticator.setLocalOnly(true); // Code generated by plugins and new operators. - gfx.setRotation(0); - gfx.begin(); + gfx = new AdafruitSSD1306Spi(SPIWithSettings(&spi, PF_13, 10000000), PD_15, PF_12, 64, 128, ENCMODE_UTF8, SSD_1306); + gfx->setRotation(0); + gfx->begin(); renderer.setUpdatesPerSecond(5); + gfxDrawable.setGraphics(gfx); + gfxDrawable.setFontHandler(gfx->getFontHandler()); switches.init(internalDigitalIo(), SWITCHES_POLL_EVERYTHING, true); menuMgr.initForEncoder(&renderer, &menuRTCDate, PC_8, PC_10, PC_9); remoteServer.addConnection(ðernetConnection); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_ALWAYS); - renderer.setUseSliderForAnalog(false); - installMonoInverseTitleTheme(renderer, MenuFontDef(nullptr, 1), MenuFontDef(nullptr, 1), true); + installMonoInverseTitleTheme(renderer, MenuFontDef(&OpenSansRegular7pt, 0), MenuFontDef(&OpenSansRegular7pt, 0), true, BaseGraphicalRenderer::TITLE_ALWAYS, true); // We have an IoT monitor, register the server menuIoTMonitor.setRemoteServer(remoteServer); diff --git a/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.h b/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.h index 1fe0c3b5..ff071d8e 100644 --- a/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.h +++ b/examples/mbed/stm32OledEncoder/generated/stm32OledEncoder_menu.h @@ -14,6 +14,7 @@ #include #include +#include #include "Adafruit_SSD1306.h" #include "tcMenuAdaFruitGfxMono.h" #include "MBedEthernetTransport.h" @@ -31,10 +32,11 @@ extern const PROGMEM ConnectorLocalInfo applicationInfo; extern TcMenuRemoteServer remoteServer; extern SPI spi; -extern Adafruit_SSD1306_Spi gfx; +extern AdafruitSSD1306Spi* gfx; extern AdafruitDrawable gfxDrawable; extern GraphicsDeviceRenderer renderer; extern MbedEthernetInitialiser mbedEthInitialisation; +extern const UnicodeFont OpenSansRegular7pt[]; // Any externals needed by IO expanders, EEPROMs etc diff --git a/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.cpp b/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.cpp index 339ca403..e39b1fd7 100644 --- a/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.cpp +++ b/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.cpp @@ -21,7 +21,7 @@ using namespace tcgfx; void AdafruitDrawable::transaction(bool isStarting, bool redrawNeeded) { if(!isStarting && redrawNeeded) { - reinterpret_cast(graphics)->display(); + reinterpret_cast(graphics)->display(); } } diff --git a/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.h b/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.h index 23bdb313..1753ff84 100644 --- a/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.h +++ b/examples/mbed/stm32OledEncoder/generated/tcMenuAdaFruitGfxMono.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/examples/mbed/stm32OledEncoder/stm32OledEncoder.emf b/examples/mbed/stm32OledEncoder/stm32OledEncoder.emf index a343c933..b40f9db6 100644 --- a/examples/mbed/stm32OledEncoder/stm32OledEncoder.emf +++ b/examples/mbed/stm32OledEncoder/stm32OledEncoder.emf @@ -317,15 +317,20 @@ ], "codeOptions": { "embeddedPlatform": "MBED_RTOS", - "lastDisplayUuid": "8a15d500-410f-489d-b3dc-540b05e630ed", + "lastDisplayUuid": "61159C5B-F23A-4050-980F-A8FE114E2965", "lastInputUuid": "6dd87e7d-e751-4912-a70d-91793b1d3d87", "lastRemoteUuids": [ "27e7a502-330e-4570-9f8e-bd26ac88051f" ], - "lastThemeUuid": "0dd60ceb-7e0f-46e2-8d40-b264eb3aa7e0", + "lastThemeUuid": "396ED4DF-AD7B-4951-A848-A9E5838A549B", "applicationUUID": "f5325e26-a7f6-40ff-876e-47afa06df532", "applicationName": "Demo mbed", "lastProperties": [ + { + "name": "BUS_TYPE", + "latestValue": "SPI", + "subsystem": "DISPLAY" + }, { "name": "SERIAL_BUS", "latestValue": "spi", @@ -352,8 +357,8 @@ "subsystem": "DISPLAY" }, { - "name": "BUS_TYPE", - "latestValue": "SPI", + "name": "DISPLAY_I2C_ADDR", + "latestValue": "0xFF", "subsystem": "DISPLAY" }, { @@ -371,6 +376,11 @@ "latestValue": "PD_15", "subsystem": "DISPLAY" }, + { + "name": "DISPLAY_SPI_FREQ", + "latestValue": "10000000", + "subsystem": "DISPLAY" + }, { "name": "DISPLAY_ROTATION", "latestValue": "0", @@ -381,6 +391,11 @@ "latestValue": "5", "subsystem": "DISPLAY" }, + { + "name": "TEXT_ENCODING", + "latestValue": "ENCMODE_UTF8", + "subsystem": "DISPLAY" + }, { "name": "SW_POLLING_MODE", "latestValue": "SWITCHES_POLL_EVERYTHING", @@ -448,12 +463,12 @@ }, { "name": "ITEM_FONT", - "latestValue": "def:,1", + "latestValue": "ada:OpenSansRegular7pt,0", "subsystem": "THEME" }, { "name": "TITLE_FONT", - "latestValue": "def:,1", + "latestValue": "ada:OpenSansRegular7pt,0", "subsystem": "THEME" }, { @@ -473,7 +488,7 @@ }, { "name": "USE_TC_UNICODE", - "latestValue": "false", + "latestValue": "true", "subsystem": "THEME" } ], @@ -490,8 +505,7 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] + "appIsModular": false }, "stringLists": [] } \ No newline at end of file diff --git a/examples/mbed/stm32f429FrameBuffer/ThemeCoolBlueModern.h b/examples/mbed/stm32f429FrameBuffer/ThemeCoolBlueModern.h deleted file mode 100644 index 9e505828..00000000 --- a/examples/mbed/stm32f429FrameBuffer/ThemeCoolBlueModern.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Cool blue modern theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. - * This file will not be updated by the designer, you can edit. - */ -#ifndef THEME_COOL_BLUE -#define THEME_COOL_BLUE - -#include - -const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(0,133,255)}; -const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; -const color_t coolBlueActionPalette[] = {RGB(255, 255, 255), RGB(0,45,120), RGB(20,133,255), RGB(31,100,178)}; - -#define ACTION_BORDER_WIDTH 0 - -void installCoolBlueModernTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { - // here we get a refrerence to the drawable and then set the dimensions. - auto* rootDrawable = bgr.getDeviceDrawable(); - bgr.setDisplayDimensions(rootDrawable->getDisplayDimensions().x, rootDrawable->getDisplayDimensions().y); - - // we need a reference to the factory object that we will use to configure the drawing. - auto& factory = bgr.getGraphicsPropertiesFactory(); - - // change the selected colours. - factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); - - // for this theme we use the same size padding for each case, we need touchable items. We calculate the height too - MenuPadding allPadding(4, 3, 4, 3); - int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, allPadding); - int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, allPadding); - - // now we configure the drawing for each item type - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, allPadding, titleFont.fontData, titleFont.fontMag, 3, titleHeight, - GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, - GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); - factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueActionPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, - GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(ACTION_BORDER_WIDTH)); - - // and lastly, whenever changing the configuration, we must refresh. - tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); -} - -#endif //THEME_COOL_BLUE \ No newline at end of file diff --git a/examples/mbed/stm32f429FrameBuffer/ThemeCoolBlueModernBuilder.h b/examples/mbed/stm32f429FrameBuffer/ThemeCoolBlueModernBuilder.h new file mode 100644 index 00000000..071c7e7e --- /dev/null +++ b/examples/mbed/stm32f429FrameBuffer/ThemeCoolBlueModernBuilder.h @@ -0,0 +1,71 @@ +/** + * Cool blue modern theme by tcMenu organisation. This is part of the standard themes shipped with TcMenu. + * This file will not be updated by the designer, you can edit. + * See https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/themes/rendering-with-themes-icons-grids/ + */ + +#ifndef THEME_COOL_BLUE +#define THEME_COOL_BLUE + +#include + +const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; +const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; +const color_t coolBlueActionPalette[] = {RGB(255, 255, 255), RGB(0,45,120), RGB(20,133,255), RGB(31,100,178)}; + +#define ACTION_BORDER_WIDTH 0 +#define USE_SLIDER_FOR_ANALOG true + +/** + * This is one of the stock themes, you can modify it to meet your requirements, and it will not be updated by tcMenu + * Designer unless you delete it. This sets up the fonts, spacing and padding for all items. + * @param gr the graphical renderer + * @param itemFont the font for items + * @param titleFont the font for titles + * @param needEditingIcons if editing icons are needed + */ +void installCoolBlueModernTheme(GraphicsDeviceRenderer& gr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, + bool needEditingIcons, BaseGraphicalRenderer::TitleMode titleMode, bool useUnicode) { + + // See https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/themes/rendering-with-themes-icons-grids/ + TcThemeBuilder themeBuilder(gr); + + themeBuilder.dimensionsFromRenderer() + .withSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)) + .withItemPadding(MenuPadding(4, 3, 4, 3)) + .withTitlePadding(MenuPadding(4, 3, 4, 3)) + .withRenderingSettings(titleMode, USE_SLIDER_FOR_ANALOG) + .withPalette(coolBlueItemPalette) + .withNativeFont(itemFont.fontData, itemFont.fontMag) + .withSpacing(2); + + if(needEditingIcons) { + themeBuilder.withStandardMedResCursorIcons(); + } + + if(useUnicode) { + themeBuilder.enableTcUnicode(); + } + + themeBuilder.defaultItemProperties() + .withJustification(GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT) + .apply(); + + themeBuilder.defaultTitleProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withNativeFont(titleFont.fontData, titleFont.fontMag) + .withPalette(coolBlueTitlePalette) + .withSpacing(3) + .apply(); + + + themeBuilder.defaultActionProperties() + .withJustification(GridPosition::JUSTIFY_CENTER_WITH_VALUE) + .withPalette(coolBlueActionPalette) + .withBorder(MenuBorder(ACTION_BORDER_WIDTH)) + .apply(); + + themeBuilder.apply(); +} + +#endif //THEME_COOL_BLUE \ No newline at end of file diff --git a/examples/mbed/stm32f429FrameBuffer/dashboardConfig.cpp b/examples/mbed/stm32f429FrameBuffer/dashboardConfig.cpp index 88f021d1..93c91a3d 100644 --- a/examples/mbed/stm32f429FrameBuffer/dashboardConfig.cpp +++ b/examples/mbed/stm32f429FrameBuffer/dashboardConfig.cpp @@ -34,7 +34,7 @@ DashDrawParametersIntUpdateRange::IntColorRange drawVoltageColorRanges[] { {LCD_WHITE, LCD_BLUE, 2440, 3000} }; DashDrawParametersIntUpdateRange drawVoltageWithIntRange(LCD_BLACK, LCD_LIGHT_BLUE, LCD_BLACK, LCD_YELLOW, - &RobotoMedium24, drawVoltageColorRanges, 2); + OpenSansCyrillicLatin14, drawVoltageColorRanges, 2); // As above we create another one for the analog item, it has two ranges. // Note that this is a parameter, not the actual dashboard item, they are defined below @@ -43,7 +43,7 @@ DashDrawParametersIntUpdateRange::IntColorRange drawPowerColorRanges[] { {LCD_YELLOW, LCD_RED, 2100, 3000} }; DashDrawParametersIntUpdateRange drawPowerValueWithIntRange(LCD_BLACK, LCD_LIGHT_BLUE, LCD_BLACK, LCD_YELLOW, - &RobotoMedium24, drawPowerColorRanges, 2); + OpenSansCyrillicLatin14, drawPowerColorRanges, 2); // // Although the dashboard support provides a wide range of menu drawing capabilities, it does not cover every case, @@ -52,9 +52,9 @@ DashDrawParametersIntUpdateRange drawPowerValueWithIntRange(LCD_BLACK, LCD_LIGHT // to the encoder state. // // For drawing onto device drawable see: -// https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/rendering-with-tcmenu-lcd-tft-oled/#drawing-direct-to-the-display-with-devicedrawabl -// For more on the delegate class and all the points where you can extend -// https://www.thecoderscorner.com/ref-docs/tcmenu/html/class_drawable_dashboard_delegate.html +// https://tcmenu.github.io/documentation/arduino-libraries//tc-menu/rendering-with-tcmenu-lcd-tft-oled/#drawing-direct-to-the-display-with-devicedrawabl +// For more on the dashboard, delegate class and all the points where you can extend +// https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/renderer-take-over-display/ // class MyDrawableDashboardDelegate : public DrawableDashboardDelegate { private: @@ -63,9 +63,9 @@ class MyDrawableDashboardDelegate : public DrawableDashboardDelegate { int lastEncoderTurn = 0; public: MyDrawableDashboardDelegate() : button1(Coord(10, 240), Coord(105, 60), LCD_LIGHT_BLUE, LCD_BLACK, LCD_SEL_BLUE, "AC", - DeviceFontDrawingMode(&RobotoMedium24)), + DeviceFontDrawingMode(OpenSansCyrillicLatin14)), button2(Coord(125, 240), Coord(105, 60), LCD_LIGHT_BLUE, LCD_BLACK, LCD_SEL_BLUE, "Batt", - DeviceFontDrawingMode(&RobotoMedium24)) { } + DeviceFontDrawingMode(OpenSansCyrillicLatin14)) { } // this is called before the dashboard titles are drawn when first presented. // you return true to tell the core code that you've already cleared the screen, otherwise false. @@ -92,7 +92,7 @@ class MyDrawableDashboardDelegate : public DrawableDashboardDelegate { color_t palette[2] = { LCD_LIGHT_BLUE, RGB(0, 0, 0) }; DeviceDrawableHelper helper(dr, palette, 2, Coord(10, 10), Coord(80, 25)); helper.getDrawable()->setDrawColor(palette[0]); - helper.setFont(DeviceFontDrawingMode(&RobotoMedium24)); + helper.setFont(DeviceFontDrawingMode(OpenSansCyrillicLatin14)); helper.getDrawable()->drawBox(helper.offsetLocation(Coord(10, 10)), Coord(80, 25), true); helper.drawText(helper.offsetLocation(Coord(12, 10)), palette[1], "Power"); helper.endDraw(); diff --git a/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer.emf b/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer.emf index 6504800b..06237cf3 100644 --- a/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer.emf +++ b/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer.emf @@ -424,7 +424,7 @@ "lastRemoteUuids": [ "2c101fec-1f7d-4ff3-8d2b-992ad41e7fcb" ], - "lastThemeUuid": "850dc0a3-f534-47c2-94d8-1e64ff368a54", + "lastThemeUuid": "1947F585-9D36-448C-8A80-B425686107BD", "applicationUUID": "4df3d784-674a-4a3d-bcee-54a49693788e", "applicationName": "Factory", "lastProperties": [ @@ -490,12 +490,12 @@ }, { "name": "ITEM_FONT", - "latestValue": "ada:OpenSansCyrillicLatin18,0", + "latestValue": "ada:OpenSansCyrillicLatin14,0", "subsystem": "THEME" }, { "name": "TITLE_FONT", - "latestValue": "ada:RobotoMedium24,1", + "latestValue": "ada:RobotoMedium24,0", "subsystem": "THEME" }, { @@ -537,8 +537,7 @@ "menuDefinitions": [] }, "packageNamespace": "", - "appIsModular": false, - "listOfEmbeddedForms": [] + "appIsModular": false }, "stringLists": [ { diff --git a/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.cpp b/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.cpp index fc76f0e9..2998c3fc 100644 --- a/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.cpp +++ b/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.cpp @@ -8,10 +8,12 @@ use elsewhere. */ +// Generated for mbed RTOS by TcMenu 4.3.1 on 2024-10-12T09:55:43.637853300Z. + #include #include "stm32f429FrameBuffer_menu.h" -#include "ThemeCoolBlueModern.h" -#include +#include "ThemeCoolBlueModernBuilder.h" +#include #include // Global variable declarations @@ -105,9 +107,6 @@ void setupMenu() { renderer.setUpdatesPerSecond(10); touchScreen.start(); menuMgr.initWithoutInput(&renderer, &menuPower); - renderer.setTitleMode(BaseGraphicalRenderer::TITLE_FIRST_ROW); - renderer.setUseSliderForAnalog(true); - renderer.enableTcUnicode(); - installCoolBlueModernTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin18, 0), MenuFontDef(&RobotoMedium24, 1), false); + installCoolBlueModernTheme(renderer, MenuFontDef(&OpenSansCyrillicLatin14, 0), MenuFontDef(&RobotoMedium24, 0), false, BaseGraphicalRenderer::TITLE_FIRST_ROW, true); } diff --git a/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.h b/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.h index cab4036a..4fadafd4 100644 --- a/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.h +++ b/examples/mbed/stm32f429FrameBuffer/stm32f429FrameBuffer_menu.h @@ -33,8 +33,8 @@ extern GraphicsDeviceRenderer renderer; extern StBspTouchInterrogator touchInterrogator; extern MenuTouchScreenManager touchScreen; extern tcextras::IoaTouchScreenCalibrator touchCalibrator; -extern const UnicodeFont OpenSansCyrillicLatin18[]; -extern const GFXfont RobotoMedium24; +extern const UnicodeFont OpenSansCyrillicLatin14[]; +extern const UnicodeFont RobotoMedium24[]; // Any externals needed by IO expanders, EEPROMs etc diff --git a/examples/mbed/stm32f429FrameBuffer/tcmenu_main.cpp b/examples/mbed/stm32f429FrameBuffer/tcmenu_main.cpp index 1b428917..168678d7 100644 --- a/examples/mbed/stm32f429FrameBuffer/tcmenu_main.cpp +++ b/examples/mbed/stm32f429FrameBuffer/tcmenu_main.cpp @@ -1,7 +1,7 @@ // An example showing how to setup and use the BSP framebuffer support for STM32 devices on mbed. Tested and working // with STM32F4x9 DISC1 // -// Getting started: https://www.thecoderscorner.com/products/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ +// Getting started: https://tcmenu.github.io/documentation/arduino-libraries/tc-menu/tcmenu-overview-quick-start/ #include #include "stm32f429FrameBuffer_menu.h" diff --git a/library.json b/library.json index 8ff1ca0d..878bf2f8 100644 --- a/library.json +++ b/library.json @@ -10,8 +10,8 @@ "authors": [ { - "name": "DaveTcc", - "url": "https://www.thecoderscorner.com", + "name": "tcmenu", + "url": "https://tcmenu.github.io/documentation/", "maintainer": true } ], @@ -19,14 +19,14 @@ [ { "name": "IoAbstraction", - "authors": "DaveTCC" + "authors": "tcmenu" }, { "name": "tcUnicodeHelper", - "authors": "DaveTCC" + "authors": "tcmenu" } ], - "version": "4.3.1", + "version": "4.4.0", "license": "Apache-2.0", "frameworks": "arduino, mbed", "platforms": "*" diff --git a/library.properties b/library.properties index ca625d5a..612dd9b6 100755 --- a/library.properties +++ b/library.properties @@ -4,7 +4,7 @@ # name=tcMenu -version=4.3.1 +version=4.4.0 maintainer=www.thecoderscorner.com author=davetcc category=Other @@ -12,3 +12,4 @@ url=https://github.com/TcMenu/tcMenuLib sentence=Menu library for Arduino with IoT capabilities that supports many input and display devices with a designer UI, code generator, CLI, and strong remote control capability. paragraph=Menu library for Arduino with IoT capabilities supporting full multi level navigation. Complete with a designer UI and CLI that can round trip. It has plugins for Adafruit_GFX, U8G2, TFT_eSPI and LiquidCrystalIO. Input is supported from Touch, Rotary Encoder, Digital / Analog joysticks, DfRobot, Keypad and more. Any menu can be remotely using embedCONTROL UI / API over Ethernet2, UIP, STM32 Ethernet and Serial / Bluetooth. Even works with no local display for remote control only. depends=IoAbstraction,tcUnicodeHelper +architectures=* \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index fa5f5f65..19758738 100644 --- a/platformio.ini +++ b/platformio.ini @@ -3,9 +3,9 @@ framework = arduino lib_deps = SPI - davetcc/IoAbstraction@^4.0.2 - davetcc/tcUnicodeHelper@^1.0.0 - davetcc/LiquidCrystalIO@^1.4.3 + tcmenu/IoAbstraction@^4.0.2 + tcmenu/tcUnicodeHelper@^1.0.0 + tcmenu/LiquidCrystalIO@^1.4.3 bodmer/TFT_eSPI@^2.5.43 adafruit/Adafruit GFX Library@^1.11.9 adafruit/Adafruit BusIO@^1.16.1 @@ -32,6 +32,7 @@ lib_deps = SPIFFS olikraus/U8g2@^2.35.17 adafruit/Adafruit ILI9341@^1.6.1 + adafruit/Adafruit ST7735 and ST7789 Library@^1.10.4 [env:esp01_1m] platform = espressif8266 diff --git a/src/BaseRenderers.h b/src/BaseRenderers.h index 192a8f71..46f0d709 100755 --- a/src/BaseRenderers.h +++ b/src/BaseRenderers.h @@ -450,6 +450,7 @@ class BaseMenuRenderer : public MenuRenderer, Executable { * @param the first widget in a chain of widgets linked by next pointer. */ void setFirstWidget(TitleWidget* widget); + TitleWidget* getFirstWidget() { return this->firstWidget; } /** * Called when the menu has been altered, to reset the countdown to diff --git a/src/EditableLargeNumberMenuItem.cpp b/src/EditableLargeNumberMenuItem.cpp index fab21cbd..4792512f 100644 --- a/src/EditableLargeNumberMenuItem.cpp +++ b/src/EditableLargeNumberMenuItem.cpp @@ -32,7 +32,7 @@ uint32_t LargeFixedNumber::fromBcdPacked(int start, int end) { void LargeFixedNumber::convertToBcdPacked(uint32_t value, int start, int end) { uint32_t modulo = dpToDivisor((end - start) - 1); for (int i = start; i < end; i++) { - setDigit(i, min(9, int(value / modulo))); + setDigit(i, internal_min(9, int(value / modulo))); value = value % modulo; modulo /= 10L; } diff --git a/src/EepromItemStorage.cpp b/src/EepromItemStorage.cpp index 50f63d90..42956924 100644 --- a/src/EepromItemStorage.cpp +++ b/src/EepromItemStorage.cpp @@ -15,11 +15,11 @@ uint16_t saveRecursively(EepromAbstraction* eeprom, MenuItem* nextMenuItem) { uint16_t lastItemSaved = 0; while (nextMenuItem) { if (nextMenuItem->getMenuType() == MENUTYPE_SUB_VALUE) { - lastItemSaved = max(lastItemSaved, saveRecursively(eeprom, ((SubMenuItem *) nextMenuItem)->getChild())); + lastItemSaved = internal_max(lastItemSaved, saveRecursively(eeprom, ((SubMenuItem *) nextMenuItem)->getChild())); } else { saveMenuItem(eeprom, nextMenuItem); if(nextMenuItem->getEepromPosition() != 0xFFFF) { - lastItemSaved = max(lastItemSaved, nextMenuItem->getEepromPosition()); + lastItemSaved = internal_max(lastItemSaved, nextMenuItem->getEepromPosition()); } } nextMenuItem = nextMenuItem->getNext(); diff --git a/src/MenuItems.cpp b/src/MenuItems.cpp index 386e259d..1d1c9ad8 100755 --- a/src/MenuItems.cpp +++ b/src/MenuItems.cpp @@ -80,7 +80,7 @@ uint8_t MenuItem::copyNameToBuffer(char* buf, int offset, int size) const { uint16_t MenuItem::getId() const { - if (info == nullptr) { + if (info == nullptr || menuType == MENUTYPE_BACK_VALUE) { return asRuntimeItem(this)->getRuntimeId(); } diff --git a/src/MessageProcessors.cpp b/src/MessageProcessors.cpp index 2525c0c1..23381d6f 100644 --- a/src/MessageProcessors.cpp +++ b/src/MessageProcessors.cpp @@ -22,10 +22,6 @@ void CombinedMessageProcessor::initialise() { messageHandlers.add(MsgHandler(MSG_PAIR, fieldUpdatePairingMsg)); messageHandlers.add(MsgHandler(MSG_DIALOG, fieldUpdateDialogMsg)); messageHandlers.add(MsgHandler(MSG_HEARTBEAT, fieldUpdateHeartbeatMsg)); - if(flashedFormTemplates != nullptr) { - messageHandlers.add(MsgHandler(MSG_GET_FORMS_REQUEST, fieldGetFormNames)); - messageHandlers.add(MsgHandler(MSG_FORM_DATA_REQUEST, fieldHandleFormRequest)); - } } void CombinedMessageProcessor::newMsg(uint16_t msgType) { @@ -97,59 +93,6 @@ void fieldUpdateDialogMsg(TagValueRemoteConnector* connector, FieldAndValue* fie } -void fieldGetFormNames(TagValueRemoteConnector* connector, FieldAndValue* field, MessageProcessorInfo* info) { - if(field->fieldType == FVAL_END_MSG) { - connector->encodeCustomTagValMessage(MSG_GET_FORM_RESPONSE, [](TagValueTransport* transport) { - auto **allTemplates = CombinedMessageProcessor::getFormTemplatesInFlash(); - int i=0; - if(allTemplates != nullptr) { - while(auto* formInfo = (EmbedControlFlashedForm*)pgm_read_ptr(allTemplates)) { - char sz[24]; - strncpy_P(sz, (const char*)pgm_read_ptr(&formInfo->formName), sizeof(sz)); - sz[sizeof(sz)-1]=0; - transport->writeField(msgFieldToWord(FIELD_PREPEND_CHOICE, 'A' + i), sz); - i++; - allTemplates++; - } - } - transport->writeFieldInt(FIELD_NO_CHOICES, i); - }); - } -} - -void fieldHandleFormRequest(TagValueRemoteConnector* connector, FieldAndValue* field, MessageProcessorInfo* info) { - if(field->fieldType == FVAL_END_MSG) { - const auto **allTemplates = CombinedMessageProcessor::getFormTemplatesInFlash(); - int i=0; - if(allTemplates != nullptr) { - while (auto *formInfo = (EmbedControlFlashedForm *) pgm_read_ptr(allTemplates)) { - char sz[24]; - strncpy_P(sz, (const char*)pgm_read_ptr(&formInfo->formName), sizeof(sz)); - sz[sizeof(sz)-1]=0; - if(strcmp((const char*)info->custom.data, sz) == 0) { - info->formLoad.length = pgm_read_word(&formInfo->formDataLen); - info->formLoad.data = (const uint8_t*)pgm_read_ptr(&formInfo->formDataGzipped); - connector->encodeCustomBinaryMessage(MSG_FORM_DATA_RESPONSE, info->formLoad.length, [](TagValueTransport* transport, void* data) { - auto* lInfo = reinterpret_cast(data); - const uint8_t* d = lInfo->formLoad.data; - for(uint16_t i=0; i< lInfo->formLoad.length; ++i) { - transport->writeChar(pgm_read_byte(d++)); - } - }, info); - return; - } - allTemplates++; - } - } - connector->encodeAcknowledgement(0, ACK_ID_NOT_FOUND); - } else if(field->fieldType == FVAL_FIELD && field->field == FIELD_ID) { - strncpy((char*)info->custom.data, field->value, sizeof(info->custom.data)); - } else if(field->fieldType == FVAL_NEW_MSG) { - info->custom.data[0] = 0; - } -} - - void fieldUpdatePairingMsg(TagValueRemoteConnector* connector, FieldAndValue* field, MessageProcessorInfo* info) { if(field->fieldType == FVAL_END_MSG) return; diff --git a/src/RemoteAuthentication.cpp b/src/RemoteAuthentication.cpp index 50c4b837..7b799795 100644 --- a/src/RemoteAuthentication.cpp +++ b/src/RemoteAuthentication.cpp @@ -75,7 +75,8 @@ void EepromAuthenticatorManager::copyKeyNameToBuffer(int idx, char* buffer, int return; } - eeprom->readIntoMemArray(reinterpret_cast(buffer), eepromOffset(idx), min(bufSize, CLIENT_DESC_SIZE)); + auto maxSize = internal_min(bufSize, CLIENT_DESC_SIZE); + eeprom->readIntoMemArray(reinterpret_cast(buffer), eepromOffset(idx), maxSize); buffer[bufSize-1]=0; } diff --git a/src/RemoteConnector.cpp b/src/RemoteConnector.cpp index 0050a8ca..d2fad29b 100644 --- a/src/RemoteConnector.cpp +++ b/src/RemoteConnector.cpp @@ -162,6 +162,7 @@ void TagValueRemoteConnector::close() { if (transport->connected()) { encodeHeartbeat(HBMODE_ENDCONNECT); } + transport->flush(); transport->close(); if (isPairing()) stopPairing(); @@ -354,9 +355,9 @@ void TagValueRemoteConnector::encodeDialogMsg(uint8_t mode, uint8_t btn1, uint8_ transport->endMsg(); } -void TagValueRemoteConnector::encodeCustomTagValMessage(uint16_t msgType, void (*msgWriter)(TagValueTransport*)) { +void TagValueRemoteConnector::encodeCustomTagValMessage(uint16_t msgType, void (*msgWriter)(TagValueTransport*, void* data), void* data) { if(!prepareWriteMsg(msgType)) return; - msgWriter(transport); + msgWriter(transport, data); transport->endMsg(); serlogF2(SER_NETWORK_INFO, "Msg wr ", msgType); } @@ -403,7 +404,7 @@ bool TagValueRemoteConnector::prepareWriteMsg(uint16_t msgType) { return true; } -void TagValueRemoteConnector::encodeCustomBinaryMessage(uint16_t msgType, uint16_t len, void (*msgWriter)(TagValueTransport*, void* data), void* data) { +void TagValueRemoteConnector::encodeCustomBinaryMessage(uint16_t msgType, uint16_t len, void (*msgWriter)(TagValueTransport*, void* data, size_t len), void* data) { if(!transport->connected()) { logMessageHeader("Wr ErrB ", remoteNo, msgType); commsNotify(COMMSERR_WRITE_NOT_CONNECTED); @@ -413,7 +414,7 @@ void TagValueRemoteConnector::encodeCustomBinaryMessage(uint16_t msgType, uint16 transport->startBinMsg(msgType, len); ticksLastSend = 0; logMessageHeader("Bin Out ", remoteNo, msgType); - msgWriter(transport, data); + msgWriter(transport, data, len); transport->endMsg(); serlogF2(SER_NETWORK_INFO, "Bin write complete", msgType); } @@ -567,7 +568,8 @@ void TagValueRemoteConnector::encodeAcknowledgement(uint32_t correlation, AckRes if(!prepareWriteMsg(MSG_ACKNOWLEDGEMENT)) return; transport->writeFieldInt(FIELD_ACK_STATUS, status); char sz[10]; - ltoa(correlation, sz, 16); + sz[0]=0; + intToHexString(sz, sizeof sz, correlation, 8, false); transport->writeField(FIELD_CORRELATION, sz); transport->endMsg(); @@ -739,7 +741,7 @@ void TagValueTransport::writeFieldLong(uint16_t field, long value) { sz[2] = '='; sz[3] = 0; writeStr(sz); - ltoa(value, sz, 10); + ltoaClrBuff(sz, value, 9, NOT_PADDED, sizeof sz); writeStr(sz); writeChar('|'); } diff --git a/src/RemoteConnector.h b/src/RemoteConnector.h index 78677596..11c203de 100644 --- a/src/RemoteConnector.h +++ b/src/RemoteConnector.h @@ -253,38 +253,40 @@ class TagValueRemoteConnector { * Encode a custom message onto the wire in the TagVal protocol, provide the message type and a function that sets * the fields you wish to send. This works by you providing the type of message and a function that will set all the * fields by calling transport's add field methods. Once that method returns the message will be completed and - * sent on the wire. + * sent on the wire. Where myData can be a pointer to any data you need to provide, it allows you to get data into + * the lambda without enabling captures. * * ``` * // first we define out custom message, we'd define any custom fields the same way. * #define MSG_CUSTOM msgFieldToWord('Z','Z') * * // then we call the function to send the message, it wraps up the message for us. - * myConnector.encodeCustomTagValMessage(MSG_CUSTOM, [](TagValueTransport* transport) { + * myConnector.encodeCustomTagValMessage(MSG_CUSTOM, [](TagValueTransport* transport, void* myData) { * transport.writeField(FIELD_BUFFER, "12345"); * transport.writeFieldInt(FIELD_VERSION, 123); * transport.writeFieldLong(FIELD_HB_MILLISEC, 2039349L); - * }); + * }, myData); * ``` */ - void encodeCustomTagValMessage(uint16_t msgType, void (*msgWriter)(TagValueTransport*)); + void encodeCustomTagValMessage(uint16_t msgType, void (*msgWriter)(TagValueTransport*, void*), void*); /** * Encode a binary message onto the wire using your own format, note that the other end must be able to process this * type of message. Embed Control UI will not understand such custom messages. This works by you providing the type - * of message and a function that will set all the binary data direct to the transport using the write function. + * of message and a function that will set all the binary data direct to the transport using the write function. The + * myData parameter allows you to pass data into the lambda with enabling capture. * * ``` * // first we define out custom message, we'd define any custom fields the same way. * #define MSG_CUSTOM msgFieldToWord('Z','Z') * * // then we call the function to send the message, it wraps up the message for us. - * myConnector.encodeCustomBinaryMessage(MSG_CUSTOM, len, [](TagValueTransport* transport) { - * transport.write(binDataByte); - * }); + * myConnector.encodeCustomBinaryMessage(MSG_CUSTOM, len, [](TagValueTransport* transport, void* myData, size_t len) { + * transport.writeChar(binDataByte); + * }, myData); * ``` */ - void encodeCustomBinaryMessage(uint16_t msgType, uint16_t len, void (*msgWriter)(TagValueTransport*, void*), void* data = nullptr); + void encodeCustomBinaryMessage(uint16_t msgType, uint16_t len, void (*msgWriter)(TagValueTransport*, void*, size_t), void* data = nullptr); /** * Encodes a dialog message that the UI can use to render / remove a dialog from the display. diff --git a/src/RemoteTypes.h b/src/RemoteTypes.h index 32ffc076..57109c51 100644 --- a/src/RemoteTypes.h +++ b/src/RemoteTypes.h @@ -84,14 +84,6 @@ enum AckResponseStatus { #define MSG_CHANGE_INT msgFieldToWord('V', 'C') /** Message type defintion for a dialog change msg */ #define MSG_DIALOG msgFieldToWord('D', 'M') -/** Message definition for getting the list of forms in FLASH */ -#define MSG_GET_FORMS_REQUEST msgFieldToWord('F', 'G') -/** Message definition for responding with the list of forms in FLASH */ -#define MSG_GET_FORM_RESPONSE msgFieldToWord('F', 'N') -/** Message definition for requesting the form data from FLASH */ -#define MSG_FORM_DATA_REQUEST msgFieldToWord('F', 'R') -/** Message definition for responding in binary gzip with form data from FLASH */ -#define MSG_FORM_DATA_RESPONSE msgFieldToWord('F', 'D') #define FIELD_MSG_NAME msgFieldToWord('N', 'M') #define FIELD_VERSION msgFieldToWord('V', 'E') diff --git a/src/RuntimeMenuItem.cpp b/src/RuntimeMenuItem.cpp index f8197a92..43840a44 100644 --- a/src/RuntimeMenuItem.cpp +++ b/src/RuntimeMenuItem.cpp @@ -516,7 +516,7 @@ long parseIntUntilSeparator(const char* ptr, int& offset, size_t maximumDigits) offset++; } // collect the numerics - auto maxPos = min(maximumDigits, sizeof(sz) -1); + auto maxPos = internal_min(maximumDigits, sizeof(sz) -1); while(pos < maxPos && ptr[offset] && ptr[offset] >= '0' && ptr[offset] <= '9') { sz[pos++] = ptr[offset++]; } diff --git a/src/RuntimeMenuItem.h b/src/RuntimeMenuItem.h index bef21304..8c82f19e 100644 --- a/src/RuntimeMenuItem.h +++ b/src/RuntimeMenuItem.h @@ -15,7 +15,9 @@ #include "tcUtil.h" /** For items that dont need to have the same id each time (such as back menu items), we just randomly give them an ID */ -#define RANDOM_ID_START 50000 +#ifndef RANDOM_ID_START +#define RANDOM_ID_START 30000 +#endif /** For items that dont need to have the same id each time (such as back menu items), we just randomly give them an ID */ menuid_t nextRandomId(); diff --git a/src/ScrollChoiceMenuItem.cpp b/src/ScrollChoiceMenuItem.cpp index 0da1a4cf..feb98fe9 100644 --- a/src/ScrollChoiceMenuItem.cpp +++ b/src/ScrollChoiceMenuItem.cpp @@ -95,7 +95,7 @@ void ScrollChoiceMenuItem::valueAtPosition(char *buffer, size_t bufferSize, int return; } - auto safeSize = min((size_t)itemSize, bufferSize - 1); + auto safeSize = internal_min((size_t)itemSize, bufferSize - 1); if (rangeValues != nullptr) { serlogF4(SER_TCMENU_DEBUG, "Start Cached ", idx, (int)rangeValues, itemSize); diff --git a/src/graphics/BaseGraphicalRenderer.cpp b/src/graphics/BaseGraphicalRenderer.cpp index ba0ef6ff..a9303c69 100644 --- a/src/graphics/BaseGraphicalRenderer.cpp +++ b/src/graphics/BaseGraphicalRenderer.cpp @@ -70,7 +70,7 @@ uint8_t BaseGraphicalRenderer::setActiveItem(MenuItem *item) { adjustedHeight -= startY; totalHeight -= startY; } - totalHeight = max(0, totalHeight); + totalHeight = internal_max(0, totalHeight); serlogF4(SER_TCMENU_DEBUG, "totH, actIdx, adjH ", totalHeight, activeIndex, adjustedHeight); while (totalHeight > adjustedHeight) { @@ -127,7 +127,7 @@ GridPositionRowCacheEntry* BaseGraphicalRenderer::findMenuEntryAndDimensions(con return &cachedEntryItem; } else { - auto rowNum = min(int((screenPos.y - titleHeight) / rowHeight), int(runList->getNumberOfRows() - 1)); + auto rowNum = internal_min(int((screenPos.y - titleHeight) / rowHeight), int(runList->getNumberOfRows() - 1)); cachedEntryItem = GridPositionRowCacheEntry(runList, GridPosition(GridPosition::DRAW_TEXTUAL_ITEM, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, rowNum + 1, titleHeight), titleProps); return &cachedEntryItem; } @@ -323,7 +323,9 @@ void BaseGraphicalRenderer::recalculateDisplayOrder(MenuItem *root, bool safeMod if(root->getMenuType() == MENUTYPE_BACK_VALUE) { serlogF2(SER_TCMENU_DEBUG, "Handling back item", root->getId()); auto* myProps = getDisplayPropertiesFactory().configFor(root, ItemDisplayProperties::COMPTYPE_TITLE); - itemOrderByRow.add(GridPositionRowCacheEntry(root, GridPosition(GridPosition::DRAW_TITLE_ITEM, myProps->getDefaultJustification(), 0), myProps)); + auto *confGrid = getDisplayPropertiesFactory().gridPositionForItem(item); + auto pos = (confGrid) ? confGrid->getPosition() : GridPosition(GridPosition::DRAW_TITLE_ITEM, myProps->getDefaultJustification(), 0); + itemOrderByRow.add(GridPositionRowCacheEntry(root, pos, myProps)); item = root->getNext(); } diff --git a/src/graphics/BaseGraphicalRenderer.h b/src/graphics/BaseGraphicalRenderer.h index f63fdaef..5e7c7ba7 100644 --- a/src/graphics/BaseGraphicalRenderer.h +++ b/src/graphics/BaseGraphicalRenderer.h @@ -421,6 +421,15 @@ namespace tcgfx { void preparePropertiesFromConfig(ConfigurableItemDisplayPropertiesFactory &factory, const ColorGfxMenuConfig *gfxConfig, int titleHeight, int itemHeight); + + /** + * Gets the default drawing mode based on item type + * @param item the item + * @param useSlider if sliders are enabled. + * @return grid drawing mode + */ + GridPosition::GridDrawingMode modeFromItem(MenuItem* item, bool useSlider); + } // namespace tcgfx #endif //TCMENU_BASEGRAPHICALRENDERER_H diff --git a/src/graphics/GfxMenuConfig.cpp b/src/graphics/GfxMenuConfig.cpp index e89557ae..d34a0829 100644 --- a/src/graphics/GfxMenuConfig.cpp +++ b/src/graphics/GfxMenuConfig.cpp @@ -66,6 +66,7 @@ void prepareDefaultGfxConfig(ColorGfxMenuConfig* config) { ItemDisplayProperties *ConfigurableItemDisplayPropertiesFactory::configFor(MenuItem *pItem, ItemDisplayProperties::ComponentType compType) { // make sure that we never return null, in the worst case, provide a default row for this. if(displayProperties.count()==0) { + serlogF(SER_WARNING, "No theme set"); color_t defaultColors[] = { RGB(255,255,255), RGB(0,0,0), RGB(192, 192, 192), RGB(255, 255, 255)}; setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultColors, MenuPadding(2), nullptr, 1, 2, 12, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); @@ -73,7 +74,9 @@ ItemDisplayProperties *ConfigurableItemDisplayPropertiesFactory::configFor(MenuI ItemDisplayProperties *pConf = nullptr; if(pItem != nullptr) { - pConf = displayProperties.getByKey(MakePropsKey(pItem->getId(), false, compType)); + auto key = MakePropsKey(pItem->getId(), false, compType); + pConf = displayProperties.getByKey(key); + serlogF3(SER_TCMENU_DEBUG, "Find by key: ", key, pConf != nullptr); if(pConf) return pConf; } return configForCurrentSub(compType); @@ -90,9 +93,13 @@ ItemDisplayProperties *ConfigurableItemDisplayPropertiesFactory::configForCurren ItemDisplayProperties *pConf = nullptr; auto sub = menuMgr.getCurrentSubMenu(); uint16_t subId = sub ? sub->getId() : 0; - pConf = displayProperties.getByKey(MakePropsKey(subId, true, compType)); + uint32_t key = MakePropsKey(subId, true, compType); + + pConf = displayProperties.getByKey(key); + serlogF3(SER_TCMENU_DEBUG, "Find key sub: ", key, pConf != nullptr); if(pConf) return pConf; + serlogF(SER_TCMENU_DEBUG, "Find use def"); pConf = displayProperties.getByKey(MakePropsKey(MENUID_NOTSET, false, compType)); if(pConf) return pConf; diff --git a/src/graphics/GfxMenuConfig.h b/src/graphics/GfxMenuConfig.h index 39e657e3..e053c04a 100644 --- a/src/graphics/GfxMenuConfig.h +++ b/src/graphics/GfxMenuConfig.h @@ -455,7 +455,7 @@ namespace tcgfx { #define MENUID_NOTSET 0xffff inline uint32_t MakePropsKey(uint16_t menuId, bool parentKey, ItemDisplayProperties::ComponentType ty) { - return (uint32_t)menuId | (parentKey ? 0x10000UL : 0UL) | ((uint32_t)ty << 18UL); + return ((uint32_t)menuId) | (parentKey ? 0x10000UL : 0UL) | ((uint32_t)ty << 18UL); } /** @@ -587,7 +587,10 @@ namespace tcgfx { */ void setDrawingPropertiesDefault(ItemDisplayProperties::ComponentType drawing, const color_t* palette, MenuPadding pad, const void *font, uint8_t mag, uint8_t spacing, uint8_t requiredHeight, GridPosition::GridJustification defaultJustification, MenuBorder border) { - setDrawingProperties(MakePropsKey(MENUID_NOTSET, false, drawing), palette, pad, font, mag, spacing, requiredHeight, defaultJustification, border); + + auto key = MakePropsKey(MENUID_NOTSET, false, drawing); + serlogF2(SER_TCMENU_DEBUG, "Add def prop: ", key); + setDrawingProperties(key, palette, pad, font, mag, spacing, requiredHeight, defaultJustification, border); } /** @@ -605,7 +608,9 @@ namespace tcgfx { */ void setDrawingPropertiesForItem(ItemDisplayProperties::ComponentType drawing, uint16_t id, const color_t* palette, MenuPadding pad, const void *font, uint8_t mag, uint8_t spacing, uint8_t requiredHeight, GridPosition::GridJustification defaultJustification, MenuBorder border) { - setDrawingProperties(MakePropsKey(id, false, drawing), palette, pad, font, mag, spacing, requiredHeight, defaultJustification, border); + auto key = MakePropsKey(id, false, drawing); + serlogF3(SER_TCMENU_DEBUG, "Add item prop: ", key, id); + setDrawingProperties(key, palette, pad, font, mag, spacing, requiredHeight, defaultJustification, border); } /** @@ -623,7 +628,9 @@ namespace tcgfx { */ void setDrawingPropertiesAllInSub(ItemDisplayProperties::ComponentType drawing, uint16_t id, const color_t* palette, MenuPadding pad, const void *font, uint8_t mag, uint8_t spacing, uint8_t requiredHeight, GridPosition::GridJustification defaultJustification, MenuBorder border) { - setDrawingProperties(MakePropsKey(id, true, drawing), palette, pad, font, mag, spacing, requiredHeight, defaultJustification, border); + auto key = MakePropsKey(id, true, drawing); + serlogF3(SER_TCMENU_DEBUG, "Add sub prop: ", key, id); + setDrawingProperties(key, palette, pad, font, mag, spacing, requiredHeight, defaultJustification, border); } /** diff --git a/src/graphics/GraphicsDeviceRenderer.cpp b/src/graphics/GraphicsDeviceRenderer.cpp index 2fff9225..40dfaf81 100644 --- a/src/graphics/GraphicsDeviceRenderer.cpp +++ b/src/graphics/GraphicsDeviceRenderer.cpp @@ -175,8 +175,8 @@ namespace tcgfx { helper.getDrawable()->setDrawColor(propertiesFactory.getSelectedColor(ItemDisplayProperties::BACKGROUND, true)); auto& hints = menuMgr.getEditorHints(); int startX = calculateSpaceBetween(props->getFont(), props->getFontMagnification(), buffer, 0, hints.getStartIndex() ); - int lenX = max(MINIMUM_CURSOR_SIZE, calculateSpaceBetween(props->getFont(), props->getFontMagnification(), buffer, hints.getStartIndex(), hints.getEndIndex())); - int whereX = min(int(width) - MINIMUM_CURSOR_SIZE, int(wh.x + startX)); + int lenX = internal_max(MINIMUM_CURSOR_SIZE, calculateSpaceBetween(props->getFont(), props->getFontMagnification(), buffer, hints.getStartIndex(), hints.getEndIndex())); + int whereX = internal_min(int(width) - MINIMUM_CURSOR_SIZE, int(wh.x + startX)); helper.getDrawable()->drawBox(Coord(whereX, where.y + size.y - 1), Coord(lenX, 1), true); if(size_t(hints.getEndIndex()) > strlen(buffer)) wh.x = wh.x - (unsigned int)MINIMUM_CURSOR_SIZE; helper.drawText(wh, fg, buffer); @@ -466,7 +466,7 @@ namespace tcgfx { forceDrawWidgets = true; } if (titleNeeded && (locRedrawMode == MENUDRAW_COMPLETE_REDRAW || titleEntry->getMenuItem()->isChanged(displayNumber))) { - bool active = titleNeeded && activeItem == titleEntry->getMenuItem(); + bool active = activeItem == titleEntry->getMenuItem(); drawMenuItem(titleEntry, Coord(0, 0), cardLayoutPane->getTitleSize(), DrawingFlags(true, active, menuMgr.getCurrentEditor() == titleEntry->getMenuItem())); forceDrawWidgets = true; } else { @@ -478,7 +478,7 @@ namespace tcgfx { int offsetY = (cardLayoutPane->getMenuSize().y - int(entry->getHeight())) / 2; Coord menuStart(cardLayoutPane->getMenuLocation().x, cardLayoutPane->getMenuLocation().y + offsetY); Coord menuSize(cardLayoutPane->getMenuSize().x, int(entry->getHeight())); - bool active = titleNeeded && activeItem == entry->getMenuItem(); + bool active = activeItem == entry->getMenuItem(); drawMenuItem(entry, menuStart, menuSize, DrawingFlags(false, active, menuMgr.getCurrentEditor() == entry->getMenuItem())); } cardLayoutPane->prepareAndPaintButtons(this, activeIndex, itemOrderByRow.count(), titleMode != NO_TITLE); diff --git a/src/graphics/MenuTouchScreenEncoder.cpp b/src/graphics/MenuTouchScreenEncoder.cpp index 6fe471e6..8795250d 100644 --- a/src/graphics/MenuTouchScreenEncoder.cpp +++ b/src/graphics/MenuTouchScreenEncoder.cpp @@ -39,8 +39,8 @@ void MenuTouchScreenManager::sendEvent(float locationX, float locationY, float t } if(currentlySelected) { // find the local size and ensure it does not drop below 0 in either dimension! - int locX = max(0, (int)(lastCoord.x - localStart.x)); - int locY = max(0, (int)(lastCoord.y - localStart.y)); + int locX = internal_max(0, (int)(lastCoord.x - localStart.x)); + int locY = internal_max(0, (int)(lastCoord.y - localStart.y)); sendToObservers(TouchNotification(currentlySelected, Coord(locX, locY), localStart, localSize, touched)); } else { diff --git a/src/graphics/TcThemeBuilder.cpp b/src/graphics/TcThemeBuilder.cpp index f3ee0931..3dd6bb2d 100644 --- a/src/graphics/TcThemeBuilder.cpp +++ b/src/graphics/TcThemeBuilder.cpp @@ -67,8 +67,12 @@ void ThemePropertiesBuilder::initForLevel(TcThemeBuilder *b, ItemDisplayProperti } border = props->getBorder(); justification = props->getDefaultJustification(); + if(menuItem != nullptr) { + drawingMode = modeFromItem(menuItem, b->getRenderer().isUseSliderForAnalog()); + } } else { justification = GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT; + drawingMode = GridPosition::DRAW_TEXTUAL_ITEM; border = MenuBorder(0); } } @@ -96,11 +100,22 @@ TcThemeBuilder& TcThemeBuilder::withPalette(const color_t *cols) { } ThemePropertiesBuilder &TcThemeBuilder::menuItemOverride(MenuItem &item) { - ItemDisplayProperties::ComponentType ty = (isItemActionable(&item)) ? ItemDisplayProperties::COMPTYPE_ACTION : ItemDisplayProperties::COMPTYPE_ITEM; + ItemDisplayProperties::ComponentType ty = ItemDisplayProperties::COMPTYPE_ITEM; + if(isItemActionable(&item)) { + ty = ItemDisplayProperties::COMPTYPE_ACTION; + } else if(item.getMenuType() == MENUTYPE_TITLE_ITEM || item.getMenuType() == MENUTYPE_BACK_VALUE) { + ty = ItemDisplayProperties::COMPTYPE_TITLE; + } propertiesBuilder.initForLevel(this, ty, ThemePropertiesBuilder::THEME_ITEM, &item); return propertiesBuilder; } +ThemePropertiesBuilder &TcThemeBuilder::menuItemOverride(MenuItem &item, ItemDisplayProperties::ComponentType componentType) { + propertiesBuilder.initForLevel(this, componentType, ThemePropertiesBuilder::THEME_ITEM, &item); + return propertiesBuilder; +} + + TcThemeBuilder& TcThemeBuilder::enableCardLayoutWithXbmImages(Coord iconSize, const uint8_t *leftIcon, const uint8_t *rightIcon, bool isMono) { auto left = new DrawableIcon(-1, iconSize, tcgfx::DrawableIcon::ICON_XBITMAP, leftIcon, nullptr); auto right = new DrawableIcon(-1, iconSize, tcgfx::DrawableIcon::ICON_XBITMAP, rightIcon, nullptr); @@ -137,3 +152,19 @@ TcThemeBuilder& TcThemeBuilder::manualDimensions(int x, int y) { return *this; } +TcThemeBuilder &TcThemeBuilder::addingTitleWidget(TitleWidget &theWidget) { + TitleWidget *pWidget = renderer.getFirstWidget(); + if(pWidget == nullptr) { + renderer.setFirstWidget(&theWidget); + } else { + int loopCount = 0; + while(pWidget->getNext() != nullptr && ++loopCount < 10) { + pWidget = pWidget->getNext(); + } + pWidget->setNext(&theWidget); + renderer.redrawRequirement(MENUDRAW_COMPLETE_REDRAW); + } + return *this; +} + + diff --git a/src/graphics/TcThemeBuilder.h b/src/graphics/TcThemeBuilder.h index 86959413..c00f6a80 100644 --- a/src/graphics/TcThemeBuilder.h +++ b/src/graphics/TcThemeBuilder.h @@ -70,7 +70,7 @@ namespace tcgfx { */ ThemePropertiesBuilder& withAdaFont(const GFXfont* font, int mag = 1) { fontData = font; - fontMag = min(1, mag); + fontMag = internal_min(1, mag); needsProps(); return *this; } @@ -293,11 +293,11 @@ namespace tcgfx { ConfigurableItemDisplayPropertiesFactory &factory; ThemePropertiesBuilder propertiesBuilder; color_t defaultPalette[4] = {}; - MenuPadding globalItemPadding = MenuPadding(1); - MenuPadding globalTitlePadding = MenuPadding(2); - const void *fontData = nullptr; - uint8_t fontMag = 1; - uint8_t defaultSpacing = 1; + MenuPadding globalItemPadding; + MenuPadding globalTitlePadding; + const void *fontData; + uint8_t fontMag; + uint8_t defaultSpacing; public: /** * Creates a theme builder by providing the renderer to use with it. @@ -305,6 +305,14 @@ namespace tcgfx { */ explicit TcThemeBuilder(GraphicsDeviceRenderer& renderer) : renderer(renderer), factory(renderer.getGraphicsPropertiesFactory()), propertiesBuilder(this) { + auto titleDef = factory.configFor(nullptr, ItemDisplayProperties::COMPTYPE_TITLE); + globalTitlePadding = titleDef->getPadding(); + auto itemDef = factory.configFor(nullptr, ItemDisplayProperties::COMPTYPE_ITEM); + memcpy(defaultPalette, itemDef->getPalette(), sizeof defaultPalette); + globalItemPadding = itemDef->getPadding(); + fontData = itemDef->getFont(); + fontMag = itemDef->getFontMagnification(); + defaultSpacing = itemDef->getSpaceAfter(); } /** @@ -327,7 +335,7 @@ namespace tcgfx { */ TcThemeBuilder& withAdaFont(const GFXfont* font, int mag = 1) { fontData = font; - fontMag = min(1, mag); + fontMag = internal_min(1, mag); return *this; } @@ -453,11 +461,23 @@ namespace tcgfx { /** * Get access to theme properties for a specific menu item, with this you can change how an item renders, and - * even apply different grid settings. + * even apply different grid settings. This guesses the component type in most cases but if you want to force a + * particular component type see the override method with the second parameter. + * @param item the menu item to override drawing * @return a theme properties builder */ ThemePropertiesBuilder &menuItemOverride(MenuItem &item); + /** + * Get access to theme properties for a specific menu item, with this you can change how an item renders, and + * even apply different grid settings. This specifically sets the component type for situations where it cannot + * be easily guessed. + * @param item the menu item to override drawing. + * @param componentType one of `COMPTYPE_TITLE`, `COMPTYPE_ITEM`, `COMPTYPE_ACTION` + * @return a theme properties builder + */ + ThemePropertiesBuilder &menuItemOverride(MenuItem &item, ItemDisplayProperties::ComponentType componentType); + /** * Get access to theme properties for a sub menu, with this you can change how all items in that submenu render * This applies to regular items @@ -543,6 +563,8 @@ namespace tcgfx { * @return reference to itself for chaining */ TcThemeBuilder& setMenuAsCard(SubMenuItem& item, bool on); + + TcThemeBuilder& addingTitleWidget(TitleWidget& theWidget); /** * Call after you've finished configuring your theme, this forces a refresh and ensures it presents properly. diff --git a/src/stockIcons/directionalIcons.h b/src/stockIcons/directionalIcons.h index c8426960..d06d1c0c 100644 --- a/src/stockIcons/directionalIcons.h +++ b/src/stockIcons/directionalIcons.h @@ -34,4 +34,21 @@ const uint8_t ArrowHoriz11x22BitmapRight[] PROGMEM = { 0x03,0x00,0x01,0x00 }; +/** + * defaultBackIconBitmap - the default back icon that can be used with card layout. It is 32x32 in size. + */ +// XBM_LSB_FIRST width=32, height=32, size=128 +// auto size = Coord(32, 32); +const uint8_t defaultBackIconBitmap[] PROGMEM = { + 0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xfc,0x00,0x00, + 0x00,0xff,0x00,0x00,0x80,0xff,0x00,0x00,0xe0,0xff,0x03,0x00,0xf0,0xff,0x3f,0x00,0xfc,0xff,0xff,0x00, + 0xfe,0xff,0xff,0x03,0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0x1f,0xfe,0xff,0xff,0x3f,0xfc,0xff,0xff,0x3f, + 0xf0,0xff,0xff,0x7f,0xe0,0xff,0xff,0x7f,0x80,0xff,0x00,0x7f,0x00,0xff,0x00,0x7c,0x00,0xfc,0x00,0x70, + 0x00,0xf8,0x00,0x60,0x00,0xf0,0x00,0x40,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x78, + 0x00,0x00,0x01,0x40,0x00,0x00,0x01,0x40,0x00,0x00,0x01,0x40,0x00,0x00,0x61,0x43,0x00,0x00,0x61,0x43, + 0x00,0x00,0x0f,0x78,0x00,0x00,0x00,0x00 +}; + + + #endif //TCMENU_DIRECTIONAL_ICONS_H diff --git a/src/tcMenuVersion.h b/src/tcMenuVersion.h index 19a9d836..28f02704 100644 --- a/src/tcMenuVersion.h +++ b/src/tcMenuVersion.h @@ -17,8 +17,8 @@ namespace tccore { // here we define the version as both a string and a separate field #define TCMENU_MAJOR 4 -#define TCMENU_MINOR 2 -#define TCMENU_PATCH 1 +#define TCMENU_MINOR 4 +#define TCMENU_PATCH 0 /** * A helper to generate the major minor version numbers used in the protocol