-
Notifications
You must be signed in to change notification settings - Fork 41
Custom icons
![]()
It is possible to replace set of default UI icons with a custom one (since GEM ver. 1.8). The most straightforward way to do this is to locate files containing default sprites in source code of GEM library, copy to your project and replace specific (or all) sprites with custom ones (and rename variables to avoid conflict with default set).
Default sprites are stored in sprites/sprites-glcd-default.h, sprites/sprites-u8g2-default.h and sprites/sprites-adafruit-gfx-default.h source files that ship with the library.
Array of custom sprites always should have exactly 7 icons (or 6 in case of AltSerialGraphicLCD version of GEM) in a specific order determined by values of GEM_ICON_ macro constants:
- 0:
GEM_ICON_ARROW_RIGHT - 1:
GEM_ICON_ARROW_LEFT - 2:
GEM_ICON_ARROW_BTN - 3:
GEM_ICON_CHECKBOX_UNCHECKED - 4:
GEM_ICON_CHECKBOX_CHECKED - 5:
GEM_ICON_SELECT_ARROWS - 6:
GEM_ICON_SPINNER_ARROWS(except for AltSerialGraphicLCD version of GEM: it always uses the same icon for spinners as for selects)
See Constants section of the GEM class documentation for more details.
Note: array of sprites for Adafruit GFX version of GEM is two-dimensional: first
GEMSpriteobject of each element represents 1x scale of an icon, the second represents 2x scale (for when magnification is set via setTextSize() and setSpriteSize() methods).
Then, either pass array of custom sprites to the GEM constructor, or set .sprites property of GEMAppearance object.
Each sprite is wrapped into GEMSprite struct, which stores width and height of an icon and a pointer to an actual bitmap data (with format specific to graphics library being used).
Data structure - wrapper for a sprite (icon). Object of type GEMSprite defines as follows:
GEMSprite customSprite = {width, height, image}-
width
Type:byte
Width of an icon. -
height
Type:byte
Height of an icon. -
image
Type:const uint8_t *
Pointer to an image (usually an array in a format supported by current graphics library).
Format of data image points to is determined by graphics library used to draw menu.
The following is the format of the sprite as described in AltSerialGraphicLCD library documentation:
The sprite commences with two bytes which are the width and height of the image in pixels. The pixel data is organised as rows of 8 vertical pixels per byte where the least significant bit (LSB) is the top-left pixel and the most significant bit (MSB) tends towards the bottom-left pixel. A complete row of 8 vertical pixels across the image width comprises the first row, this is then followed by the next row of 8 vertical pixels and so on. Where the image height is not an exact multiple of 8 bits then any unused bits are typically set to zero (although this does not matter).
![]()
To define a custom sprite, first define two macro aliases for width and height of the image, create GEMSprite object and populate its width and height properties with corresponding values. Populate image property with an array of bytes stored in flash (program) memory using PROGMEM directive in a format described above.
Example of an icon in a bitmap format supported by AltSerialGraphicLCD library:
#define arrowRight_width 6
#define arrowRight_height 8
static const uint8_t arrowRight_bits [] PROGMEM = {
arrowRight_width, arrowRight_height,
0, 0, 62, 28, 8, 0
};
const GEMSprite arrowRight = {arrowRight_width, arrowRight_height, arrowRight_bits};The image should be presented in XBM format.
To define a custom sprite with XBM image, first define two macro aliases for width and height of the image, create GEMSprite object and populate its width and height properties with corresponding values. Populate image property with an array of bytes stored in flash (program) memory (using an U8X8_PROGMEM alias from U8g2 library) in an XBM format.
See xbm-viewer-converter webtool for online bitmap conversion.
Example of an icon in XBM format supported by U8g2 library:
#define arrowRight_width 6
#define arrowRight_height 8
static const unsigned char arrowRight_bits [] U8X8_PROGMEM = {
0xc0, 0xc4, 0xcc, 0xdc, 0xcc, 0xc4, 0xc0, 0xc0
};
const GEMSprite arrowRight = {arrowRight_width, arrowRight_height, arrowRight_bits};The following is the format of the bitmap as described in Adafruit GFX library documentation:
A contiguous block of bits, where each
1bit sets the corresponding pixel to 'color', while each0bit is skipped.
To define a custom bitmap, first define two macro aliases for width and height of the image, create GEMSprite object and populate its width and height properties with corresponding values. Populate image property with an array of bytes stored in flash (program) memory using PROGMEM directive in a format described above.
See Bitmaps section of Adafruit GFX documentation for more details and image2cpp webtool for online bitmap conversion.
Example of an icon in a bitmap format supported by Adafruit GFX library:
#define arrowRight_width 6
#define arrowRight_height 8
static const uint8_t arrowRight_bits [] PROGMEM = {
0x00, 0x20, 0x30, 0x38, 0x30, 0x20, 0x00, 0x00
};
const GEMSprite arrowRight = {arrowRight_width, arrowRight_height, arrowRight_bits};The following is an example set of custom UI icons in XBM format based on default set of U8g2 version of GEM found in sprites/sprites-u8g2-default.h source file:
// sprites-u8g2-custom.h
//Sprites of the UI elements used to draw menu
#define arrowRight_width 6
#define arrowRight_height 8
static const unsigned char arrowRight_bits_c [] U8X8_PROGMEM = {
0x00, 0x02, 0x04, 0x08, 0x04, 0x02, 0x00, 0x00
};
#define arrowLeft_width 6
#define arrowLeft_height 8
static const unsigned char arrowLeft_bits_c [] U8X8_PROGMEM = {
0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00
};
#define arrowBtn_width 6
#define arrowBtn_height 8
static const unsigned char arrowBtn_bits_c [] U8X8_PROGMEM = {
0xc0, 0xc3, 0xc5, 0xc9, 0xc5, 0xc3, 0xc0, 0xc0
};
#define checkboxUnchecked_width 12
#define checkboxUnchecked_height 8
static const unsigned char checkboxUnchecked_bits_c [] U8X8_PROGMEM = {
0xFE, 0x07, 0x03, 0x0C, 0x19, 0x08, 0x25, 0x08, 0x19, 0x08, 0x03, 0x0C,
0xFE, 0x07, 0x00, 0x00
};
#define checkboxChecked_width 12
#define checkboxChecked_height 8
static const unsigned char checkboxChecked_bits_c [] U8X8_PROGMEM = {
0xFE, 0x07, 0x03, 0x0C, 0x81, 0x09, 0xC1, 0x0B, 0x81, 0x09, 0x03, 0x0C,
0xFE, 0x07, 0x00, 0x00
};
#define selectArrows_width 6
#define selectArrows_height 8
static const unsigned char selectArrows_bits_c [] U8X8_PROGMEM = {
0x00, 0x04, 0x0A, 0x00, 0x0A, 0x04, 0x00, 0x00
};
const GEMSprite arrowRightC = {arrowRight_width, arrowRight_height, arrowRight_bits_c};
const GEMSprite arrowLeftC = {arrowLeft_width, arrowLeft_height, arrowLeft_bits_c};
const GEMSprite arrowBtnC = {arrowBtn_width, arrowBtn_height, arrowBtn_bits_c};
const GEMSprite checkboxUncheckedC = {checkboxUnchecked_width, checkboxUnchecked_height, checkboxUnchecked_bits_c};
const GEMSprite checkboxCheckedC = {checkboxChecked_width, checkboxChecked_height, checkboxChecked_bits_c};
const GEMSprite selectArrowsC = {selectArrows_width, selectArrows_height, selectArrows_bits_c};
const GEMSprite* spritesCustom[] = {
&arrowRightC, // GEM_ICON_ARROW_RIGHT
&arrowLeftC, // GEM_ICON_ARROW_LEFT
&arrowBtnC, // GEM_ICON_ARROW_BTN
&checkboxUncheckedC, // GEM_ICON_CHECKBOX_UNCHECKED
&checkboxCheckedC, // GEM_ICON_CHECKBOX_CHECKED
&selectArrowsC, // GEM_ICON_SELECT_ARROWS
&selectArrowsC // GEM_ICON_SPINNER_ARROWS
};To use this set in your sketch, first include it and then submit spritesCustom directly to GEM constructor:
#include "sprites-u8g2-custom.h"
...
GEM_u8g2 menu(u8g2, /* menuPointerType= */ GEM_POINTER_ROW, /* menuItemsPerScreen= */ GEM_ITEMS_COUNT_AUTO, /* menuItemHeight= */ 10, /* menuPageScreenTopOffset= */ 10, /* menuValuesLeftOffset= */ 86, /* sprites= */ spritesCustom);Or alternatively create GEMAppearance object and populate its .sprites property with spritesCustom:
#include "sprites-u8g2-custom.h"
...
GEMAppearance appearanceGeneral;
GEM_u8g2 menu(u8g2);
...
void setup() {
...
// Menu init, setup and draw
menu.init();
setupMenu();
menu.drawMenu();
}
void setupMenu() {
// Populate GEMAppearance object with general values (that will be used for every menu page if not overridden)
appearanceGeneral.menuPointerType = menuPointer;
appearanceGeneral.menuItemsPerScreen = GEM_ITEMS_COUNT_AUTO;
appearanceGeneral.menuItemHeight = 10;
appearanceGeneral.menuPageScreenTopOffset = 10;
appearanceGeneral.menuValuesLeftOffset = 86;
appearanceGeneral.sprites = spritesCustom; // Use custom set of sprites (icons)
// Set appearanceGeneral as a general appearance of the menu
menu.setAppearance(appearanceGeneral);
...
}
Using GEMAppearance potentially allows for different icon sets to be used on different menu pages.
Related examples: test_98_gem-u8g2_sh1106_custom-sprites.ino + sprites-u8g2-custom.h (Wokwi)
- Test bench (push-buttons):
- Example 01: Basic
- Example 02: Blink
- Example 03: Party Hard!
- Test bench (rotary encoder):
- Example 05: Encoder
- Example 06: Todo List