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:
@@ -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
|
||||
|
||||
@@ -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, "--");
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ class TopbarImpl:
|
||||
|
||||
void checkEvents() override;
|
||||
|
||||
|
||||
void removeWidget(unsigned int index) override;
|
||||
|
||||
protected:
|
||||
uint32_t lastRefresh = 0;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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 :(
|
||||
|
||||
|
||||
@@ -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) :
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user