@@ -22,10 +22,12 @@ set(GUI_SRC
|
||||
fab_button.cpp
|
||||
# topbar.cpp
|
||||
layout.cpp
|
||||
# widget.cpp
|
||||
widget.cpp
|
||||
${THEMES_SRC}
|
||||
${LAYOUTS_SRC}
|
||||
# ${WIDGETS_SRC}
|
||||
# ${WIDGETS_SRC}
|
||||
widgets/text.cpp
|
||||
widgets/value.cpp
|
||||
# popups.cpp
|
||||
draw_functions.cpp
|
||||
# menus.cpp
|
||||
|
||||
@@ -474,6 +474,19 @@ void drawSensorCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, uint8_t sens
|
||||
}
|
||||
}
|
||||
|
||||
void drawTimer(BitmapBuffer * dc, coord_t x, coord_t y, int32_t tme, LcdFlags flags)
|
||||
{
|
||||
char str[LEN_TIMER_STRING];
|
||||
getTimerString(str, tme, (flags & TIMEHOUR) != 0);
|
||||
dc->drawText(x, y, str, flags);
|
||||
}
|
||||
|
||||
void drawSourceValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t source, LcdFlags flags)
|
||||
{
|
||||
getvalue_t value = getValue(source);
|
||||
drawSourceCustomValue(dc, x, y, source, value, flags);
|
||||
}
|
||||
|
||||
void drawSourceCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t source, int32_t value, LcdFlags flags)
|
||||
{
|
||||
if (source >= MIXSRC_FIRST_TELEM) {
|
||||
|
||||
@@ -64,6 +64,8 @@ void drawHorizontalSlider(BitmapBuffer * dc, coord_t x, coord_t y, int len, int
|
||||
void drawSlider(coord_t x, coord_t y, int len, int val, int min, int max, uint8_t steps, uint32_t options);
|
||||
void drawValueOrGVar(BitmapBuffer * dc, coord_t x, coord_t y, gvar_t value, gvar_t vmin, gvar_t vmax, LcdFlags flags = 0);
|
||||
void drawGVarValue(BitmapBuffer * dc, coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags = 0);
|
||||
void drawTimer(BitmapBuffer * dc, coord_t x, coord_t y, int32_t tme, LcdFlags flags = 0);
|
||||
void drawSourceValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t source, LcdFlags flags = 0);
|
||||
void drawSourceCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t source, int32_t value, LcdFlags flags);
|
||||
void drawSensorCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, uint8_t sensor, int32_t value, LcdFlags flags = 0);
|
||||
void drawGPSPosition(BitmapBuffer * dc, coord_t x, coord_t y, int32_t longitude, int32_t latitude, LcdFlags flags = 0);
|
||||
|
||||
@@ -35,7 +35,7 @@ class Layout: public WidgetsContainer<MAX_LAYOUT_ZONES, MAX_LAYOUT_OPTIONS>
|
||||
|
||||
public:
|
||||
Layout(const LayoutFactory * factory, PersistentData * persistentData):
|
||||
WidgetsContainer<MAX_LAYOUT_ZONES, MAX_LAYOUT_OPTIONS>(persistentData),
|
||||
WidgetsContainer<MAX_LAYOUT_ZONES, MAX_LAYOUT_OPTIONS>({0, 0, LCD_W, LCD_H}, persistentData),
|
||||
factory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@ class Layout1x1: public Layout
|
||||
return 1;
|
||||
}
|
||||
|
||||
Zone getZone(unsigned int index) const override
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
Zone zone = { 10, 10, LCD_W - 2*10, LCD_H - 2*10 };
|
||||
rect_t zone = { 10, 10, LCD_W - 2*10, LCD_H - 2*10 };
|
||||
if (persistentData->options[0].value.boolValue) {
|
||||
zone.y += MENU_HEADER_HEIGHT;
|
||||
zone.h -= MENU_HEADER_HEIGHT;
|
||||
|
||||
@@ -32,7 +32,7 @@ const ZoneOption OPTIONS_LAYOUT_2P1[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
const Zone ZONES_LAYOUT_2P1[3] = {
|
||||
const rect_t ZONES_LAYOUT_2P1[3] = {
|
||||
{ 240, 60, 192, 152 },
|
||||
{ 48, 60, 180, 70 },
|
||||
{ 48, 142, 180, 70 }
|
||||
@@ -60,7 +60,7 @@ class Layout2P1: public Layout
|
||||
return DIM(ZONES_LAYOUT_2P1);
|
||||
}
|
||||
|
||||
Zone getZone(unsigned int index) const override
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
return ZONES_LAYOUT_2P1[index];
|
||||
}
|
||||
|
||||
@@ -48,9 +48,9 @@ class Layout2x1: public Layout
|
||||
return 2;
|
||||
}
|
||||
|
||||
Zone getZone(unsigned int index) const override
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
Zone zone;
|
||||
rect_t zone;
|
||||
zone.w = (LCD_W-3*10) / 2;
|
||||
zone.x = (index & 1) ? 20 + zone.w : 10;
|
||||
if (persistentData->options[0].value.boolValue) {
|
||||
|
||||
@@ -48,9 +48,9 @@ class Layout2x2: public Layout
|
||||
return 4;
|
||||
}
|
||||
|
||||
Zone getZone(unsigned int index) const override
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
Zone zone;
|
||||
rect_t zone;
|
||||
zone.w = (LCD_W-3*10) / 2;
|
||||
zone.x = (index & 1) ? 20 + zone.w : 10;
|
||||
if (persistentData->options[0].value.boolValue) {
|
||||
|
||||
@@ -62,9 +62,9 @@ class Layout2x4: public Layout
|
||||
return 8;
|
||||
}
|
||||
|
||||
Zone getZone(unsigned int index) const override
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
Zone zone;
|
||||
rect_t zone;
|
||||
zone.x = (index >= 4) ? 260 : 60;
|
||||
zone.y = 56 + (index % 4) * 42;
|
||||
zone.w = 160;
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "sliders.h"
|
||||
|
||||
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
|
||||
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
|
||||
#define HAS_SLIDERS() (persistentData->options[2].value.boolValue == true)
|
||||
#define HAS_TRIMS() (persistentData->options[3].value.boolValue == true)
|
||||
#define IS_MIRRORED() (persistentData->options[4].value.boolValue == true)
|
||||
|
||||
const uint8_t LBM_LAYOUT_4P2[] = {
|
||||
#include "mask_layout4+2.lbm"
|
||||
};
|
||||
|
||||
const ZoneOption OPTIONS_LAYOUT_4P2[] = {
|
||||
{ STR_TOP_BAR, ZoneOption::Bool },
|
||||
{ STR_FLIGHT_MODE, ZoneOption::Bool },
|
||||
{ STR_SLIDERS, ZoneOption::Bool },
|
||||
{ STR_TRIMS, ZoneOption::Bool },
|
||||
{ STR_MIRROR, ZoneOption::Bool },
|
||||
{ NULL, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
constexpr coord_t HTRIM_W = 120;
|
||||
constexpr coord_t HTRIM_H = 40;
|
||||
constexpr coord_t HSLIDER_W = 120;
|
||||
constexpr coord_t HSLIDER_H = 40;
|
||||
|
||||
class Layout4P2: public Layout
|
||||
{
|
||||
public:
|
||||
Layout4P2(const LayoutFactory * factory, Layout::PersistentData * persistentData):
|
||||
Layout(factory, persistentData)
|
||||
{
|
||||
decorate();
|
||||
}
|
||||
|
||||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0].value.boolValue = true;
|
||||
persistentData->options[1].value.boolValue = true;
|
||||
persistentData->options[2].value.boolValue = true;
|
||||
persistentData->options[3].value.boolValue = true;
|
||||
persistentData->options[4].value.boolValue = false;
|
||||
persistentData->options[5].value.boolValue = false;
|
||||
|
||||
decorate();
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
if (1 /*HAS_SLIDERS()*/) {
|
||||
new MainViewHorizontalSlider(this, {0, LCD_H - HTRIM_H - 1, HTRIM_W, HSLIDER_H}, [=] { return calibratedAnalogs[CALIBRATED_POT1]; }, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
new MainViewHorizontalSlider(this, {LCD_W - HTRIM_W, LCD_H - HTRIM_H, HTRIM_W, HSLIDER_H}, [=] { return calibratedAnalogs[CALIBRATED_POT3]; }, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
coord_t areaw = LCD_W - (HAS_SLIDERS() ? 55 : 8) - (HAS_TRIMS() ? 55 : 8);
|
||||
coord_t areah = LCD_H - 4 - (HAS_TOPBAR() ? 55 : 8) - (HAS_SLIDERS() ? HSLIDER_H + 4 : 4) - (HAS_TRIMS() ? HTRIM_H + 4 : 4);
|
||||
|
||||
rect_t zone;
|
||||
zone.x = IS_MIRRORED() ? ((index >= 4) ? (LCD_W - areaw) / 2 - 4 : 245) : ((index >= 4) ? 245 : (LCD_W - areaw) / 2 - 4);
|
||||
zone.h = (index >= 4) ? (areah / 2) : (areah / 4) - 2;
|
||||
zone.y = (index >= 4) ? (HAS_TOPBAR() ? 52 : 6) + (index == 5 ? zone.h + ((HAS_TRIMS() + HAS_SLIDERS() == 1) ? 8 : 10): 0): (HAS_TOPBAR() ? 52 : 6) + (index % 4) * (zone.h + 6);
|
||||
zone.w = areaw / 2;
|
||||
|
||||
return zone;
|
||||
}
|
||||
|
||||
//virtual void refresh();
|
||||
};
|
||||
|
||||
//void Layout4P2::refresh()
|
||||
//{
|
||||
//theme->drawBackground();
|
||||
|
||||
//if (HAS_TOPBAR()) {
|
||||
// drawTopBar();
|
||||
//}
|
||||
//
|
||||
//if (HAS_FM()) {
|
||||
// // Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, sizeof(g_model.flightModeData[mixerCurrentFlightMode].name),
|
||||
// ZCHAR | SMLSIZE) / 2, 232, g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | SMLSIZE);
|
||||
//}
|
||||
//
|
||||
//if (HAS_SLIDERS()) {
|
||||
// // Pots and rear sliders positions
|
||||
// drawMainPots();
|
||||
//}
|
||||
//
|
||||
//if (HAS_TRIMS()) {
|
||||
// // Trims
|
||||
// drawTrims(mixerCurrentFlightMode, HAS_SLIDERS());
|
||||
//}
|
||||
|
||||
//Layout::refresh();
|
||||
//}
|
||||
|
||||
BaseLayoutFactory<Layout4P2> layout4P2("Layout4P2", "4 + 2", LBM_LAYOUT_4P2, OPTIONS_LAYOUT_4P2);
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 239 B |
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libopenui.h"
|
||||
|
||||
class MainViewSlider : public Window
|
||||
{
|
||||
public:
|
||||
MainViewSlider(Window * parent, const rect_t & rect, std::function<int8_t()> getValue, uint32_t options):
|
||||
Window(parent, rect),
|
||||
options(options),
|
||||
getValue(std::move(getValue))
|
||||
{
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Window::checkEvents();
|
||||
int8_t newValue = getValue();
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t options = 0;
|
||||
std::function<int8_t()> getValue;
|
||||
int8_t value = 0;
|
||||
};
|
||||
|
||||
class MainViewHorizontalSlider : public MainViewSlider
|
||||
{
|
||||
public:
|
||||
using MainViewSlider::MainViewSlider;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
drawHorizontalSlider(dc, 0, 0, width(), getValue(), -RESX, RESX, 40, options);
|
||||
}
|
||||
};
|
||||
@@ -82,6 +82,20 @@ class LayoutChoice: public FormField {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchEnd(coord_t, coord_t) override
|
||||
{
|
||||
if (enabled) {
|
||||
if (!hasFocus()) {
|
||||
setFocus(SET_FOCUS_DEFAULT);
|
||||
}
|
||||
onKeyPress();
|
||||
openMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void openMenu()
|
||||
{
|
||||
auto menu = new Menu(parent);
|
||||
|
||||
@@ -26,14 +26,14 @@ unsigned int Topbar::getZonesCount() const
|
||||
return MAX_TOPBAR_ZONES;
|
||||
}
|
||||
|
||||
Zone Topbar::getZone(unsigned int index) const
|
||||
rect_t Topbar::getZone(unsigned int index) const
|
||||
{
|
||||
Zone zone;
|
||||
zone.x = 49 + (TOPBAR_ZONE_WIDTH + 2*TOPBAR_ZONE_MARGIN) * index;
|
||||
zone.y = TOPBAR_ZONE_MARGIN;
|
||||
zone.w = TOPBAR_ZONE_WIDTH;
|
||||
zone.h = MENU_HEADER_HEIGHT - 2*TOPBAR_ZONE_MARGIN;
|
||||
return zone;
|
||||
rect_t rect;
|
||||
rect.x = 49 + (TOPBAR_ZONE_WIDTH + 2*TOPBAR_ZONE_MARGIN) * index;
|
||||
rect.y = TOPBAR_ZONE_MARGIN;
|
||||
rect.w = TOPBAR_ZONE_WIDTH;
|
||||
rect.h = TOPBAR_HEIGHT;
|
||||
return rect;
|
||||
}
|
||||
|
||||
const char * const STR_MONTHS[] = TR_MONTHS;
|
||||
|
||||
@@ -26,19 +26,20 @@
|
||||
#define MAX_TOPBAR_ZONES 4
|
||||
#define MAX_TOPBAR_OPTIONS 1 // just because of VC++ which doesn't like 0-size arrays :(
|
||||
#define TOPBAR_ZONE_WIDTH 70
|
||||
#define TOPBAR_ZONE_MARGIN 3
|
||||
constexpr coord_t TOPBAR_ZONE_MARGIN = 3;
|
||||
constexpr coord_t TOPBAR_HEIGHT = MENU_HEADER_HEIGHT - 2 * TOPBAR_ZONE_MARGIN;
|
||||
|
||||
class Topbar: public WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>
|
||||
{
|
||||
public:
|
||||
explicit Topbar(PersistentData * persistentData):
|
||||
WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>(persistentData)
|
||||
WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>({0, 0, LCD_W, TOPBAR_ZONE_WIDTH}, persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual unsigned int getZonesCount() const;
|
||||
unsigned int getZonesCount() const override;
|
||||
|
||||
virtual Zone getZone(unsigned int index) const;
|
||||
rect_t getZone(unsigned int index) const override;
|
||||
};
|
||||
|
||||
#endif // _TOPBAR_H_
|
||||
|
||||
@@ -239,6 +239,15 @@ void ViewMain::openMenu()
|
||||
void ViewMain::checkEvents()
|
||||
{
|
||||
Window::checkEvents();
|
||||
|
||||
// TODO attach elsewhere
|
||||
for (uint8_t i=0; i<MAX_CUSTOM_SCREENS; i++) {
|
||||
if (customScreens[i]) {
|
||||
if (i == g_model.view && !customScreens[i]->getParent()) {
|
||||
customScreens[i]->attach(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewMain::paint(BitmapBuffer * dc)
|
||||
@@ -250,15 +259,15 @@ void ViewMain::paint(BitmapBuffer * dc)
|
||||
if (g_model.view >= getMainViewsCount()) {
|
||||
g_model.view = 0;
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<MAX_CUSTOM_SCREENS; i++) {
|
||||
if (customScreens[i]) {
|
||||
if (i == g_model.view) {
|
||||
customScreens[i]->refresh(); }
|
||||
else
|
||||
customScreens[i]->background();
|
||||
}
|
||||
}
|
||||
//
|
||||
// for (uint8_t i=0; i<MAX_CUSTOM_SCREENS; i++) {
|
||||
// if (customScreens[i]) {
|
||||
// if (i == g_model.view) {
|
||||
// customScreens[i]->refresh(); }
|
||||
// else
|
||||
// customScreens[i]->background();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -43,11 +43,11 @@ const WidgetFactory * getWidgetFactory(const char * name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Widget * loadWidget(const char * name, const Zone & zone, Widget::PersistentData * persistentData)
|
||||
Widget * loadWidget(const char * name, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData)
|
||||
{
|
||||
const WidgetFactory * factory = getWidgetFactory(name);
|
||||
if (factory) {
|
||||
return factory->create(zone, persistentData, false);
|
||||
return factory->create(parent, rect, persistentData, false);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -34,23 +34,21 @@
|
||||
#endif
|
||||
|
||||
class WidgetFactory;
|
||||
class Widget
|
||||
class Widget : public Window
|
||||
{
|
||||
public:
|
||||
struct PersistentData {
|
||||
ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS] USE_IDX;
|
||||
};
|
||||
|
||||
Widget(const WidgetFactory * factory, const Zone & zone, PersistentData * persistentData):
|
||||
Widget(const WidgetFactory * factory, Window * parent, const rect_t & rect, PersistentData * persistentData):
|
||||
Window(parent, rect),
|
||||
factory(factory),
|
||||
zone(zone),
|
||||
persistentData(persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Widget()
|
||||
{
|
||||
}
|
||||
~Widget() override = default;
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
@@ -73,15 +71,12 @@ class Widget
|
||||
return &persistentData->options[index].value;
|
||||
}
|
||||
|
||||
virtual void refresh() = 0;
|
||||
|
||||
virtual void background()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
const WidgetFactory * factory;
|
||||
Zone zone;
|
||||
PersistentData * persistentData;
|
||||
};
|
||||
|
||||
@@ -90,7 +85,7 @@ void registerWidget(const WidgetFactory * factory);
|
||||
class WidgetFactory
|
||||
{
|
||||
public:
|
||||
WidgetFactory(const char * name, const ZoneOption * options=nullptr):
|
||||
explicit WidgetFactory(const char * name, const ZoneOption * options = nullptr):
|
||||
name(name),
|
||||
options(options)
|
||||
{
|
||||
@@ -121,7 +116,7 @@ class WidgetFactory
|
||||
}
|
||||
}
|
||||
|
||||
virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const = 0;
|
||||
virtual Widget * create(Window * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const = 0;
|
||||
|
||||
protected:
|
||||
const char * name;
|
||||
@@ -137,13 +132,13 @@ class BaseWidgetFactory: public WidgetFactory
|
||||
{
|
||||
}
|
||||
|
||||
virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const
|
||||
Widget * create(Window * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const override
|
||||
{
|
||||
if (init) {
|
||||
initPersistentData(persistentData);
|
||||
}
|
||||
|
||||
return new T(this, zone, persistentData);
|
||||
return new T(this, parent, rect, persistentData);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -152,7 +147,7 @@ inline const ZoneOption * Widget::getOptions() const
|
||||
return getFactory()->getOptions();
|
||||
}
|
||||
|
||||
Widget * loadWidget(const char * name, const Zone & zone, Widget::PersistentData * persistentData);
|
||||
Widget * loadWidget(const char * name, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData);
|
||||
|
||||
std::list<const WidgetFactory *> & getRegisteredWidgets();
|
||||
|
||||
|
||||
@@ -20,17 +20,40 @@
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
#define TEXT_WIDGET_DEFAULT_LABEL '\15', '\347', '\0', '\14', '\377', '\376', '\373', '\364' // "My Label"
|
||||
#define TEXT_WIDGET_DEFAULT_LABEL 'M', 'y', ' ', 'L', 'a', 'b', 'e', 'l' // "My Label"
|
||||
|
||||
class TextWidget: public Widget
|
||||
{
|
||||
public:
|
||||
TextWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData)
|
||||
TextWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData):
|
||||
Widget(factory, parent, rect, persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
void refresh() override;
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// TODO DELETE THOSE TEST INIT VALUE !!
|
||||
strcpy(persistentData->options[0].value.stringValue, "This is a test string");
|
||||
persistentData->options[3].value.boolValue = true; // shadow
|
||||
// TODO END TEST INIT VALUE
|
||||
|
||||
// clear the background
|
||||
dc->clear(DEFAULT_BGCOLOR);
|
||||
|
||||
// get font color from options[1]
|
||||
lcdSetColor(persistentData->options[1].value.unsignedValue);
|
||||
|
||||
// get font size from options[2]
|
||||
LcdFlags fontsize = persistentData->options[2].value.unsignedValue << 8u;
|
||||
|
||||
// draw shadow
|
||||
if (persistentData->options[3].value.boolValue) {
|
||||
dc->drawText(1, 1, persistentData->options[0].value.stringValue, fontsize | BLACK);
|
||||
}
|
||||
|
||||
// draw text
|
||||
dc->drawText(0, 0, persistentData->options[0].value.stringValue, fontsize | CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
static const ZoneOption options[];
|
||||
};
|
||||
@@ -43,20 +66,4 @@ const ZoneOption TextWidget::options[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
void TextWidget::refresh()
|
||||
{
|
||||
lcdSetColor(persistentData->options[1].value.unsignedValue);
|
||||
LcdFlags fontsize = FONTSIZE(persistentData->options[2].value.unsignedValue << 8);
|
||||
if(persistentData->options[3].value.boolValue) {
|
||||
lcdDrawSizedText(zone.x+1, zone.y+1,
|
||||
persistentData->options[0].value.stringValue,
|
||||
sizeof(persistentData->options[0].value.stringValue),
|
||||
ZCHAR|fontsize|BLACK);
|
||||
}
|
||||
lcdDrawSizedText(zone.x, zone.y,
|
||||
persistentData->options[0].value.stringValue,
|
||||
sizeof(persistentData->options[0].value.stringValue),
|
||||
ZCHAR|fontsize|CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
BaseWidgetFactory<TextWidget> textWidget("Text", TextWidget::options);
|
||||
|
||||
@@ -20,17 +20,111 @@
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
const coord_t NUMBERS_PADDING = 4;
|
||||
|
||||
class ValueWidget: public Widget
|
||||
{
|
||||
public:
|
||||
ValueWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData)
|
||||
ValueWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData):
|
||||
Widget(factory, parent, rect, persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
void refresh() override;
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// TODO DELETE THOSE TEST INIT VALUE !!
|
||||
persistentData->options[0].value.unsignedValue = 1;
|
||||
// TODO END TEST INIT VALUE
|
||||
|
||||
// draw the background and border
|
||||
dc->clear(DEFAULT_BGCOLOR);
|
||||
dc->drawFilledRect(0,0, width(), height(), SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
|
||||
// get source from options[0]
|
||||
mixsrc_t field = persistentData->options[0].value.unsignedValue;
|
||||
|
||||
// get color from options[1]
|
||||
lcdSetColor(persistentData->options[1].value.unsignedValue);
|
||||
|
||||
coord_t xValue, yValue, xLabel, yLabel;
|
||||
LcdFlags attrValue, attrLabel = 0;
|
||||
|
||||
if (width() < 120 && height() < 50) {
|
||||
xValue = 0;
|
||||
yValue = 14;
|
||||
xLabel = 0;
|
||||
yLabel = 0;
|
||||
attrValue = LEFT | NO_UNIT | FONT(XS);
|
||||
attrLabel = FONT(XS);
|
||||
}
|
||||
else if (height() < 50) {
|
||||
xValue = width() - NUMBERS_PADDING;
|
||||
yValue = -2;
|
||||
xLabel = NUMBERS_PADDING;
|
||||
yLabel = +2;
|
||||
attrValue = RIGHT | NO_UNIT | FONT(XL);
|
||||
}
|
||||
else {
|
||||
xValue = NUMBERS_PADDING;
|
||||
yValue = 18;
|
||||
xLabel = NUMBERS_PADDING;
|
||||
yLabel = 2;
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
if (isGPSSensor(1 + (field - MIXSRC_FIRST_TELEM) / 3)) {
|
||||
attrValue = LEFT | FONT(L) | EXPANDED;
|
||||
}
|
||||
else {
|
||||
attrValue = LEFT | FONT(XL);
|
||||
}
|
||||
}
|
||||
#if defined(INTERNAL_GPS)
|
||||
else if (field == MIXSRC_TX_GPS) {
|
||||
attrValue = LEFT | FONT(L) | EXPANDED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
attrValue = LEFT | FONT(XL);
|
||||
}
|
||||
}
|
||||
|
||||
if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) {
|
||||
TimerState & timerState = timersStates[field - MIXSRC_FIRST_TIMER];
|
||||
if (timerState.val < 0) {
|
||||
lcdSetColor(lcdColorTable[ALARM_COLOR_INDEX]);
|
||||
}
|
||||
drawSource(dc, NUMBERS_PADDING, 2, field, CUSTOM_COLOR);
|
||||
drawSource(dc, NUMBERS_PADDING + 1, 3, field, BLACK);
|
||||
drawTimer(dc, xValue, yValue, abs(timerState.val), attrValue | FONT(XL) | CUSTOM_COLOR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
TelemetryItem & telemetryItem = telemetryItems[(field - MIXSRC_FIRST_TELEM) / 3]; // TODO macro to convert a source to a telemetry index
|
||||
if (!telemetryItem.isAvailable() || telemetryItem.isOld()) {
|
||||
lcdSetColor(lcdColorTable[TEXT_DISABLE_COLOR_INDEX]);
|
||||
}
|
||||
}
|
||||
|
||||
if (persistentData->options[2].value.boolValue) {
|
||||
drawSource(dc,xLabel + 1, yLabel + 1, field, attrLabel | BLACK);
|
||||
drawSourceValue(dc, xValue + 1, yValue + 1, field, attrValue | BLACK);
|
||||
}
|
||||
|
||||
drawSource(dc, xLabel, yLabel, field, attrLabel | CUSTOM_COLOR);
|
||||
drawSourceValue(dc, xValue, yValue, field, attrValue | CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
auto newValue = getValue(persistentData->options[0].value.unsignedValue);
|
||||
if (lastValue != newValue) {
|
||||
lastValue = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
static const ZoneOption options[];
|
||||
int32_t lastValue = 0;
|
||||
};
|
||||
|
||||
const ZoneOption ValueWidget::options[] = {
|
||||
@@ -40,85 +134,4 @@ const ZoneOption ValueWidget::options[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
void ValueWidget::refresh()
|
||||
{
|
||||
const int NUMBERS_PADDING = 4;
|
||||
|
||||
mixsrc_t field = persistentData->options[0].value.unsignedValue;
|
||||
lcdSetColor(persistentData->options[1].value.unsignedValue);
|
||||
|
||||
int x = zone.x;
|
||||
int y = zone.y;
|
||||
|
||||
// TRACE("w=%d, h=%d", zone.w, zone.h);
|
||||
|
||||
// lcdDrawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
|
||||
int xValue, yValue, xLabel, yLabel;
|
||||
LcdFlags attrValue, attrLabel=0;
|
||||
if (zone.w < 120 && zone.h < 50) {
|
||||
xValue = x;
|
||||
yValue = y+14;
|
||||
xLabel = x;
|
||||
yLabel = y;
|
||||
attrValue = LEFT | NO_UNIT | MIDSIZE;
|
||||
attrLabel = FONT(XS);
|
||||
}
|
||||
else if (zone.h < 50) {
|
||||
xValue = x+zone.w-NUMBERS_PADDING;
|
||||
yValue = y-2;
|
||||
xLabel = x+NUMBERS_PADDING;
|
||||
yLabel = y+2;
|
||||
attrValue = RIGHT | NO_UNIT | FONT(XL);
|
||||
}
|
||||
else {
|
||||
xValue = x+NUMBERS_PADDING;
|
||||
yValue = y+18;
|
||||
xLabel = x+NUMBERS_PADDING;
|
||||
yLabel = y+2;
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
if (isGPSSensor(1+(field-MIXSRC_FIRST_TELEM)/3)) {
|
||||
attrValue = LEFT | MIDSIZE | EXPANDED;
|
||||
}
|
||||
else {
|
||||
attrValue = LEFT | FONT(XL);
|
||||
}
|
||||
}
|
||||
#if defined(INTERNAL_GPS)
|
||||
else if (field == MIXSRC_TX_GPS) {
|
||||
attrValue = LEFT | MIDSIZE | EXPANDED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
attrValue = LEFT | FONT(XL);
|
||||
}
|
||||
}
|
||||
|
||||
if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) {
|
||||
TimerState & timerState = timersStates[field-MIXSRC_FIRST_TIMER];
|
||||
if (timerState.val < 0) {
|
||||
lcdSetColor(lcdColorTable[ALARM_COLOR_INDEX]);
|
||||
}
|
||||
drawSource(x+NUMBERS_PADDING, y+2, field, CUSTOM_COLOR);
|
||||
drawSource(x+NUMBERS_PADDING + 1, y + 3, field, BLACK);
|
||||
drawTimer(xValue, yValue, abs(timerState.val), attrValue|FONT(XL)|CUSTOM_COLOR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index
|
||||
if (!telemetryItem.isAvailable() || telemetryItem.isOld()) {
|
||||
lcdSetColor(lcdColorTable[TEXT_DISABLE_COLOR_INDEX]);
|
||||
}
|
||||
}
|
||||
|
||||
if(persistentData->options[2].value.boolValue) {
|
||||
drawSource(xLabel + 1, yLabel + 1, field, attrLabel|BLACK);
|
||||
drawSourceValue(xValue + 1, yValue + 1, field, attrValue|BLACK);
|
||||
}
|
||||
drawSource(xLabel, yLabel, field, attrLabel|CUSTOM_COLOR);
|
||||
drawSourceValue(xValue, yValue, field, attrValue|CUSTOM_COLOR);
|
||||
|
||||
}
|
||||
|
||||
BaseWidgetFactory<ValueWidget> ValueWidget("Value", ValueWidget::options);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define _WIDGETS_CONTAINER_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <window.h>
|
||||
#include "widget.h"
|
||||
|
||||
class WidgetsContainerInterface
|
||||
@@ -29,7 +30,7 @@ class WidgetsContainerInterface
|
||||
public:
|
||||
virtual unsigned int getZonesCount() const = 0;
|
||||
|
||||
virtual Zone getZone(unsigned int index) const = 0;
|
||||
virtual rect_t getZone(unsigned int index) const = 0;
|
||||
|
||||
inline Widget * getWidget(unsigned int index)
|
||||
{
|
||||
@@ -50,7 +51,7 @@ class WidgetsContainerInterface
|
||||
#define WIDGET_NAME_LEN 10
|
||||
|
||||
template<int N, int O>
|
||||
class WidgetsContainer: public WidgetsContainerInterface
|
||||
class WidgetsContainer: public Window, public WidgetsContainerInterface
|
||||
{
|
||||
public:
|
||||
struct ZonePersistentData {
|
||||
@@ -63,21 +64,10 @@ class WidgetsContainer: public WidgetsContainerInterface
|
||||
ZoneOptionValueTyped options[O];
|
||||
};
|
||||
|
||||
public:
|
||||
WidgetsContainer(PersistentData * persistentData):
|
||||
WidgetsContainer(const rect_t & rect, PersistentData * persistentData):
|
||||
Window(nullptr, rect),
|
||||
persistentData(persistentData)
|
||||
{
|
||||
widgets = (Widget **)calloc(N, sizeof(Widget *));
|
||||
}
|
||||
|
||||
virtual ~WidgetsContainer()
|
||||
{
|
||||
if (widgets) {
|
||||
for (uint8_t i=0; i<N; i++) {
|
||||
delete widgets[i];
|
||||
}
|
||||
free(widgets);
|
||||
}
|
||||
}
|
||||
|
||||
void createWidget(unsigned int index, const WidgetFactory * factory) override
|
||||
@@ -86,7 +76,7 @@ class WidgetsContainer: public WidgetsContainerInterface
|
||||
memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName));
|
||||
if (factory) {
|
||||
strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(persistentData->zones[index].widgetName));
|
||||
widgets[index] = factory->create(getZone(index), &persistentData->zones[index].widgetData);
|
||||
widgets[index] = factory->create(this, getZone(index), &persistentData->zones[index].widgetData);
|
||||
}
|
||||
else {
|
||||
widgets[index] = nullptr;
|
||||
@@ -103,13 +93,20 @@ class WidgetsContainer: public WidgetsContainerInterface
|
||||
{
|
||||
if (widgets) {
|
||||
unsigned int count = getZonesCount();
|
||||
for (unsigned int i=0; i<count; i++) {
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
delete widgets[i];
|
||||
if (persistentData->zones[i].widgetName[0]) {
|
||||
if (i == 0) {
|
||||
char name[WIDGET_NAME_LEN + 1] = "Text";
|
||||
widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData);
|
||||
} else if (i == 1) {
|
||||
char name[WIDGET_NAME_LEN + 1] = "Value";
|
||||
widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData);
|
||||
}
|
||||
else if (persistentData->zones[i].widgetName[0]) {
|
||||
char name[WIDGET_NAME_LEN + 1];
|
||||
memset(name, 0, sizeof(name));
|
||||
strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN);
|
||||
// widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData);
|
||||
// TODO widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData);
|
||||
}
|
||||
else {
|
||||
widgets[i] = nullptr;
|
||||
@@ -125,23 +122,12 @@ class WidgetsContainer: public WidgetsContainerInterface
|
||||
|
||||
unsigned int getZonesCount() const override = 0;
|
||||
|
||||
Zone getZone(unsigned int index) const override = 0;
|
||||
|
||||
virtual void refresh()
|
||||
{
|
||||
if (widgets) {
|
||||
for (int i=0; i<N; i++) {
|
||||
if (widgets[i]) {
|
||||
widgets[i]->refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rect_t getZone(unsigned int index) const override = 0;
|
||||
|
||||
virtual void background()
|
||||
{
|
||||
if (widgets) {
|
||||
for (int i=0; i<N; i++) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (widgets[i]) {
|
||||
widgets[i]->background();
|
||||
}
|
||||
@@ -151,6 +137,7 @@ class WidgetsContainer: public WidgetsContainerInterface
|
||||
|
||||
protected:
|
||||
PersistentData * persistentData;
|
||||
Widget * widgets[N] = {};
|
||||
};
|
||||
|
||||
#endif // _WIDGETS_CONTAINER_H_
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
#define OPTION_VALUE_STRING(...) { .stringValue = { __VA_ARGS__ } }
|
||||
#endif
|
||||
|
||||
struct Zone
|
||||
{
|
||||
uint16_t x, y, w, h;
|
||||
};
|
||||
|
||||
union ZoneOptionValue
|
||||
{
|
||||
uint32_t unsignedValue;
|
||||
|
||||
@@ -183,7 +183,7 @@ void postModelLoad(bool alarms)
|
||||
referenceModelAudioFiles();
|
||||
#endif
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#if defined(COLORLCD)
|
||||
loadCustomScreens();
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user