By dave | September 5, 2021

Rendering using themes - properties, grids and icons

From TcMenu 2.0 onwards all display plugins except Uno are customized using themes and render using properties and grids. For these renderers you can override the way that they draw in several ways. Firstly, lets start with a discussion of what’s possible.

Firstly, icons can be used in place of actionable items, they are setup on a per menu-item basis. The colors, padding, orientation, and font for a menu item are now customisable at three levels: Default, Sub-menu, Item. Lastly, the grid position of an item can be configured, in that each row can have a grid of columns.

You could define all these settings from scratch yourself, but to help get you started we have themes that can be applied out of the box. Whenever a graphical display plugin is selected that needs a theme, then the theme is shown underneath the display plugin choice. There are a few pre-canned choices to choose from, but to get started, pick one that works for your display. The manual theme is the basic starting point with no style whatsoever applied, it will require you to define your own settings.

Once you’ve run code generator for the first time, a new header file for the theme will be added to your project. Once added, this will not be altered or overwritten so you are safe to edit it. However, if you want to regenerate the theme, delete the file and the designer will generate it again.

NOTE: Do not pick a color theme for a monochrome display, it is unlikely to work.

This flexible configuration based rendering is made possible by a display factory. The display factory stores all the grids, icons and drawing properties in high performance btree lists that are optimised for reading. We’ll go through each below but first there’s a couple of types you will come across often that we’ll discuss here.

Along with this overview, please see the reference documentation for more complete details, they will not be repeated here:

struct Coord - coordinates

Stores an X and Y coordinate in a 32bit bit-packed struct. It supports copy construction and assignment. You can directly access x and y.

Coord myCoord(10, 4);     // create a coord with x=10 and y=4
Coord copyCoord(myCoord); // copy myCoord into copyCoord
int x = myCoord.x;
int y = myCoord.y;

struct MenuPadding - item padding

Works similar to padding in HTML, You can directly access the top, bottom, left, right values.

MenuPadding equalPadding(4);                        // all sides have padding of 4
MenuPadding perSidePadding(top, right, bottom, left); // per side padding.

Drawing in grid positions

We can draw a menu item at any grid and row position, just be careful that the row definition comes before the natural menu row, otherwise the row will already be taken and can’t be overridden. There are three ways to draw with this type of renderer:

  • Fully on the fly, don’t configure any grid positions, every item will be on a new row by default.
  • Partial overriding of the grid positions
  • Full overriding of grid positions for every menu item in a given submenu.

Let’s say we want menuBtn1 and menuBtn2 in a single row, here’s how we do it, further let’s say that we want them to justify center without the value being presented:

// We define grid positions for menuBtn1 and menuBtn2, with a grid width of 2.
factory.addGridPosition(&menuBtn1, GridPosition(GridPosition:: DRAW_TEXTUAL_ITEM,
                                                GridPosition::JUSTIFY_CENTER_NO_VALUE, 2, 1, 4, 45));
factory.addGridPosition(&menuBtn2, GridPosition(GridPosition:: DRAW_TEXTUAL_ITEM,
                                                GridPosition::JUSTIFY_CENTER_NO_VALUE, 2, 2, 4, 45));

Adding icons for actionable items (requires V2.0)

In order to be able to render as an icon we first need to tell our display properties about the icon, we do this by registering an icon with an association to a particular menu item. Let’s say for example that we had a sub-menu called menuSettings that we wanted to draw as an icon. First we would add the icon to the cache:

// step 1, get the graphics factory
auto & factory = renderer.getGraphicsPropertiesFactory();
// step 2, add an icon to the image cache
Coord iconSize(32, 32);
factory.addImageToCache(DrawableIcon(menuSettings.getId(), iconSize, DrawableIcon::ICON_XBITMAP, 
                        settingsIconData, optionalSelectedIcon));
// step 3, tell the renderer that the settings icon should be in a grid of three, column 1, 45 high, drawn as icon 
factory.addGridPosition(&menuSettings, GridPosition(GridPosition::DRAW_AS_ICON_ONLY,
                                GridPosition::JUSTIFY_CENTER_NO_VALUE, 3, 1, 4, 45));

Changing the drawing parameters (requires V2.0 and above)

You can also change the font, color, padding, size and default justification at three levels:

  • Default settings when no others match
  • SubMenu level, when there is no match at item level
  • Item level, where there is a match on menu item

To change the defaults use setDrawingPropertiesDefault on the factory, providing the component type and the drawing settings.

To change the properties for all in a submenu use setDrawingPropertiesForItem on the factory, providing the component type and drawing settings.

To change the properties for a single item use setDrawingPropertiesAllInSub on the factory, providing the component type and drawing settings.

Here is an example that provides an override for a specific item, it is overridden to display as a title, provides a custom palette, padding, spacing, font and height:

color_t specialPalette[] { ILI9341_WHITE, ILI9341_RED, ILI9341_BLACK, ILI9341_BLUE};
factory.setDrawingPropertiesForItem(ItemDisplayProperties::COMPTYPE_TITLE, menuStatus.getId(), specialPalette,
                                    MenuPadding(4), nullptr, 4, 10, 30,
                                    GridPosition::JUSTIFY_CENTER_WITH_VALUE );

Color palettes and how they relate to menu items

Color palettes can be provided at the default level, the submenu level, or for a given item. They are defined as part of the properties. Each property current takes a four color palette, each color in the palette has a special meaning as follows:

Palette 0 - TEXT

Used to draw the textual components for COMPTYPE_ITEM, COMPTYPE_TITLE and COMPTYPE_ACTION types

Palette 1 - BACKGROUND

used to draw the background for any item, but for COMPTYPE_ITEM it is also the entire background color.

Palette 2 - HIGHLIGHT1

Highlight 1 is used for various additional drawing components, and varies by the type of item being drawn.

  • For the title this refers to the widget color.
  • For Up/Down items, this refers to the color of the button backgrounds.
  • For slider controls it is the active part of the slider area.

Palette 3 - HIGHLIGHT2

  • For sliders this is the inactive part of the slider area.
  • For icon actionable items, this is the colour of the icon when it is not active.

Selected color

You can also set the selected text and background color, these will override other choices when the item is selected, so they should be as compatible as possible with the rest of the color scheme.

Title visibility, enabling sliders

You can set how the renderer object displays the title as shown below:

void setTitleMode(TitleMode mode);

Where title mode which is defined with BaseGraphicalRenderer is one of:

  • BaseGraphicalRenderer::NO_TITLE - the title will not be displayed
  • BaseGraphicalRenderer::TITLE_FIRST_ROW - the title will be displayed as if it were the first row
  • BaseGraphicalRenderer::TITLE_ALWAYS - the title will always be displayed regardless of row.

You can turn on or off slider support, which gives a visual indicator of the range between 0 and the maximum value for analog items:

void setUseSliderForAnalog(bool useSlider);

Touch screen support

The easiest way to use touch support, is from tcMenuDesigner where it can be automatically added to appropriate display devices, this just explains how designer adds touch support for those who want more information, or wish to do it manually.

Touch screen support is added in two steps, first you must tell the renderer that you’re going to use a touch screen:

void setHasTouchInterface(bool hasTouch);

Then you must create a touch screen manager and encoder:

using namespace iotouch;
ResistiveTouchInterrogator touchInterrogator(xplus, xminus, yplus, yminus);
MenuTouchScreenManager touchScreen(touchInterrogator, renderer, rotation);

Then in your setup method:

touchScreen.start();
menuMgr.initWithoutInput(renderer, &rootMenuItem());

Font overview

Read the guide for setting up fonts in the menu designer.

Back to tcMenu main page

Other pages within this category

comments powered by Disqus

This site uses cookies to analyse traffic, serve ads by Google AdSense (non-personalized in EEA/UK), and to record consent. We also embed Twitter, Youtube and Disqus content on some pages, these companies have their own privacy policies.

Our privacy policy applies to all pages on our site

Should you need further guidance on how to proceed: External link for information about cookie management.