Most display plugins can be customized using a grid layout, with graphical displays additionally using themes to configure fonts, colors, spacing and icons. To the left you can see cool-blue theme with a multi-column grid layout.
Grid positions are used to define an items position in the menu, and even break rows up into multiple columns. Each grid position also defines the justification and drawing mode too.
To avoid having to define the fonts, spacing, colors and other details from scratch, 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, so to get started, pick one that works for your display. The manual theme applies no style whatsoever and is not recommended for beginners.
NOTE: Do not pick a color theme for a monochrome display, it is unlikely to work.
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.
Menu items are drawn in a grid layout as presented in the image above. 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.
A row can have either the default height, or the grid position can override the height (in multi-column arrangements all items on one row must be the same height), it can also define the drawing mode and justification. To make a row become multi-column set the grid size parameter to other than 1, and create a grid position for each column position, starting at 1 and working upwards.
Further, if the item at row 0 is the title, then any title widgets will also be rendered onto the right. If you choose to use active and edit icons, then appear on the left and are not considered part of the item.
There are three ways to draw with this type of renderer:
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 with the item name only (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));
addGridPosition
method in ItemDisplayPropertiesFactoryIn 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));
FOR each item in the current menu
LET gridPosition = gridOverrides.getForItem(item)
IF gridPosition was found
Put item in drawingCache at the position specified by gridPosition
ELSE
Put item in drawingCache at next available grid row, colums=1, height=0
END IF
END FOR
Our 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. Graphical displays nearly always have a ConfigurableItemDisplayPropertiesFactory that can be obtained using renderer.getGraphicsPropertiesFactory()
. The themes are always a good starting point for making adjustments to these values.
You can also change the font, color, padding, size and default justification at three levels (shown below in priority order):
nullptr
.To change the default settings use setDrawingPropertiesDefault
on the factory, providing the component type and the drawing settings. This will take effect when there are no other overrides
To change the properties for all items that belong to a submenu use setDrawingPropertiesForItem
on the factory, providing the component type and drawing settings. This will take effect when there are no item level overrides.
To change the properties for a single item use setDrawingPropertiesAllInSub
on the factory, providing the component type and drawing settings. This item will always have priority over anything else.
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 );
There is a properties cache within any graphical menu application, the cache stores the grid positions, icon cache and also a list of drawing properties as described above. These are stored in high performance btree lists, and memory usage is quite minimal for most applications.
Each time a new menu is displayed, the rows are calculated upfront to avoid having to query these lists and perform the priority defaulting during each run.
Along with this overview, please see the reference documentation for more complete details, they will not be repeated here:
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;
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.
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:
Used to draw the textual components for COMPTYPE_ITEM, COMPTYPE_TITLE and COMPTYPE_ACTION types
used to draw the background for any item, but for COMPTYPE_ITEM it is also the entire background color.
Highlight 1 is used for various additional drawing components, and varies by the type of item being drawn.
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.
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:
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);