feat(color): Convert top bar display in main view into widgets (#3700)

* Convert radio info (USB, volume, signal strength), date/time and internal GPS display from top bar into widgets.

* Fix B&W build.
This commit is contained in:
philmoz
2023-08-04 12:14:31 +10:00
committed by GitHub
parent 69338ab0ab
commit 4272a03025
14 changed files with 347 additions and 240 deletions
+4 -4
View File
@@ -86,7 +86,7 @@ static inline void check_struct()
CHKSIZE(ModelHeader, 131);
CHKSIZE(CurveHeader, 4);
CHKSIZE(CustomScreenData, 852);
CHKTYPE(TopBarPersistentData, 300);
CHKTYPE(TopBarPersistentData, 444);
#elif defined(PCBNV14)
// TODO
#else
@@ -146,14 +146,14 @@ static inline void check_struct()
#elif defined(PCBHORUS)
#if defined(PCBX10)
CHKSIZE(RadioData, 916);
CHKSIZE(ModelData, 15463);
CHKSIZE(ModelData, 15607);
#else
CHKSIZE(RadioData, 916);
CHKSIZE(ModelData, 15463);
CHKSIZE(ModelData, 15607);
#endif
#elif defined(PCBNV14)
CHKSIZE(RadioData, 916);
CHKSIZE(ModelData, 15319);
CHKSIZE(ModelData, 15463);
#endif
#undef CHKSIZE
+29 -199
View File
@@ -24,67 +24,6 @@
constexpr uint32_t TOPBAR_REFRESH = 1000 / 10; // 10 Hz
static const uint8_t _LBM_DOT[] = {
#include "mask_dot.lbm"
};
static const uint8_t _LBM_TOPMENU_GPS[] = {
#include "mask_topmenu_gps_18.lbm"
};
static const uint8_t _LBM_TOPMENU_USB[] = {
#include "mask_topmenu_usb.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_0[] = {
#include "mask_volume_0.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_1[] = {
#include "mask_volume_1.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_2[] = {
#include "mask_volume_2.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_3[] = {
#include "mask_volume_3.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_4[] = {
#include "mask_volume_4.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_SCALE[] = {
#include "mask_volume_scale.lbm"
};
static const uint8_t _LBM_TOPMENU_TXBATT[] = {
#include "mask_txbat.lbm"
};
static const uint8_t _LBM_TOPMENU_TXBATT_CHARGING[] = {
#include "mask_txbat_charging.lbm"
};
static const uint8_t _LBM_TOPMENU_ANTENNA[] = {
#include "mask_antenna.lbm"
};
STATIC_LZ4_BITMAP(LBM_DOT);
STATIC_LZ4_BITMAP(LBM_TOPMENU_GPS);
STATIC_LZ4_BITMAP(LBM_TOPMENU_USB);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_0);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_1);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_2);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_3);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_4);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_SCALE);
STATIC_LZ4_BITMAP(LBM_TOPMENU_TXBATT);
STATIC_LZ4_BITMAP(LBM_TOPMENU_TXBATT_CHARGING);
STATIC_LZ4_BITMAP(LBM_TOPMENU_ANTENNA);
TopbarImpl::TopbarImpl(Window * parent) :
TopbarImplBase(parent, {0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData)
{
@@ -92,21 +31,21 @@ TopbarImpl::TopbarImpl(Window * parent) :
unsigned int TopbarImpl::getZonesCount() const
{
#if defined(INTERNAL_GPS)
if (hasSerialMode(UART_MODE_GPS) != -1) {
return MAX_TOPBAR_ZONES-1;
}
#endif
return MAX_TOPBAR_ZONES;
}
rect_t TopbarImpl::getZone(unsigned int index) const
{
if (index == MAX_TOPBAR_ZONES - 1) {
coord_t size = LCD_W - 48 - (MAX_TOPBAR_ZONES - 1) * (TOPBAR_ZONE_WIDTH + TOPBAR_ZONE_HMARGIN);
return {LCD_W - size, TOPBAR_ZONE_VMARGIN, size, TOPBAR_ZONE_HEIGHT};
}
return {
coord_t(49 + (TOPBAR_ZONE_WIDTH + 2 * TOPBAR_ZONE_MARGIN) * index),
TOPBAR_ZONE_MARGIN,
coord_t(48 + (TOPBAR_ZONE_WIDTH + TOPBAR_ZONE_HMARGIN) * index),
TOPBAR_ZONE_VMARGIN,
TOPBAR_ZONE_WIDTH,
TOPBAR_HEIGHT
TOPBAR_ZONE_HEIGHT
};
}
@@ -139,137 +78,8 @@ coord_t TopbarImpl::getVisibleHeight(float visible) const // 0.0 -> 1.0
void TopbarImpl::paint(BitmapBuffer * dc)
{
dc->drawSolidFilledRect(0, 0, width(), height(), COLOR_THEME_SECONDARY1);
EdgeTxTheme::instance()->drawHeaderIcon(dc, ICON_EDGETX);
const TimerOptions timerOptions = {.options = SHOW_TIME};
struct gtm t;
gettime(&t);
char str[10];
#if defined(TRANSLATIONS_CN) || defined(TRANSLATIONS_TW)
sprintf(str, "%02d-%02d", t.tm_mon + 1, t.tm_mday);
#else
sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]);
#endif
//dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, COLOR_THEME_SECONDARY1);
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE1, str, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
getTimerString(str, getValue(MIXSRC_TX_TIME), timerOptions);
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
#if defined(INTERNAL_GPS)
if (hasSerialMode(UART_MODE_GPS) != -1) {
if (gpsData.fix) {
char s[10];
sprintf(s, "%d", gpsData.numSat);
dc->drawText(GPS_X, 4, s, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
}
dc->drawBitmapPattern(
GPS_X - 10, 22, LBM_TOPMENU_GPS,
(gpsData.fix) ? COLOR_THEME_PRIMARY2 : COLOR_THEME_PRIMARY3);
}
#endif
// USB icon
if (usbPlugged()) {
LcdFlags flags = COLOR_THEME_PRIMARY2;
if (getSelectedUsbMode() == USB_UNSELECTED_MODE) {
flags = COLOR_THEME_PRIMARY3;
}
dc->drawBitmapPattern(USB_X, 8, LBM_TOPMENU_USB, flags);
}
// Logs
else if (isFunctionActive(FUNCTION_LOGS) && BLINK_ON_PHASE) {
dc->drawBitmapPattern(LOG_X, 6, LBM_DOT, COLOR_THEME_PRIMARY2);
}
// RSSI
const uint8_t rssiBarsValue[] = {30, 40, 50, 60, 80};
const uint8_t rssiBarsHeight[] = {5, 10, 15, 21, 31};
for (unsigned int i = 0; i < DIM(rssiBarsHeight); i++) {
uint8_t height = rssiBarsHeight[i];
dc->drawSolidFilledRect(RSSI_X + i * 6, 38 - height, 4, height,
TELEMETRY_RSSI() >= rssiBarsValue[i]
? COLOR_THEME_PRIMARY2
: COLOR_THEME_PRIMARY3);
}
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) {
dc->drawBitmapPattern(RSSI_X - 4, 4, LBM_TOPMENU_ANTENNA, COLOR_THEME_PRIMARY2);
}
#endif
/* Audio volume */
dc->drawBitmapPattern(AUDIO_X, 4, LBM_TOPMENU_VOLUME_SCALE, COLOR_THEME_PRIMARY3);
if (requiredSpeakerVolume == 0 || g_eeGeneral.beepMode == e_mode_quiet)
dc->drawBitmapPattern(AUDIO_X, 4, LBM_TOPMENU_VOLUME_0, COLOR_THEME_PRIMARY2);
else if (requiredSpeakerVolume < 7)
dc->drawBitmapPattern(AUDIO_X, 4, LBM_TOPMENU_VOLUME_1, COLOR_THEME_PRIMARY2);
else if (requiredSpeakerVolume < 13)
dc->drawBitmapPattern(AUDIO_X, 4, LBM_TOPMENU_VOLUME_2, COLOR_THEME_PRIMARY2);
else if (requiredSpeakerVolume < 19)
dc->drawBitmapPattern(AUDIO_X, 4, LBM_TOPMENU_VOLUME_3, COLOR_THEME_PRIMARY2);
else
dc->drawBitmapPattern(AUDIO_X, 4, LBM_TOPMENU_VOLUME_4, COLOR_THEME_PRIMARY2);
/* Tx battery */
uint8_t bars = GET_TXBATT_BARS(5);
#if defined(USB_CHARGER)
if (usbChargerLed()) {
dc->drawBitmapPattern(AUDIO_X, 25, LBM_TOPMENU_TXBATT_CHARGING, COLOR_THEME_PRIMARY2);
}
else {
dc->drawBitmapPattern(AUDIO_X, 25, LBM_TOPMENU_TXBATT, COLOR_THEME_PRIMARY2);
}
#else
dc->drawBitmapPattern(AUDIO_X, 25, LBM_TOPMENU_TXBATT, COLOR_THEME_PRIMARY2);
#endif
for (unsigned int i = 0; i < 5; i++) {
dc->drawSolidFilledRect(AUDIO_X + 2 + 4 * i, 30, 2, 8, i >= bars ? COLOR_THEME_PRIMARY3 : COLOR_THEME_PRIMARY2);
}
#if 0
// Radio battery - TODO
// drawValueWithUnit(370, 8, g_vbat100mV, UNIT_VOLTS, PREC1|FONT(XS)|COLOR_THEME_SECONDARY1);
// lcdDrawSolidRect(300, 3, 20, 50, COLOR_THEME_SECONDARY1);
// lcdDrawRect(batt_icon_x+FW, BAR_Y+1, 13, 7);
// lcdDrawSolidVerticalLine(batt_icon_x+FW+13, BAR_Y+2, 5);
// Rx battery
if (g_model.voltsSource) {
TelemetryItem & item = telemetryItems[g_model.voltsSource-1];
if (item.isAvailable()) {
int32_t value = item.value;
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
LcdFlags att = 0;
if (sensor.prec == 2) {
att |= PREC1;
value /= 10;
}
else if (sensor.prec == 1) {
att |= PREC1;
}
att |= (item.isOld() ? COLOR_THEME_WARNING : COLOR_THEME_SECONDARY1);
lcdDrawSolidFilledRect(ALTITUDE_X, VOLTS_Y, ALTITUDE_W, ALTITUDE_H, COLOR_THEME_SECONDARY3);
lcdDrawText(ALTITUDE_X+PADDING, VOLTS_Y+2, "Voltage", att);
drawValueWithUnit(ALTITUDE_X+PADDING, VOLTS_Y+12, value, UNIT_VOLTS, FONT(XL)|LEFT|att);
}
}
// Model altitude
if (g_model.frsky.altitudeSource) {
TelemetryItem & item = telemetryItems[g_model.frsky.altitudeSource-1];
if (item.isAvailable()) {
int32_t value = item.value;
TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1];
if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10;
LcdFlags att = (item.isOld() ? COLOR_THEME_WARNING : COLOR_THEME_SECONDARY1);
lcdDrawSolidFilledRect(ALTITUDE_X, ALTITUDE_Y, ALTITUDE_W, ALTITUDE_H, COLOR_THEME_SECONDARY3);
lcdDrawText(ALTITUDE_X+PADDING, ALTITUDE_Y+2, "Alt", att);
drawValueWithUnit(ALTITUDE_X+PADDING, ALTITUDE_Y+12, value, UNIT_METERS, FONT(XL)|LEFT|att);
}
}
#endif
}
void TopbarImpl::checkEvents()
@@ -281,3 +91,23 @@ void TopbarImpl::checkEvents()
}
}
void TopbarImpl::removeWidget(unsigned int index)
{
bool mark = false;
// If user manually removes 'system' widgets, mark name so widget does not get reloaded on restart
if ((index == MAX_TOPBAR_ZONES - 1) && (strcmp(persistentData->zones[index].widgetName, "Date Time") == 0))
mark = true;
if ((index == MAX_TOPBAR_ZONES - 2) && (strcmp(persistentData->zones[index].widgetName, "Radio Info") == 0))
mark = true;
#if defined(INTERNAL_GPS)
if ((index == MAX_TOPBAR_ZONES - 3) && (strcmp(persistentData->zones[index].widgetName, "Internal GPS") == 0))
mark = true;
#endif
WidgetsContainerImpl::removeWidget(index);
// If user manually removes 'system' widgets, mark name so widget does not get reloaded on restart
if (mark)
strcpy(persistentData->zones[index].widgetName, "--");
}
+2 -1
View File
@@ -56,7 +56,8 @@ class TopbarImpl:
void checkEvents() override;
void removeWidget(unsigned int index) override;
protected:
uint32_t lastRefresh = 0;
};
+2 -2
View File
@@ -302,7 +302,7 @@ class PreviewWindow : public FormWindow
dc->clear(COLOR_THEME_SECONDARY3);
// top bar background
dc->drawSolidFilledRect(0, 0, rect.w, TOPBAR_HEIGHT, COLOR_THEME_SECONDARY1);
dc->drawSolidFilledRect(0, 0, rect.w, TOPBAR_ZONE_HEIGHT, COLOR_THEME_SECONDARY1);
int width;
int x = 5;
@@ -315,7 +315,7 @@ class PreviewWindow : public FormWindow
delete bm;
dc->drawSolidFilledRect(x - 2, 0, MENU_HEADER_BUTTON_WIDTH + 2,
TOPBAR_HEIGHT, COLOR_THEME_FOCUS);
TOPBAR_ZONE_HEIGHT, COLOR_THEME_FOCUS);
auto mask_radio_tools = getBuiltinIcon(ICON_RADIO_TOOLS);
bm = getBitmap(mask_radio_tools, COLOR_THEME_FOCUS, COLOR_THEME_PRIMARY2,
&width);
+3 -2
View File
@@ -24,8 +24,9 @@
#include "layout.h"
constexpr coord_t TOPBAR_ZONE_WIDTH = 70;
constexpr coord_t TOPBAR_ZONE_MARGIN = 3;
constexpr coord_t TOPBAR_HEIGHT = MENU_HEADER_HEIGHT - 2 * TOPBAR_ZONE_MARGIN;
constexpr coord_t TOPBAR_ZONE_VMARGIN = 3;
constexpr coord_t TOPBAR_ZONE_HMARGIN = 3;
constexpr coord_t TOPBAR_ZONE_HEIGHT = MENU_HEADER_HEIGHT - 2 * TOPBAR_ZONE_VMARGIN;
class ScreenMenu;
class TopbarImpl;
@@ -0,0 +1,270 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
#include "widgets_container_impl.h"
#define W_AUDIO_X 0
#define W_USB_X 32
#define W_LOG_X 32
#define W_RSSI_X 40
static const uint8_t _LBM_DOT[] = {
#include "mask_dot.lbm"
};
static const uint8_t _LBM_TOPMENU_USB[] = {
#include "mask_topmenu_usb.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_0[] = {
#include "mask_volume_0.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_1[] = {
#include "mask_volume_1.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_2[] = {
#include "mask_volume_2.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_3[] = {
#include "mask_volume_3.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_4[] = {
#include "mask_volume_4.lbm"
};
static const uint8_t _LBM_TOPMENU_VOLUME_SCALE[] = {
#include "mask_volume_scale.lbm"
};
static const uint8_t _LBM_TOPMENU_TXBATT[] = {
#include "mask_txbat.lbm"
};
static const uint8_t _LBM_TOPMENU_TXBATT_CHARGING[] = {
#include "mask_txbat_charging.lbm"
};
static const uint8_t _LBM_TOPMENU_ANTENNA[] = {
#include "mask_antenna.lbm"
};
STATIC_LZ4_BITMAP(LBM_DOT);
STATIC_LZ4_BITMAP(LBM_TOPMENU_USB);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_0);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_1);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_2);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_3);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_4);
STATIC_LZ4_BITMAP(LBM_TOPMENU_VOLUME_SCALE);
STATIC_LZ4_BITMAP(LBM_TOPMENU_TXBATT);
STATIC_LZ4_BITMAP(LBM_TOPMENU_TXBATT_CHARGING);
STATIC_LZ4_BITMAP(LBM_TOPMENU_ANTENNA);
class RadioInfoWidget: public Widget
{
protected:
public:
RadioInfoWidget(const WidgetFactory* factory, Window* parent,
const rect_t& rect, Widget::PersistentData* persistentData) :
Widget(factory, parent, rect, persistentData)
{
}
void refresh(BitmapBuffer * dc) override
{
// USB icon
if (usbPlugged()) {
LcdFlags flags = COLOR_THEME_PRIMARY2;
if (getSelectedUsbMode() == USB_UNSELECTED_MODE) {
flags = COLOR_THEME_PRIMARY3;
}
dc->drawBitmapPattern(W_USB_X, 5, LBM_TOPMENU_USB, flags);
}
// Logs
else if (isFunctionActive(FUNCTION_LOGS) && BLINK_ON_PHASE) {
dc->drawBitmapPattern(W_LOG_X, 3, LBM_DOT, COLOR_THEME_PRIMARY2);
}
// RSSI
const uint8_t rssiBarsValue[] = {30, 40, 50, 60, 80};
const uint8_t rssiBarsHeight[] = {5, 10, 15, 21, 31};
for (unsigned int i = 0; i < DIM(rssiBarsHeight); i++) {
uint8_t height = rssiBarsHeight[i];
dc->drawSolidFilledRect(W_RSSI_X + i * 6, 35 - height, 4, height,
TELEMETRY_RSSI() >= rssiBarsValue[i]
? COLOR_THEME_PRIMARY2
: COLOR_THEME_PRIMARY3);
}
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) {
dc->drawBitmapPattern(W_RSSI_X - 4, 1, LBM_TOPMENU_ANTENNA, COLOR_THEME_PRIMARY2);
}
#endif
/* Audio volume */
dc->drawBitmapPattern(W_AUDIO_X, 1, LBM_TOPMENU_VOLUME_SCALE, COLOR_THEME_PRIMARY3);
if (requiredSpeakerVolume == 0 || g_eeGeneral.beepMode == e_mode_quiet)
dc->drawBitmapPattern(W_AUDIO_X, 1, LBM_TOPMENU_VOLUME_0, COLOR_THEME_PRIMARY2);
else if (requiredSpeakerVolume < 7)
dc->drawBitmapPattern(W_AUDIO_X, 1, LBM_TOPMENU_VOLUME_1, COLOR_THEME_PRIMARY2);
else if (requiredSpeakerVolume < 13)
dc->drawBitmapPattern(W_AUDIO_X, 1, LBM_TOPMENU_VOLUME_2, COLOR_THEME_PRIMARY2);
else if (requiredSpeakerVolume < 19)
dc->drawBitmapPattern(W_AUDIO_X, 1, LBM_TOPMENU_VOLUME_3, COLOR_THEME_PRIMARY2);
else
dc->drawBitmapPattern(W_AUDIO_X, 1, LBM_TOPMENU_VOLUME_4, COLOR_THEME_PRIMARY2);
/* Tx battery */
uint8_t bars = GET_TXBATT_BARS(5);
#if defined(USB_CHARGER)
if (usbChargerLed()) {
dc->drawBitmapPattern(W_AUDIO_X, 22, LBM_TOPMENU_TXBATT_CHARGING, COLOR_THEME_PRIMARY2);
}
else {
dc->drawBitmapPattern(W_AUDIO_X, 22, LBM_TOPMENU_TXBATT, COLOR_THEME_PRIMARY2);
}
#else
dc->drawBitmapPattern(W_AUDIO_X, 22, LBM_TOPMENU_TXBATT, COLOR_THEME_PRIMARY2);
#endif
for (unsigned int i = 0; i < 5; i++) {
dc->drawSolidFilledRect(W_AUDIO_X + 2 + 4 * i, 27, 2, 8, i >= bars ? COLOR_THEME_PRIMARY3 : COLOR_THEME_PRIMARY2);
}
}
void checkEvents() override
{
Widget::checkEvents();
invalidate();
}
static const ZoneOption options[];
};
BaseWidgetFactory<RadioInfoWidget> RadioInfoWidget("Radio Info", nullptr, "Radio Info");
// Adjustment to make main view date/time align with model/radio settings views
#if LCD_W > LCD_H
#define DT_OFFSET 8
#else
#define DT_OFFSET 1
#endif
class DateTimeWidget: public Widget
{
protected:
public:
DateTimeWidget(const WidgetFactory* factory, Window* parent,
const rect_t& rect, Widget::PersistentData* persistentData) :
Widget(factory, parent, rect, persistentData)
{
}
void refresh(BitmapBuffer * dc) override
{
// get color from options
LcdFlags color = COLOR2FLAGS(persistentData->options[0].value.unsignedValue);
const TimerOptions timerOptions = {.options = SHOW_TIME};
struct gtm t;
gettime(&t);
char str[10];
#if defined(TRANSLATIONS_CN) || defined(TRANSLATIONS_TW)
sprintf(str, "%02d-%02d", t.tm_mon + 1, t.tm_mday);
#else
sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]);
#endif
dc->drawText(width()/2+DT_OFFSET, 3, str, FONT(XS) | CENTERED | color);
getTimerString(str, getValue(MIXSRC_TX_TIME), timerOptions);
dc->drawText(width()/2+DT_OFFSET, 18, str, FONT(XS) | CENTERED | color);
}
void checkEvents() override
{
Widget::checkEvents();
invalidate();
}
static const ZoneOption options[];
};
const ZoneOption DateTimeWidget::options[] = {
{ STR_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(COLOR_THEME_PRIMARY2) },
{ nullptr, ZoneOption::Bool }
};
BaseWidgetFactory<DateTimeWidget> DateTimeWidget("Date Time", DateTimeWidget::options, "Date Time");
#if defined(INTERNAL_GPS)
static const uint8_t _LBM_TOPMENU_GPS[] = {
#include "mask_topmenu_gps_18.lbm"
};
STATIC_LZ4_BITMAP(LBM_TOPMENU_GPS);
class InternalGPSWidget: public Widget
{
protected:
public:
InternalGPSWidget(const WidgetFactory* factory, Window* parent,
const rect_t& rect, Widget::PersistentData* persistentData) :
Widget(factory, parent, rect, persistentData)
{
}
void refresh(BitmapBuffer * dc) override
{
if (hasSerialMode(UART_MODE_GPS) != -1) {
if (gpsData.fix) {
char s[10];
sprintf(s, "%d", gpsData.numSat);
dc->drawText(width() / 2, 1, s, FONT(XS) | CENTERED | COLOR_THEME_PRIMARY2);
}
dc->drawBitmapPattern(
width() / 2 - 10, 19, LBM_TOPMENU_GPS,
(gpsData.fix) ? COLOR_THEME_PRIMARY2 : COLOR_THEME_PRIMARY3);
}
}
void checkEvents() override
{
Widget::checkEvents();
invalidate();
}
static const ZoneOption options[];
};
BaseWidgetFactory<InternalGPSWidget> InternalGPSWidget("Internal GPS", nullptr, "Internal GPS");
#endif
+2 -2
View File
@@ -31,9 +31,9 @@
#define MAX_WIDGET_OPTIONS 5 // Name?
#if LCD_W > LCD_H
#define MAX_TOPBAR_ZONES 4
#define MAX_TOPBAR_ZONES 6
#else
#define MAX_TOPBAR_ZONES 2
#define MAX_TOPBAR_ZONES 4
#endif
#define MAX_TOPBAR_OPTIONS 1 // just because of VC++ which doesn't like 0-size arrays :(
+1 -6
View File
@@ -66,12 +66,7 @@ SetupWidgetsPageSlot::SetupWidgetsPageSlot(FormWindow* parent,
void SetupWidgetsPageSlot::paint(BitmapBuffer* dc)
{
if (hasFocus()) {
dc->drawRect(0, 0, width() - 1, height() - 1, 2, STASHED,
COLOR_THEME_FOCUS);
} else {
dc->drawSolidRect(0, 0, width() - 1, height() - 1, 2, COLOR_THEME_PRIMARY3);
}
dc->drawRect(0, 0, width(), height(), 2, hasFocus() ? STASHED : SOLID, COLOR_THEME_FOCUS);
}
SetupWidgetsPage::SetupWidgetsPage(uint8_t customScreenIdx) :
+22
View File
@@ -139,6 +139,28 @@ static void sortMixerLines()
void postModelLoad(bool alarms)
{
#if defined(COLORLCD)
// Load 'date time' widget if slot is empty
if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetName[0] == 0) {
strcpy(g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetName, "Date Time");
g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetData.options[0].type = ZOV_Color;
g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetData.options[0].value.unsignedValue = 0xFFFFFF;
storageDirty(EE_MODEL);
}
// Load 'radio info' widget if slot is empty
if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-2].widgetName[0] == 0) {
strcpy(g_model.topbarData.zones[MAX_TOPBAR_ZONES-2].widgetName, "Radio Info");
storageDirty(EE_MODEL);
}
#if defined(INTERNAL_GPS)
// Load 'internal gps' widget if slot is empty
if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-3].widgetName[0] == 0) {
strcpy(g_model.topbarData.zones[MAX_TOPBAR_ZONES-3].widgetName, "Internal GPS");
storageDirty(EE_MODEL);
}
#endif
#endif
// Convert 'noGlobalFunctions' to 'radioGFDisabled'
// TODO: Remove sometime in the future (and remove 'noGlobalFunctions' property)
if (g_model.noGlobalFunctions) {
@@ -287,7 +287,7 @@ static const struct YamlNode struct_ZoneOptionValueTyped[] = {
YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov),
YAML_END
};
static const struct YamlNode struct_OpenTxTheme__PersistentData[] = {
static const struct YamlNode struct_EdgeTxTheme__PersistentData[] = {
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
@@ -373,7 +373,7 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "blOffBright", 7 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("themeName", 8),
YAML_STRUCT("themeData", 480, struct_OpenTxTheme__PersistentData, NULL),
YAML_STRUCT("themeData", 480, struct_EdgeTxTheme__PersistentData, NULL),
YAML_STRING("ownerRegistrationID", 8),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 2 ),
@@ -785,7 +785,7 @@ static const struct YamlNode struct_CustomScreenData[] = {
YAML_END
};
static const struct YamlNode struct_TopBarPersistentData[] = {
YAML_ARRAY("zones", 576, 2, struct_ZonePersistentData, NULL),
YAML_ARRAY("zones", 576, 4, struct_ZonePersistentData, NULL),
YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
@@ -849,7 +849,7 @@ static const struct YamlNode struct_ModelData[] = {
YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL),
YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL),
YAML_ARRAY("screenData", 6816, 10, struct_CustomScreenData, NULL),
YAML_STRUCT("topbarData", 1248, struct_TopBarPersistentData, NULL),
YAML_STRUCT("topbarData", 2400, struct_TopBarPersistentData, NULL),
YAML_UNSIGNED( "view", 8 ),
YAML_STRING("modelRegistrationID", 8),
YAML_UNSIGNED( "usbJoystickExtMode", 1 ),
@@ -295,7 +295,7 @@ static const struct YamlNode struct_ZoneOptionValueTyped[] = {
YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov),
YAML_END
};
static const struct YamlNode struct_OpenTxTheme__PersistentData[] = {
static const struct YamlNode struct_EdgeTxTheme__PersistentData[] = {
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
@@ -379,7 +379,7 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "blOffBright", 7 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("themeName", 8),
YAML_STRUCT("themeData", 480, struct_OpenTxTheme__PersistentData, NULL),
YAML_STRUCT("themeData", 480, struct_EdgeTxTheme__PersistentData, NULL),
YAML_STRING("ownerRegistrationID", 8),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 2 ),
@@ -793,7 +793,7 @@ static const struct YamlNode struct_CustomScreenData[] = {
YAML_END
};
static const struct YamlNode struct_TopBarPersistentData[] = {
YAML_ARRAY("zones", 576, 4, struct_ZonePersistentData, NULL),
YAML_ARRAY("zones", 576, 6, struct_ZonePersistentData, NULL),
YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
@@ -857,7 +857,7 @@ static const struct YamlNode struct_ModelData[] = {
YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL),
YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL),
YAML_ARRAY("screenData", 6816, 10, struct_CustomScreenData, NULL),
YAML_STRUCT("topbarData", 2400, struct_TopBarPersistentData, NULL),
YAML_STRUCT("topbarData", 3552, struct_TopBarPersistentData, NULL),
YAML_UNSIGNED( "view", 8 ),
YAML_STRING("modelRegistrationID", 8),
YAML_UNSIGNED( "usbJoystickExtMode", 1 ),
@@ -295,7 +295,7 @@ static const struct YamlNode struct_ZoneOptionValueTyped[] = {
YAML_UNION("value", 64, union_ZoneOptionValue_elmts, select_zov),
YAML_END
};
static const struct YamlNode struct_OpenTxTheme__PersistentData[] = {
static const struct YamlNode struct_EdgeTxTheme__PersistentData[] = {
YAML_ARRAY("options", 96, 5, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
@@ -379,7 +379,7 @@ static const struct YamlNode struct_RadioData[] = {
YAML_UNSIGNED( "blOffBright", 7 ),
YAML_STRING("bluetoothName", 10),
YAML_STRING("themeName", 8),
YAML_STRUCT("themeData", 480, struct_OpenTxTheme__PersistentData, NULL),
YAML_STRUCT("themeData", 480, struct_EdgeTxTheme__PersistentData, NULL),
YAML_STRING("ownerRegistrationID", 8),
YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr),
YAML_UNSIGNED( "rotEncMode", 2 ),
@@ -793,7 +793,7 @@ static const struct YamlNode struct_CustomScreenData[] = {
YAML_END
};
static const struct YamlNode struct_TopBarPersistentData[] = {
YAML_ARRAY("zones", 576, 4, struct_ZonePersistentData, NULL),
YAML_ARRAY("zones", 576, 6, struct_ZonePersistentData, NULL),
YAML_ARRAY("options", 96, 1, struct_ZoneOptionValueTyped, NULL),
YAML_END
};
@@ -857,7 +857,7 @@ static const struct YamlNode struct_ModelData[] = {
YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL),
YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL),
YAML_ARRAY("screenData", 6816, 10, struct_CustomScreenData, NULL),
YAML_STRUCT("topbarData", 2400, struct_TopBarPersistentData, NULL),
YAML_STRUCT("topbarData", 3552, struct_TopBarPersistentData, NULL),
YAML_UNSIGNED( "view", 8 ),
YAML_STRING("modelRegistrationID", 8),
YAML_UNSIGNED( "usbJoystickExtMode", 1 ),
@@ -21,12 +21,6 @@
#pragma once
constexpr uint32_t RSSI_X = LCD_W - 90;
constexpr uint32_t AUDIO_X = LCD_W - 130;
constexpr uint32_t USB_X = LCD_W - 98;
constexpr uint32_t LOG_X = LCD_W - 98;
constexpr uint32_t GPS_X = LCD_W - 148;
constexpr uint32_t ALERT_FRAME_TOP = 70;
constexpr uint32_t ALERT_FRAME_HEIGHT = (LCD_H - 2 * ALERT_FRAME_TOP);
constexpr uint32_t ALERT_BITMAP_TOP = ALERT_FRAME_TOP + 15;
@@ -21,12 +21,6 @@
#pragma once
constexpr uint32_t RSSI_X = LCD_W - 80;
constexpr uint32_t AUDIO_X = LCD_W - 115;
constexpr uint32_t USB_X = LCD_W - 82;
constexpr uint32_t LOG_X = LCD_W - 82;
constexpr uint32_t GPS_X = LCD_W - 130;
constexpr uint32_t ALERT_FRAME_TOP = 70;
constexpr uint32_t ALERT_FRAME_HEIGHT = (LCD_H - 2 * ALERT_FRAME_TOP);
constexpr uint32_t ALERT_BITMAP_TOP = ALERT_FRAME_TOP + 15;