Files
Arduino/ESP32_WAVESHARE_7x5/Designer.cpp
Jérôme Delacotte 7b30d6e298 first commit
2025-03-06 11:15:32 +01:00

375 lines
20 KiB
C++
Executable File

#include "Designer.h"
#include "common.h"
#include "common_functions.h"
#include "Graph.h"
Designer::Designer(Ecran * _ecran, Meteo * _meteo, Connect * _connect, Domoticz * _domoticz, Timer * _timer)
{
ecran = _ecran;
meteo = _meteo;
connect = _connect;
domoticz = _domoticz;
timer = _timer;
}
//#########################################################################################
void Designer::displayWeather(int boucle) { // 7.5" e-paper display is 800x480 resolution
if (debug) Serial.println("B - displayWeather boucle=" + String(boucle));
if (true || boucle == 1) {
displayGeneralInfoSection(); // Top line of the display
if (debug) Serial.println("1 - displayWeather");
displayWindSection(108, 146, meteo->conditions[0].Winddir, meteo->conditions[0].Windspeed, 81);
if (debug) Serial.println("2 - displayWeather");
// displayMainWeatherSection(300, 100); // Centre section of display for Location, temperature, Weather report, current Wx Symbol and wind direction
ecran->_display->drawLine(0, 38, SCREEN_WIDTH - 3, 38, GxEPD_BLACK);
displayConditionsSection(303, 149, meteo->conditions[0].Icon,LargeIcon);
displayTemperatureSection(389, 19, 137, 100);
//displayForecastTextSection(397, 120, 409, 65);
displayPressureSection(581, 19, meteo->conditions[0].Pressure, meteo->conditions[0].Trend, 140, 100);
displayPrecipitationSection(712, 19, 136, 100);
if (debug) Serial.println("3 - displayWeather");
displayForecastSection(0, 243,FORECAST_WIDTH, FORECAST_HEIGHT); // 3hr forecast boxes
if (debug) Serial.println("4 - displayWeather");
// displayAstronomySection(0, 245); // Astronomy section Sun rise/set, Moon phase and Moon icon
// if (debug) Serial.println("5 - displayWeather");
displayStatusSection(700, 10); // Wi-Fi signal strength and Battery voltage
domoticz->drawTemps(389, 117, 412, 105);
domoticz->drawGraphs(0, 375, 150, 72);
//domoticz->loadLinky();
}
// Partial mode
else {
ecran->_display->setPartialWindow(1,1,601,17);
//ecran->_display->fillScreen(GxEPD_WHITE);;
displayGeneralInfoSection(); // Top line of the display
}
if (debug) Serial.println("E - displayWeather");
}
//#########################################################################################
void Designer::displayGeneralInfoSection() {
ecran->fonts.setFont(FONT_10);
ecran->drawString(6, 2, "[Version: " + String(VERSION) + "] " + timer->Date_str + ' ' + timer->Time_str, LEFT); // Programme version
ecran->drawString(SCREEN_WIDTH / 2, 3, meteo->City, CENTER);
ecran->_display->drawLine(0, 18, SCREEN_WIDTH - 3, 18, GxEPD_BLACK);
}
//#########################################################################################
void Designer::displayWindSection(int x, int y, float angle, float windspeed, int Cradius) {
ecran->arrow(x, y, Cradius - 22, angle, 18, 33); // Show wind direction on outer circle of width and length
ecran->fonts.setFont(FONT_08);
ecran->drawString(x, y - Cradius - 41, TXT_WIND_SPEED_DIRECTION, CENTER, GxEPD_BLACK);
int dxo, dyo, dxi, dyi;
ecran->_display->drawLine(0, 18, 0, y + Cradius + 37, GxEPD_BLACK);
ecran->_display->drawCircle(x, y, Cradius, GxEPD_BLACK); // Draw compass circle
ecran->_display->drawCircle(x, y, Cradius + 1, GxEPD_BLACK); // Draw compass circle
ecran->_display->drawCircle(x, y, Cradius * 0.7, GxEPD_BLACK); // Draw compass inner circle
for (float a = 0; a < 360; a = a + 22.5) {
dxo = Cradius * cos((a - 90) * PI / 180);
dyo = Cradius * sin((a - 90) * PI / 180);
if (a == 45) ecran->drawString(dxo + x + 12, dyo + y - 12, TXT_NE, CENTER);
if (a == 135) ecran->drawString(dxo + x + 7, dyo + y + 6, TXT_SE, CENTER);
if (a == 225) ecran->drawString(dxo + x - 18, dyo + y, TXT_SW, CENTER);
if (a == 315) ecran->drawString(dxo + x - 18, dyo + y - 12, TXT_NW, CENTER);
dxi = dxo * 0.9;
dyi = dyo * 0.9;
ecran->_display->drawLine(dxo + x, dyo + y, dxi + x, dyi + y, GxEPD_BLACK);
dxo = dxo * 0.7;
dyo = dyo * 0.7;
dxi = dxo * 0.9;
dyi = dyo * 0.9;
ecran->_display->drawLine(dxo + x, dyo + y, dxi + x, dyi + y, GxEPD_BLACK);
}
ecran->drawString(x, y - Cradius - 12, TXT_N, CENTER);
ecran->drawString(x, y + Cradius + 6, TXT_S, CENTER);
ecran->drawString(x - Cradius - 12, y - 3, TXT_W, CENTER);
ecran->drawString(x + Cradius + 10, y - 3, TXT_E, CENTER);
ecran->drawString(x - 2, y - 43, WindDegToDirection(angle), CENTER);
ecran->drawString(x + 6, y + 30, String(angle, 0) + "°", CENTER);
ecran->fonts.setFont(FONT_18);
ecran->drawString(x - 12, y - 3, String(windspeed, 1), CENTER,GxEPD_BLACK);
ecran->fonts.setFont(FONT_08);
ecran->drawString(x, y + 12, (Units == "M" ? "m/s" : "mph"), CENTER);
}
//#########################################################################################
void Designer::displayTemperatureSection(int x, int y, int twidth, int tdepth) {
ecran->_display->drawRect(x, y - 1, twidth, tdepth, GxEPD_BLACK); // temp outline
ecran->fonts.setFont(FONT_08);
ecran->drawString(x + 63, y + 5, String(TXT_TEMPERATURES), CENTER);
ecran->fonts.setFont(FONT_10);
ecran->drawString(x + 73, y + 82, String(meteo->conditions[0].High, 0) + "° | " + String(meteo->conditions[0].Low, 0) + "°", CENTER); // Show forecast high and Low
ecran->fonts.setFont(FONT_24);
ecran->drawString(x + 53, y + 53, String(meteo->conditions[0].Temperature, 1) + "°", CENTER); // Show current Temperature
ecran->fonts.setFont(FONT_10);
ecran->_display->drawInvertedBitmap(x, y + 66, thermometer32x32, 32, 32, GxEPD_BLACK);
//ecran->drawString(x + 43, y + 53, Units == "M" ? "C" : "F", LEFT);
}
//#########################################################################################
void Designer::displayPressureSection(int x, int y, float pressure, String slope, int pwidth, int pdepth) {
ecran->_display->drawRect(x - 56, y - 1, pwidth, pdepth, GxEPD_BLACK); // pressure outline
ecran->fonts.setFont(FONT_08);
ecran->drawString(x + 8, y + 5, TXT_PRESSURE, CENTER);
String slope_direction = TXT_PRESSURE_STEADY;
int x_i = x + 40;
if (slope == "+") {
slope_direction = TXT_PRESSURE_RISING;
ecran->_display->fillTriangle(x_i, y + 50, x_i + 10, y + 50, x_i + 5, y + 40, GxEPD_RED);
ecran->_display->fillTriangle(x_i, y + 55, x_i + 10, y + 55, x_i + 5, y + 65, GxEPD_BLACK);
}
if (slope == "-") {
slope_direction = TXT_PRESSURE_FALLING;
ecran->_display->fillTriangle(x_i, y + 50, x_i + 10, y + 50, x_i + 5, y + 40, GxEPD_BLACK);
ecran->_display->fillTriangle(x_i, y + 55, x_i + 10, y + 55, x_i + 5, y + 65, GxEPD_RED);
}
ecran->_display->drawRect(x + 40, y + 78, 41, 21, GxEPD_BLACK);
ecran->fonts.setFont(FONT_24);
if (Units == "I")
ecran->drawString(x - 22, y + 55, String(pressure, 2), CENTER); // "Imperial"
else
ecran->drawString(x - 22, y + 55, String(pressure, 0), CENTER); // "Metric"
ecran->fonts.setFont(FONT_08);
ecran->drawString(x + 59, y + 83, (Units == "M" ? "hPa" : "in"), CENTER);
//ecran->drawString(x - 3, y + 83, slope_direction, CENTER);
}
//#########################################################################################
void Designer::displayPrecipitationSection(int x, int y, int pwidth, int pdepth) {
ecran->_display->drawRect(x - 48, y - 1, pwidth, pdepth, GxEPD_BLACK); // precipitation outline
ecran->fonts.setFont(FONT_08);
ecran->drawString(x + 25, y + 5, TXT_PRECIPITATION_SOON, CENTER);
ecran->fonts.setFont(u8g2_font_helvB12_tf);
if (meteo->previsions[1].Rainfall >= 0.005) { // Ignore small amounts
ecran->drawString(x - 25, y + 40, String(meteo->previsions[1].Rainfall, 2) + (Units == "M" ? "mm" : "in"), LEFT); // Only display rainfall total today if > 0
meteo->addraindrop(x + 58, y + 40, 7);
}
if (meteo->previsions[1].Snowfall >= 0.005) // Ignore small amounts
ecran->drawString(x - 25, y + 71, String(meteo->previsions[1].Snowfall, 2) + (Units == "M" ? "mm" : "in") + " **", LEFT); // Only display snowfall total today if > 0
if (meteo->previsions[1].Pop >= 0.005) // Ignore small amounts
ecran->drawString(x - 25, y + 81, String(meteo->previsions[1].Pop * 100, 0) + "%", LEFT); // Only display pop if > 0
ecran->_display->drawInvertedBitmap(x + 45, y + 65, humidity32x32, 32, 32, GxEPD_BLACK);
ecran->drawString(x + 40, y + 81, String(meteo->conditions[0].Humidity, 0), CENTER);
}
//#########################################################################################
void Designer::displayForecastWeather(int x, int y, int fwidth, int height, int index) {
Forecast_record_type frt;
ecran->fonts.setFont(FONT_10);
frt = meteo->previsions[index];
ecran->_display->drawRect(x, y, fwidth, height, GxEPD_BLACK);
ecran->_display->drawLine(x, y + 16, x + fwidth, y + 16, GxEPD_BLACK);
displayConditionsSection(x + fwidth / 2, y + 43, frt.Icon, SmallIcon);
ecran->drawString(x + fwidth / 2, y + 6,
String(meteo->ConvertUnixTime(frt.Dt + meteo->conditions[0].Timezone).substring(0, 5))
, CENTER);
ecran->drawString(x + 5, y + height - 10, String(frt.High, 0) + "°", LEFT);
ecran->drawString(x + fwidth, y + height - 10, String(frt.Low, 0) + "°", RIGHT);
}
//#########################################################################################
void Designer::displayForecastSection(int x, int y,int fwidth, int height) {
if (debug) Serial.println("B - displayForecastSection");
int f = 8 - FORECAST_HORIZON;
int to_show = 0;
// displayForecastWeather(x, y, to_show);
// to_show ++;
do {
displayForecastWeather(x + FORECAST_WIDTH * (to_show), y, fwidth, height, to_show);
f++;
to_show ++;
} while (f <= 7);
}
//#########################################################################################
void Designer::displayConditionsSection(int x, int y, String IconName, bool IconSize) {
if (debug) Serial.println("B - displayConditionsSection Icon name: " + IconName);
#if defined(ICONS_SET_ONE)
bool inverted = true;
IconName.replace('n', 'd');
#endif
#if defined(ICONS_SET_TWO)
bool inverted = false;
#endif
#if defined(ICONS_SET_THREE)
bool inverted = true;
#endif
if (IconSize != LargeIcon) {
int scale = 1;
int xi = x - ICON_SIZE / 2;
int yi = y - ICON_SIZE / 2;
if (String(IconName) == "01d") ecran->drawBitmap(xi, yi, icon_64x64_01d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "02d") ecran->drawBitmap(xi, yi, icon_64x64_02d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "03d") ecran->drawBitmap(xi, yi, icon_64x64_03d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "04d") ecran->drawBitmap(xi, yi, icon_64x64_04d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "09d") ecran->drawBitmap(xi, yi, icon_64x64_09d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "10d") ecran->drawBitmap(xi, yi, icon_64x64_10d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "11d") ecran->drawBitmap(xi, yi, icon_64x64_11d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "13d") ecran->drawBitmap(xi, yi, icon_64x64_13d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "50d") ecran->drawBitmap(xi, yi, icon_64x64_50d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
#if defined(ICONS_SET_THREE) || defined(ICONS_SET_TWO)
if (String(IconName) == "01n") ecran->drawBitmap(xi, yi, icon_64x64_01n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "02n") ecran->drawBitmap(xi, yi, icon_64x64_02n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "03n") ecran->drawBitmap(xi, yi, icon_64x64_03n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "04n") ecran->drawBitmap(xi, yi, icon_64x64_04n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "09n") ecran->drawBitmap(xi, yi, icon_64x64_09n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "10n") ecran->drawBitmap(xi, yi, icon_64x64_10n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "11n") ecran->drawBitmap(xi, yi, icon_64x64_11n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "13n") ecran->drawBitmap(xi, yi, icon_64x64_13n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "50n") ecran->drawBitmap(xi, yi, icon_64x64_50n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
#endif
}
if (SHOW_MOON_IN_FORECAST) {
if (IconName.endsWith("n")) meteo->addMoon(x, y + 3, Small, IconSize);
}
if (IconSize ==LargeIcon) {
float scale = 2;
int xi = x - ICON_SIZE / 2 * scale;
int yi = y - 20 - ICON_SIZE / 2 * scale;
#if defined(CALCULATED)
yi = y - 20;
if (IconName == "01d" || IconName == "01n") meteo->Sunny(x, yi, IconSize, IconName);
else if (IconName == "02d" || IconName == "02n") meteo->MostlySunny(x, yi, IconSize, IconName);
else if (IconName == "03d" || IconName == "03n") meteo->Cloudy(x, yi, IconSize, IconName);
else if (IconName == "04d" || IconName == "04n") meteo->MostlyCloudy(x, yi, IconSize, IconName);
else if (IconName == "09d" || IconName == "09n") meteo->ChanceRain(x, yi, IconSize, IconName);
else if (IconName == "10d" || IconName == "10n") meteo->Rain(x, yi, IconSize, IconName);
else if (IconName == "11d" || IconName == "11n") meteo->Tstorms(x, yi, IconSize, IconName);
else if (IconName == "13d" || IconName == "13n") meteo->Snow(x, yi, IconSize, IconName);
else if (IconName == "50d") meteo->Haze(x, yi, IconSize, IconName);
else if (IconName == "50n") meteo->Fog(x, yi, IconSize, IconName);
else Nodata(x, yi, IconSize, IconName);
#endif
if (xi > 0) {
if (String(IconName) == "01d") ecran->drawBitmap(xi, yi, icon_64x64_01d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "02d") ecran->drawBitmap(xi, yi, icon_64x64_02d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "03d") ecran->drawBitmap(xi, yi, icon_64x64_03d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "04d") ecran->drawBitmap(xi, yi, icon_64x64_04d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "09d") ecran->drawBitmap(xi, yi, icon_64x64_09d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "10d") ecran->drawBitmap(xi, yi, icon_64x64_10d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "11d") ecran->drawBitmap(xi, yi, icon_64x64_11d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "13d") ecran->drawBitmap(xi, yi, icon_64x64_13d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "50d") ecran->drawBitmap(xi, yi, icon_64x64_50d, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
#if defined(ICONS_SET_THREE) || defined(ICONS_SET_TWO)
if (String(IconName) == "01n") ecran->drawBitmap(xi, yi, icon_64x64_01n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "02n") ecran->drawBitmap(xi, yi, icon_64x64_02n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "03n") ecran->drawBitmap(xi, yi, icon_64x64_03n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "04n") ecran->drawBitmap(xi, yi, icon_64x64_04n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "09n") ecran->drawBitmap(xi, yi, icon_64x64_09n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "10n") ecran->drawBitmap(xi, yi, icon_64x64_10n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "11n") ecran->drawBitmap(xi, yi, icon_64x64_11n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "13n") ecran->drawBitmap(xi, yi, icon_64x64_13n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
if (String(IconName) == "50n") ecran->drawBitmap(xi, yi, icon_64x64_50n, ICON_SIZE, ICON_SIZE, GxEPD_BLACK, scale, inverted);
#endif
}
ecran->_display->drawRect(x - 86, y - 131, 173, 226, GxEPD_BLACK);
ecran->fonts.setFont(FONT_08);
ecran->drawString(x, y - 125, TXT_CONDITIONS, CENTER);
ecran->fonts.setFont(FONT_14);
ecran->fonts.setFont(FONT_10);
// ecran->drawString(x + 35, y + 80, "RH", CENTER);
if (meteo->conditions[0].Visibility > 0)
meteo->Visibility(x - 20, y - 10, String(meteo->conditions[0].Visibility) + "M");
if (meteo->conditions[0].Cloudcover > 0)
meteo->CloudCover(x - 20, y - 35, meteo->conditions[0].Cloudcover);
ecran->fonts.setFont(FONT_10);
meteo->drawTodayMoon(x + 90 - 2 * MOON_DIAMETER - 10, y - 120);
int yp = 35;
ecran->_display->drawInvertedBitmap(x - 85, y + yp, sunrise48x48, 48, 48, GxEPD_BLACK);
ecran->_display->drawInvertedBitmap(x + 90 - 64, y + yp, sunset48x48, 48, 48, GxEPD_BLACK);
String sunset = String(meteo->ConvertUnixTime(meteo->conditions[0].Sunset + meteo->conditions[0].Timezone));
String sunrise = String(meteo->ConvertUnixTime(meteo->conditions[0].Sunrise + meteo->conditions[0].Timezone));
ecran->fonts.setFont(FONT_14);
ecran->drawString(x - 30, y + yp + 10, sunrise.substring(0, 2), CENTER);
ecran->drawString(x - 30, y + yp + 35, sunrise.substring(3, 5), CENTER);
ecran->drawString(x + 10, y + yp + 10, sunset.substring(0, 2), CENTER);
ecran->drawString(x + 10, y + yp + 35, sunset.substring(3, 5), CENTER);
}
if (debug) Serial.println("E - displayConditionsSection Icon name: " + IconName);
}
//#########################################################################################
void Designer::displayStatusSection(int x, int y) {
// ecran->_display->drawRect(x - 35, y - 32, 145, 61, GxEPD_BLACK);
// ecran->_display->drawLine(x - 35, y - 17, x - 35 + 145, y - 17, GxEPD_BLACK);
// ecran->_display->drawLine(x - 35 + 146 / 2, y - 18, x - 35 + 146 / 2, y - 32, GxEPD_BLACK);
ecran->fonts.setFont(FONT_08);
// ecran->drawString(x, y - 29, TXT_WIFI, CENTER);
// ecran->drawString(x + 68, y - 30, TXT_POWER, CENTER);
connect->drawRSSI(x, y + 6);
DrawBattery(x + 58, y + 6, 1);
}
//#########################################################################################
String Designer::WindDegToDirection(float winddirection) {
int dir = int((winddirection / 22.5) + 0.5);
String Ord_direction[16] = {TXT_N, TXT_NNE, TXT_NE, TXT_ENE, TXT_E, TXT_ESE, TXT_SE, TXT_SSE, TXT_S, TXT_SSW, TXT_SW, TXT_WSW, TXT_W, TXT_WNW, TXT_NW, TXT_NNW};
return Ord_direction[(dir % 16)];
}
//#########################################################################################
void Designer::DrawBattery(int x, int y, float scale) {
uint8_t percentage = 100;
float voltage = analogRead(35) / 4096.0 * 7.46;
if (voltage < 0.5) {
voltage = 4.95;
}
if (voltage > 1 ) { // Only display if there is a valid reading
if (debug) Serial.println("Voltage = " + String(voltage));
percentage = 2836.9625 * pow(voltage, 4) - 43987.4889 * pow(voltage, 3) + 255233.8134 * pow(voltage, 2) - 656689.7123 * voltage + 632041.7303;
if (voltage >= 4.20) percentage = 100;
if (voltage <= 3.50) percentage = 0;
ecran->_display->drawRect(x + 15, y - 12, 19, 10, GxEPD_RED);
ecran->_display->fillRect(x + 34, y - 10, 2, 5, GxEPD_RED);
ecran->_display->fillRect(x + 17, y - 10, 15 * percentage / 100.0, 6, GxEPD_RED);
ecran->drawString(x + 10, y - 11, String(percentage) + "%", RIGHT);
//ecran->drawString(x + 13, y + 5, String(voltage, 2) + "v", CENTER);
}
}
//#########################################################################################
void Designer::Nodata(int x, int y, bool IconSize, String IconName) {
if (IconSize ==LargeIcon) ecran->fonts.setFont(FONT_24); else ecran->fonts.setFont(FONT_10);
ecran->drawString(x - 3, y - 10, "?", CENTER);
ecran->fonts.setFont(FONT_08);
}