I am writing a menu handler comprising a number of "buttons" using the UTFT library from here:
http://henningkarlsen.com/electronics/library.php?id=52
The aim is to simplify the creation of a number of menus. For the moment I need only consider the main menu structure which is represented by a single vertical column of "buttons".
This question addresses only the colour information required to display each "button".
Each button requires a number of colour values:
- a fill colour
- a border colour
- a text colour
the background colour for the button fill is always the same as the background colour for the text, so only three parameters are required to define the colour of each button.
The first thing is to define a simple rgb struct in the header file:
#ifndef TFT_h
#define TFT_h
#include <Arduino.h>
// Each triad represents a single RGB colour
struct RGB {
byte r;
byte g;
byte b;
};
#endif
the required rgb values for each colour required to build a button can be defined in a series of arrays:
RGB vMenuFillCol[7] = {{0, 32, 0},{12, 56, 28},{0,132,102},{0, 0, 0},{102,102,82},{250,250,250},{148,32,0}};
RGB vMenuBorderCol[7] = {{34, 139, 34},{56, 128, 64},{0,164,122},{32, 32,32},{132,132,102},{255,255,255},{164,36,12}};
RGB vMenuTextCol[7] = {{144, 238, 144},{144, 238, 144},{144,248,153},{144, 144, 126},{32,32,28},{0,0,0},{255,255,255}};
These 3 arrays define a set of different colours that can be assigned to each button
The text for each button (there are 6 vertical buttons always) can be defined by an array:
char* MenuTxt [][6] = {
{"Date-Time", "Co-ords", "Solar", "Equations", "Setup", "RESET"}, // up to 6 items for the main menu
{"Set Date", "Set Time", "Time Zone", "", "", "BACK"}
};
For the first main (vertical) menu the colour of each button can be defined using an array of rgb values:
RGB MenuCol [3][6] = {
{{vMenuFillCol[0]}, {vMenuFillCol[1]}, {vMenuFillCol[2]}, {vMenuFillCol[3]}, {vMenuFillCol[4]}, {vMenuFillCol[5]}}, // up to 6 items or greyed-out
{{vMenuBorderCol[0]}, {vMenuBorderCol[1]}, {vMenuBorderCol[2]}, {vMenuBorderCol[3]}, {vMenuBorderCol[4]}, {vMenuBorderCol[5]}},
{{vMenuTextCol[0]}, {vMenuTextCol[1]}, {vMenuTextCol[2]}, {vMenuTextCol[3]}, {vMenuTextCol[4]}, {vMenuTextCol[5]}}
};
The above array defines the colours for the first set of menu buttons only (creating arrays for each set of menus (each comprising column of vertical buttons) is a problem to be solved later). For testing, most of the available colours (there are 7) are assigned to the 6 menu buttons. This bizarre arrangement of colours would never happen in practice, only in test....
I can define a menu function as follows:
void vDrawMenu (int menu, int vMOX, int vMOY, int vMP, int vBH, int vBW) {
for (int i=0; i<6; i++) {
myGLCD.setBackColor(MenuCol[0][i].r,MenuCol[0][i].g,MenuCol[0][i].b); // Text Background, index 0
myGLCD.setColor(MenuCol[0][i].r,MenuCol[0][i].g,MenuCol[0][i].b); // Button Fill, index 0
myGLCD.fillRoundRect(vMOX, vMOY + i * vMP, vBW, vMOY + i * vMP + vBH);
myGLCD.setColor(MenuCol[1][i].r,MenuCol[1][i].g,MenuCol[1][i].b); // Button Border, index 1
myGLCD.drawRoundRect(vMOX, vMOY + i * vMP, vBW, vMOY + i * vMP + vBH);
myGLCD.setColor(MenuCol[2][i].r,MenuCol[2][i].g,MenuCol[2][i].b); // Text Colour, index 2
int xpos = vMOX + vBW/2 - strlen(MenuTxt[menu][i]) * MenuFontWidth/2;
int vMenuTextOffsetY = (vBH-MenuFontHeight)/2 + 3;
myGLCD.print(MenuTxt[menu][i], vMOX + xpos, vMOY + vMenuTextOffsetY + i * vMP); // 8 = v offset to centre vertically
}
}
The function can be called as follows:
vDrawMenu (0, vMenuOrigX,vMenuOrigY,vMenuPitch,vBtnHeight,vBtnWidth);
No colour information is passed by the function call, only positional information. Colour information is available via globals.
So far so good. It works and although somewhat clumsy )and probably at this stage far from good practice) it delivers the correct colour values for drawing each button. The full code is attached for those that wish to run it (but it requires a 3.2" TFT Touch screen to display the results, hence my extracting the key bits of the code to explain what I have been doing).
The problem
I am new to C++ and feeling my way into it. But this is an initial stab at a solution as well as an opportunity to learn.
Problems started when I tried to create another block of colours for the next menu (in this example it will be the menu starting:
{"Set Date", "Set Time", "Time Zone", "", "", "BACK"}
I first of all tried expanding the MenuCol array to a 3D array. I was never able to address the the 3D array correctly and colours were presented seemingly at random, even to the point of presenting colours that were to do with positional information. Clearly I was adressing the array incorrectly and visting areas of memory outside the new 3D array. I decided to put that aside...
Reading up on the inadvisability of creating 3D arrays in C++ I began to think there would be two better solutions:
- using vectors
- using a struct to hold the button information
Being new to C++ I realised a lot of learning would be required to implement vectors. Even then I was not sure it would be a good fit towards creating a generalised menu handler.
I opted to try the Struct approach.
I changed the header file as follows:
#ifndef TFT_h
#define TFT_h
#include <Arduino.h>
// Each triad represents a single RGB colour
struct RGB {
byte r;
byte g;
byte b;
};
// Each triad of RGB colours represents a single fill, border and text colour respectively
struct BtnCol {
struct RGB fill;
struct RGB border;
struct RGB text;
};
#endif
struct BtnCol should now hold the triad of RGB values required to define each button. I also hoped it would result in a more readable display of each colour.
The next step is to create such a triad of rgb values:
BtnCol main = {{0, 32, 0},{34, 139, 34},{144, 238, 144}}; // main (vertical) menu
This creates a compile error whcih I have been unable to resolve:
c:/program-arduino/arduino-1.0.1/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr6/crtm2560.o:(.init9+0x0): warning: internal error: out of range error
There may be other (better) ways to find a solution to assigning rgb values to each of the three elements that define a button's colour values and I will be interested to hear about those. The immediate question is: Why do I get the out of range error and how should I go about assigning values to what is, essentially, a struct of structs?
I hope I have made everything clear.
Thanks,
Ric
Note <ITDB02_Touch.h> is not needed in this example and can be commented-out.
touch_interface_v13.ino (13.9 KB)
TFT.h (339 Bytes)
UTFT.h (6.1 KB)
UTFT.cpp (58.3 KB)