Merge pull request #193 from EdgeTX/theme-facelift

Default Theme facelift
This commit is contained in:
Raphael Coeffic
2021-06-14 19:50:09 +02:00
committed by GitHub
46 changed files with 2183 additions and 1613 deletions
+50 -27
View File
@@ -58,18 +58,30 @@ class MixerChannelBar : public ChannelBar
chanVal = limit<int>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
// Draw Background
dc->drawSolidFilledRect(0, 0, width(), height(), BARGRAPH_BGCOLOR);
dc->drawSolidFilledRect(0, 0, width(), height(), FIELD_BGCOLOR);
// Draw mixer bar
if (chanVal > 0) {
dc->drawSolidFilledRect(0 + width() / 2, 0, divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), height(), BARGRAPH2_COLOR);
dc->drawNumber(width() / 2 - 10, 0, displayVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
}
else if (chanVal < 0) {
dc->drawSolidFilledRect(
0 + width() / 2, 0,
divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2),
height(), FOCUS_BGCOLOR);
dc->drawNumber(width() / 2 - 10, 0, displayVal,
FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
} else if (chanVal < 0) {
const unsigned endpoint = width() / 2;
const unsigned size = divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2);
dc->drawSolidFilledRect(endpoint - size, 0, size, height(), BARGRAPH2_COLOR);
dc->drawNumber(10 + width() / 2, 0, displayVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
const unsigned size =
divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2);
dc->drawSolidFilledRect(endpoint - size, 0, size, height(),
FOCUS_BGCOLOR);
dc->drawNumber(10 + width() / 2, 0, displayVal,
FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
}
// Draw middle bar
@@ -100,36 +112,47 @@ class OutputChannelBar : public ChannelBar
int chanVal = calcRESXto100(channelOutputs[channel]);
int displayVal = chanVal;
chanVal = limit<int>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
chanVal = limit<int>(-VIEW_CHANNELS_LIMIT_PCT, chanVal,
VIEW_CHANNELS_LIMIT_PCT);
// Draw Background
dc->drawSolidFilledRect(0, 0, width(), height(), BARGRAPH_BGCOLOR);
dc->drawSolidFilledRect(0, 0, width(), height(), FIELD_BGCOLOR);
// Draw output bar
if (chanVal > 0) {
dc->drawSolidFilledRect(width() / 2, 0, divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), height(), BARGRAPH1_COLOR);
dc->drawNumber(width() / 2 - 10, 0, displayVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
}
else if (chanVal < 0) {
dc->drawSolidFilledRect(
width() / 2, 0,
divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2),
height(), HIGHLIGHT_COLOR);
dc->drawNumber(width() / 2 - 10, 0, displayVal,
FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
} else if (chanVal < 0) {
unsigned endpoint = width() / 2;
unsigned size = divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2);
dc->drawSolidFilledRect(endpoint - size, 0, size, height(), BARGRAPH1_COLOR);
dc->drawNumber(width() / 2 + 10, 0, displayVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
unsigned size =
divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2);
dc->drawSolidFilledRect(endpoint - size, 0, size, height(),
HIGHLIGHT_COLOR);
dc->drawNumber(width() / 2 + 10, 0, displayVal,
FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
}
// Draw middle bar
dc->drawSolidVerticalLine(width() / 2, 0, height(), DEFAULT_COLOR);
// Draw output limits bars
LimitData * ld = limitAddress(channel);
LimitData* ld = limitAddress(channel);
if (ld && ld->revert) {
drawOutputBarLimits(dc, posOnBar(-100 - ld->max / 10), posOnBar(100 - ld->min / 10));
//lcd->drawBitmap(x - X_OFFSET + 7, y + 25, chanMonInvertedBitmap);
drawOutputBarLimits(dc, posOnBar(-100 - ld->max / 10),
posOnBar(100 - ld->min / 10));
} else if (ld) {
drawOutputBarLimits(dc, posOnBar(-100 + ld->min / 10),
posOnBar(100 + ld->max / 10));
}
else if (ld) {
drawOutputBarLimits(dc, posOnBar(-100 + ld->min / 10), posOnBar(100 + ld->max / 10));
}
}
inline unsigned posOnBar(int value_to100)
@@ -193,13 +216,13 @@ class ComboChannelBar : public ChannelBar
// Override icon
#if defined(OVERRIDE_CHANNEL_FUNCTION)
if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED)
dc->drawBitmap(0, 1, chanMonLockedBitmap);
dc->drawMask(0, 1, chanMonLockedBitmap, DEFAULT_COLOR);
#endif
// Channel reverted icon
LimitData * ld = limitAddress(channel);
if (ld && ld->revert) {
lcd->drawBitmap(0, 20, chanMonInvertedBitmap);
lcd->drawMask(0, 20, chanMonInvertedBitmap, DEFAULT_COLOR);
}
}
@@ -215,4 +238,4 @@ class ComboChannelBar : public ChannelBar
protected:
int value = 0;
};
};
+45 -34
View File
@@ -27,50 +27,58 @@
// TODO common code, not in target
enum LcdColorIndex
{
DEFAULT_COLOR_INDEX,
DEFAULT_BGCOLOR_INDEX,
FOCUS_COLOR_INDEX,
FOCUS_BGCOLOR_INDEX,
TEXT_STATUSBAR_COLOR_INDEX,
LINE_COLOR_INDEX,
MENU_LINE_COLOR_INDEX = LINE_COLOR_INDEX,
CHECKBOX_COLOR_INDEX,
SCROLLBAR_COLOR_INDEX,
MENU_BGCOLOR_INDEX,
MENU_HIGHLIGHT_BGCOLOR_INDEX /*= MENU_BGCOLOR_INDEX*/,
MENU_COLOR_INDEX,
MENU_TITLE_DISABLE_COLOR_INDEX,
HEADER_COLOR_INDEX,
ALARM_COLOR_INDEX,
HIGHLIGHT_COLOR_INDEX,
MENU_HIGHLIGHT_COLOR_INDEX = HIGHLIGHT_COLOR_INDEX,
TEXT_DISABLE_COLOR_INDEX,
DISABLE_COLOR_INDEX,
CURVE_COLOR_INDEX,
CURVE_AXIS_COLOR_INDEX,
CURVE_CURSOR_COLOR_INDEX,
HEADER_BGCOLOR_INDEX,
HEADER_ICON_BGCOLOR_INDEX,
HEADER_CURRENT_BGCOLOR_INDEX,
TITLE_BGCOLOR_INDEX,
TRIM_BGCOLOR_INDEX,
TRIM_SHADOW_COLOR_INDEX,
MAINVIEW_PANES_COLOR_INDEX,
MAINVIEW_GRAPHICS_COLOR_INDEX,
OVERLAY_COLOR_INDEX,
CUSTOM_COLOR_INDEX,
BARGRAPH1_COLOR_INDEX,
BARGRAPH2_COLOR_INDEX,
BARGRAPH_BGCOLOR_INDEX,
SCROLLBOX_COLOR_INDEX,
TABLE_HEADER_BGCOLOR_INDEX,
TABLE_BGCOLOR_INDEX,
BATTERY_CHARGE_COLOR_INDEX,
CHECKBOX_COLOR_INDEX,
CURVE_AXIS_COLOR_INDEX,
CURVE_COLOR_INDEX,
CURVE_CURSOR_COLOR_INDEX,
CUSTOM_COLOR_INDEX,
DEFAULT_BGCOLOR_INDEX,
DEFAULT_COLOR_INDEX,
DISABLE_COLOR_INDEX,
EDIT_MARKER_COLOR_INDEX,
FIELD_BGCOLOR_INDEX,
FIELD_FRAME_COLOR_INDEX,
FOCUS_BGCOLOR_INDEX,
FOCUS_COLOR_INDEX,
HEADER_BGCOLOR_INDEX,
HEADER_COLOR_INDEX,
HEADER_CURRENT_BGCOLOR_INDEX,
HEADER_ICON_BGCOLOR_INDEX,
HIGHLIGHT_COLOR_INDEX,
LINE_COLOR_INDEX,
MENU_HIGHLIGHT_BGCOLOR_INDEX,
MAINVIEW_GRAPHICS_COLOR_INDEX,
MAINVIEW_PANES_COLOR_INDEX,
MENU_BGCOLOR_INDEX,
MENU_COLOR_INDEX,
MENU_HIGHLIGHT_COLOR_INDEX,
MENU_LINE_COLOR_INDEX,
MENU_TITLE_DISABLE_COLOR_INDEX,
OVERLAY_COLOR_INDEX,
SCROLLBAR_COLOR_INDEX,
SCROLLBOX_COLOR_INDEX,
TABLE_BGCOLOR_INDEX,
TABLE_HEADER_BGCOLOR_INDEX,
TEXT_DISABLE_COLOR_INDEX,
TEXT_STATUSBAR_COLOR_INDEX,
TITLE_BGCOLOR_INDEX,
TRIM_BGCOLOR_INDEX,
TRIM_SHADOW_COLOR_INDEX,
// this one MUST be last
LCD_COLOR_COUNT,
};
//#define MENU_HIGHLIGHT_COLOR_INDEX HIGHLIGHT_COLOR_INDEX
//#define MENU_LINE_COLOR_INDEX LINE_COLOR_INDEX
//
// Basic color definitions
//
@@ -116,6 +124,9 @@ inline void lcdSetColor(uint16_t color)
#define DEFAULT_BGCOLOR COLOR(DEFAULT_BGCOLOR_INDEX)
#define DEFAULT_COLOR COLOR(DEFAULT_COLOR_INDEX)
#define DISABLE_COLOR COLOR(DISABLE_COLOR_INDEX)
#define EDIT_MARKER_COLOR COLOR(EDIT_MARKER_COLOR_INDEX)
#define FIELD_BGCOLOR COLOR(FIELD_BGCOLOR_INDEX)
#define FIELD_FRAME_COLOR COLOR(FIELD_FRAME_COLOR_INDEX)
#define FOCUS_BGCOLOR COLOR(FOCUS_BGCOLOR_INDEX)
#define FOCUS_COLOR COLOR(FOCUS_COLOR_INDEX)
#define HEADER_BGCOLOR COLOR(HEADER_BGCOLOR_INDEX)
+14 -15
View File
@@ -27,21 +27,20 @@
void Curve::drawBackground(BitmapBuffer * dc)
{
lcdSetColor(RGB(0xE0, 0xE0, 0xE0));
dc->clear(CUSTOM_COLOR);
dc->clear(FIELD_BGCOLOR);
// Axis
dc->drawSolidHorizontalLine(0, height()/2, width(), DISABLE_COLOR);
dc->drawSolidVerticalLine(width()/2, 0, height(), DISABLE_COLOR);
dc->drawSolidHorizontalLine(0, height()/2, width(), FIELD_FRAME_COLOR);
dc->drawSolidVerticalLine(width()/2, 0, height(), FIELD_FRAME_COLOR);
// Extra lines
dc->drawVerticalLine(width()/4, 0, height(), STASHED, DISABLE_COLOR);
dc->drawVerticalLine(width()*3/4, 0, height(), STASHED, DISABLE_COLOR);
dc->drawHorizontalLine(0, height()/4, width(), STASHED, DISABLE_COLOR);
dc->drawHorizontalLine(0, height()*3/4, width(), STASHED, DISABLE_COLOR);
dc->drawVerticalLine(width()/4, 0, height(), STASHED, FIELD_FRAME_COLOR);
dc->drawVerticalLine(width()*3/4, 0, height(), STASHED, FIELD_FRAME_COLOR);
dc->drawHorizontalLine(0, height()/4, width(), STASHED, FIELD_FRAME_COLOR);
dc->drawHorizontalLine(0, height()*3/4, width(), STASHED, FIELD_FRAME_COLOR);
// Outside border
// dc->drawSolidRect(0, 0, width(), height(), 1, DEFAULT_COLOR);
dc->drawSolidRect(0, 0, width(), height(), 1, FIELD_FRAME_COLOR);
}
coord_t Curve::getPointX(int x) const
@@ -89,17 +88,17 @@ void Curve::drawPosition(BitmapBuffer * dc)
coord_t y = getPointY(valueY);
// the 2 lines
dc->drawSolidHorizontalLine(0, y, width(), CURVE_CURSOR_COLOR);
dc->drawSolidVerticalLine(x, 0, height(), CURVE_CURSOR_COLOR);
dc->drawSolidHorizontalLine(0, y, width(), HIGHLIGHT_COLOR);
dc->drawSolidVerticalLine(x, 0, height(), HIGHLIGHT_COLOR);
// the point (white inside)
dc->drawBitmapPattern(x-4, y-4, LBM_CURVE_POINT, CURVE_CURSOR_COLOR);
dc->drawBitmapPattern(x-4, y-4, LBM_CURVE_POINT_CENTER, DEFAULT_BGCOLOR);
dc->drawBitmapPattern(x-4, y-4, LBM_CURVE_POINT, HIGHLIGHT_COLOR);
dc->drawBitmapPattern(x-4, y-4, LBM_CURVE_POINT_CENTER, FOCUS_COLOR);
char coords[16];
strAppendSigned(strAppend(strAppendSigned(coords, calcRESXto100(valueX)), ","), calcRESXto100(valueY));
dc->drawSolidFilledRect(10, 11, 1 + getTextWidth(coords, 0, FONT(XS)), 17, CURVE_CURSOR_COLOR);
dc->drawText(11, 10, coords, FONT(XS)|DEFAULT_BGCOLOR);
dc->drawSolidFilledRect(10, 11, 1 + getTextWidth(coords, 0, FONT(XS)), 17, HIGHLIGHT_COLOR);
dc->drawText(11, 10, coords, FONT(XS) | FOCUS_COLOR);
}
void Curve::drawPoint(BitmapBuffer * dc, const CurvePoint & point)
+71 -46
View File
@@ -42,48 +42,73 @@ void CurveDataEdit::update()
grid.setMarginRight(parent->width() - rect.w + 5);
coord_t boxWidth = rect.w / 5;
coord_t boxHeight = (rect.h - 6) / 3;
coord_t boxHeight = PAGE_LINE_HEIGHT;
CurveHeader & curve = g_model.curves[index];
uint8_t curvePointsCount = 5 + curve.points;
// Point number
for (uint8_t i = 0; i < curvePointsCount; i++) {
new StaticText(this, {i * boxWidth, 10, boxWidth, boxHeight}, std::to_string(i + 1), 0, RIGHT | TEXT_DISABLE_COLOR);
auto txt = new StaticText(
this,
{i * boxWidth + PAGE_PADDING, 10, boxWidth - PAGE_PADDING, boxHeight},
std::to_string(i + 1) + " ", 0, RIGHT | DEFAULT_COLOR);
txt->setBackgroundColor(FIELD_FRAME_COLOR);
}
grid.spacer(rect.h / 3);
grid.spacer(boxHeight + 10 + PAGE_PADDING);
// x value
if (curve.type == CURVE_TYPE_CUSTOM) {
// Adjustable points for custom curves
for (uint8_t i = 0; i < curvePointsCount; i++) {
int8_t * points = curveAddress(index);
auto pointEdit = new NumberEdit(this, {coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth), 10 + boxHeight, coord_t(boxWidth - PAGE_LINE_SPACING), boxHeight - 12},
i <= 1 ? -100 : points[curvePointsCount + i - 2],
i >= curvePointsCount - 2 ? 100 : points[curvePointsCount + i],
GET_VALUE(i == 0 ? -100 : i == curvePointsCount - 1 ? 100 : points[curvePointsCount + i - 1]),
[=](int32_t newValue) {
points[curvePointsCount + i - 1] = newValue;
SET_DIRTY();
curveEdit->updatePreview();
}, 0, RIGHT);
int8_t* points = curveAddress(index);
auto pointEdit = new NumberEdit(
this,
{coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth),
grid.getWindowHeight(), coord_t(boxWidth - PAGE_LINE_SPACING),
boxHeight},
i <= 1 ? -100 : points[curvePointsCount + i - 2],
i >= curvePointsCount - 2 ? 100 : points[curvePointsCount + i],
GET_VALUE(i == 0 ? -100
: i == curvePointsCount - 1
? 100
: points[curvePointsCount + i - 1]),
[=](int32_t newValue) {
points[curvePointsCount + i - 1] = newValue;
SET_DIRTY();
curveEdit->updatePreview();
},
0, RIGHT);
if (i == 0 || i == curvePointsCount - 1) {
pointEdit->disable();
}
}
}
else {
} else {
for (uint8_t i = 0; i < curvePointsCount; i++) {
new StaticText(this, {i * boxWidth, 10 + boxHeight, boxWidth, boxHeight}, std::to_string(-100 + 200 * i / (5 + curve.points - 1)), 0, RIGHT | TEXT_DISABLE_COLOR);
new StaticText(this, {i * boxWidth, grid.getWindowHeight(), boxWidth, boxHeight},
std::to_string(-100 + 200 * i / (5 + curve.points - 1)), 0,
RIGHT | DEFAULT_COLOR);
}
}
grid.spacer(boxHeight + PAGE_PADDING);
// y value
for (uint8_t i = 0; i < curvePointsCount; i++) {
int8_t * points = curveAddress(index);
new NumberEdit(this, {coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth), 10 + 2 * boxHeight, coord_t(boxWidth - PAGE_LINE_SPACING), boxHeight - 12}, -100, 100,
GET_VALUE(points[i]), [=](int32_t newValue) { points[i] = newValue; SET_DIRTY(); curveEdit->updatePreview(); }, 0, RIGHT);
int8_t* points = curveAddress(index);
new NumberEdit(
this,
{coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth),
grid.getWindowHeight(),
coord_t(boxWidth - PAGE_LINE_SPACING),
boxHeight},
-100, 100, GET_VALUE(points[i]),
[=](int32_t newValue) {
points[i] = newValue;
SET_DIRTY();
curveEdit->updatePreview();
},
0, RIGHT);
}
setInnerWidth(curvePointsCount * boxWidth);
@@ -92,8 +117,8 @@ void CurveDataEdit::update()
void CurveDataEdit::paint(BitmapBuffer * dc)
{
dc->clear(DEFAULT_BGCOLOR);
dc->drawSolidHorizontalLine(0, rect.h / 3, getInnerWidth(), 0);
dc->drawSolidHorizontalLine(0, 2 * rect.h / 3, getInnerWidth(), 0);
// dc->drawSolidHorizontalLine(0, rect.h / 3, getInnerWidth(), 0);
// dc->drawSolidHorizontalLine(0, 2 * rect.h / 3, getInnerWidth(), 0);
drawHorizontalScrollbar(dc);
}
@@ -125,35 +150,35 @@ void CurveEdit::updatePreview()
invalidate();
}
#if defined(HARDWARE_TOUCH)
bool CurveEdit::onTouchEnd(coord_t x, coord_t y)
{
if (!hasFocus()) {
setFocus(SET_FOCUS_DEFAULT);
}
// #if defined(HARDWARE_TOUCH)
// bool CurveEdit::onTouchEnd(coord_t x, coord_t y)
// {
// if (!hasFocus()) {
// setFocus(SET_FOCUS_DEFAULT);
// }
CurveKeyboard::show(this, isCustomCurve());
// CurveKeyboard::show(this, isCustomCurve());
CurveHeader & curve = g_model.curves[index];
for (int i=0; i<5 + curve.points; i++) {
if (i != current) {
point_t point = getPoint(index, i);
if (abs(preview.getPointX(point.x) - x) <= 10 && abs(preview.getPointY(point.y) - y) <= 10) {
current = i;
updatePreview();
break;
}
}
}
// CurveHeader & curve = g_model.curves[index];
// for (int i=0; i<5 + curve.points; i++) {
// if (i != current) {
// point_t point = getPoint(index, i);
// if (abs(preview.getPointX(point.x) - x) <= 10 && abs(preview.getPointY(point.y) - y) <= 10) {
// current = i;
// updatePreview();
// break;
// }
// }
// }
return true;
}
// return true;
// }
void CurveEdit::onFocusLost()
{
CurveKeyboard::hide();
}
#endif
// void CurveEdit::onFocusLost()
// {
// CurveKeyboard::hide();
// }
// #endif
void CurveEdit::next()
{
+4 -5
View File
@@ -62,11 +62,10 @@ class CurveEdit: public FormField
void onEvent(event_t event) override;
#if defined(HARDWARE_TOUCH)
bool onTouchEnd(coord_t x, coord_t y) override;
void onFocusLost() override;
#endif
// #if defined(HARDWARE_TOUCH)
// bool onTouchEnd(coord_t x, coord_t y) override;
// void onFocusLost() override;
// #endif
protected:
Curve preview;
+22 -18
View File
@@ -85,25 +85,26 @@ void TopbarImpl::paint(BitmapBuffer * dc)
char str[10];
sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]);
dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, MENU_COLOR);
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE1, str, FONT(XS) | CENTERED| MENU_COLOR);
//dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, MENU_COLOR);
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE1, str, FONT(XS) | CENTERED| FOCUS_COLOR);
getTimerString(str, getValue(MIXSRC_TX_TIME));
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | MENU_COLOR);
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | FOCUS_COLOR);
#if defined(INTERNAL_GPS)
if (gpsData.fix) {
char s[10];
sprintf(s, "%d", gpsData.numSat);
dc->drawText(LCD_W-148, 4, s, FONT(XS) | CENTERED | MENU_COLOR);
dc->drawText(LCD_W-148, 4, s, FONT(XS) | CENTERED | FOCUS_COLOR);
}
dc->drawBitmapPattern(LCD_W-158, 22, LBM_TOPMENU_GPS, (gpsData.fix) ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR);
dc->drawBitmapPattern(LCD_W - 158, 22, LBM_TOPMENU_GPS,
(gpsData.fix) ? FOCUS_COLOR : MENU_TITLE_DISABLE_COLOR);
#endif
// USB icon
if (usbPlugged()) {
LcdFlags flags = MENU_COLOR;
LcdFlags flags = FOCUS_COLOR;
if (getSelectedUsbMode() == USB_UNSELECTED_MODE) {
flags = MENU_TITLE_DISABLE_COLOR;
}
@@ -112,7 +113,7 @@ void TopbarImpl::paint(BitmapBuffer * dc)
}
// Logs
else if (isFunctionActive(FUNCTION_LOGS) && BLINK_ON_PHASE) {
dc->drawBitmapPattern(LCD_W - 98, 6, LBM_DOT, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 98, 6, LBM_DOT, FOCUS_COLOR);
}
// RSSI
@@ -120,42 +121,45 @@ void TopbarImpl::paint(BitmapBuffer * dc)
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(LCD_W - 90 + i * 6, 38 - height, 4, height, TELEMETRY_RSSI() >= rssiBarsValue[i] ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR);
dc->drawSolidFilledRect(LCD_W - 90 + i * 6, 38 - height, 4, height,
TELEMETRY_RSSI() >= rssiBarsValue[i]
? FOCUS_COLOR
: MENU_TITLE_DISABLE_COLOR);
}
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) {
dc->drawBitmapPattern(LCD_W-94, 4, LBM_TOPMENU_ANTENNA, MENU_COLOR);
dc->drawBitmapPattern(LCD_W-94, 4, LBM_TOPMENU_ANTENNA, FOCUS_COLOR);
}
#endif
/* Audio volume */
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_SCALE, MENU_TITLE_DISABLE_COLOR);
if (requiredSpeakerVolume == 0 || g_eeGeneral.beepMode == e_mode_quiet)
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_0, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_0, FOCUS_COLOR);
else if (requiredSpeakerVolume < 7)
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_1, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_1, FOCUS_COLOR);
else if (requiredSpeakerVolume < 13)
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_2, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_2, FOCUS_COLOR);
else if (requiredSpeakerVolume < 19)
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_3, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_3, FOCUS_COLOR);
else
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_4, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_4, FOCUS_COLOR);
/* Tx battery */
uint8_t bars = GET_TXBATT_BARS(5);
#if defined(USB_CHARGER)
if (usbChargerLed()) {
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, FOCUS_COLOR);
}
else {
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, FOCUS_COLOR);
}
#else
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR);
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, FOCUS_COLOR);
#endif
for (unsigned int i = 0; i < 5; i++) {
dc->drawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_COLOR);
dc->drawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : FOCUS_COLOR);
}
#if 0
+27 -14
View File
@@ -44,19 +44,25 @@ void MainViewHorizontalTrim::paint(BitmapBuffer * dc)
}
// Trim line
lcdSetColor(GREY); // TODO add a color
dc->drawSolidFilledRect(TRIM_SQUARE_SIZE / 2, (height() - TRIM_LINE_WIDTH - 1) / 2, width() - TRIM_SQUARE_SIZE + 1, TRIM_LINE_WIDTH, CUSTOM_COLOR);
dc->drawSolidFilledRect(
TRIM_SQUARE_SIZE / 2, (height() - TRIM_LINE_WIDTH - 1) / 2,
width() - TRIM_SQUARE_SIZE + 1, TRIM_LINE_WIDTH, DEFAULT_COLOR);
// Trim square
coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin);
drawTrimSquare(dc, x, 0, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR);
coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value - trimMin),
trimMax - trimMin);
drawTrimSquare(dc, x, 0,
(value < TRIM_MIN || value > TRIM_MAX)
? HIGHLIGHT_COLOR /* TODO add a color */
: TRIM_BGCOLOR);
// Trim value / small lines on the square
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) {
// TODO DISPLAY_TRIMS_CHANGE
dc->drawNumber(x + (TRIM_SQUARE_SIZE + 1) / 2, 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED);
}
else {
dc->drawNumber(x + (TRIM_SQUARE_SIZE + 1) / 2, 3,
divRoundClosest(value * 100, trimMax),
FONT(XXS) | FOCUS_COLOR | CENTERED);
} else {
if (value >= 0) {
dc->drawSolidVerticalLine(x + 4, 3, 9, FOCUS_COLOR);
}
@@ -79,19 +85,26 @@ void MainViewVerticalTrim::paint(BitmapBuffer * dc)
}
// Trim line
lcdSetColor(GREY); // TODO add a color
dc->drawSolidFilledRect((width() - TRIM_LINE_WIDTH) / 2, TRIM_SQUARE_SIZE / 2, TRIM_LINE_WIDTH, height() - TRIM_SQUARE_SIZE + 1, CUSTOM_COLOR);
dc->drawSolidFilledRect((width() - TRIM_LINE_WIDTH) / 2, TRIM_SQUARE_SIZE / 2,
TRIM_LINE_WIDTH, height() - TRIM_SQUARE_SIZE + 1,
DEFAULT_COLOR);
// Trim square
coord_t y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin);
drawTrimSquare(dc, 0, y, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR);
coord_t y = height() - TRIM_SQUARE_SIZE -
divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value - trimMin),
trimMax - trimMin);
drawTrimSquare(dc, 0, y,
(value < TRIM_MIN || value > TRIM_MAX)
? HIGHLIGHT_COLOR /* TODO add a color */
: TRIM_BGCOLOR);
// Trim value / small lines on the square
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) {
// TODO DISPLAY_TRIMS_CHANGE
dc->drawNumber((TRIM_SQUARE_SIZE + 1) / 2, y + 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED);
}
else {
dc->drawNumber((TRIM_SQUARE_SIZE + 1) / 2, y + 3,
divRoundClosest(value * 100, trimMax),
FONT(XXS) | FOCUS_COLOR | CENTERED);
} else {
if (value >= 0) {
dc->drawSolidHorizontalLine(3, y + 4, 9, FOCUS_COLOR);
}
+34 -6
View File
@@ -42,10 +42,16 @@ class CurveEditWindow : public Page
void buildHeader(Window * window)
{
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUCURVE, 0, MENU_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_MENUCURVE, 0, FOCUS_COLOR);
char s[16];
strAppendStringWithIndex(s, STR_CV, index + 1);
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, s, 0, MENU_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
s, 0, FOCUS_COLOR);
}
#if LCD_W > LCD_H
@@ -226,8 +232,14 @@ class CurveButton : public Button {
void paint(BitmapBuffer * dc) override
{
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, FIELD_BGCOLOR);
// bounding rect
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
if (hasFocus()) {
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
} else {
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
}
// curve characteristics
if (isCurveUsed(index)) {
@@ -297,7 +309,9 @@ void ModelCurvesPage::build(FormWindow * window, int8_t focusIndex)
if (isCurveUsed(index)) {
// Curve label
new StaticText(window, grid.getLabelSlot(), getCurveString(1 + index), BUTTON_BACKGROUND, CENTERED);
auto txt =
new StaticText(window, grid.getLabelSlot(), getCurveString(1 + index),
BUTTON_BACKGROUND, CENTERED);
// Curve drawing
Button * button = new CurveButton(window, grid.getFieldSlot(), index);
@@ -319,16 +333,30 @@ void ModelCurvesPage::build(FormWindow * window, int8_t focusIndex)
});
return 0;
});
button->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
if (focusIndex == index) {
button->setFocus(SET_FOCUS_DEFAULT);
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
txt->invalidate();
}
txt->setHeight(button->height());
grid.spacer(button->height() + 5);
}
else {
} else {
auto button = new TextButton(window, grid.getLabelSlot(),
getCurveString(1 + index));
button->setPressHandler([=]() {
Menu *menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() {
+1 -1
View File
@@ -30,7 +30,7 @@ class ModelCurvesPage: public PageTab {
virtual void build(FormWindow * window) override
{
build(window, -1);
build(window, 0);
}
protected:
@@ -58,6 +58,9 @@ class FlightModeGroup: public FormGroup
if (index == getFlightMode()) {
dc->drawSolidFilledRect(0, 0, width(), height(), HIGHLIGHT_COLOR);
}
else {
dc->drawSolidFilledRect(0, 0, width(), height(), FIELD_BGCOLOR);
}
FormGroup::paint(dc);
}
+33 -13
View File
@@ -64,9 +64,18 @@ void GVarButton::paint(BitmapBuffer * dc)
currentFlightMode = getFlightMode();
gvarSum = 0;
dc->drawSolidFilledRect(0, 0, nameRectW, rect.h, CURVE_AXIS_COLOR);
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, getGVarString(gvarIdx), 0);
dc->drawSizedText(x, y, gvar->name, LEN_GVAR_NAME, 0);
LcdFlags bgColor = FIELD_BGCOLOR;
LcdFlags textColor = 0;
if (hasFocus()) {
bgColor = FOCUS_BGCOLOR;
textColor = FOCUS_COLOR;
}
dc->drawSolidFilledRect(0, 0, nameRectW, rect.h, bgColor);
dc->drawSolidFilledRect(nameRectW, 0, rect.w - nameRectW, rect.h, FIELD_BGCOLOR);
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, getGVarString(gvarIdx), textColor);
dc->drawSizedText(x, y, gvar->name, LEN_GVAR_NAME, textColor);
// values are right aligned
x += GVAR_NAME_SIZE;
@@ -91,7 +100,8 @@ void GVarButton::paint(BitmapBuffer * dc)
}
if (!bgFilled) {
dc->drawSolidFilledRect(startX, y, width() - startX, PAGE_LINE_HEIGHT, CURVE_AXIS_COLOR);
dc->drawSolidFilledRect(startX, y, width() - startX, PAGE_LINE_HEIGHT,
FIELD_FRAME_COLOR);
bgFilled = true;
}
@@ -116,7 +126,10 @@ void GVarButton::paint(BitmapBuffer * dc)
}
}
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? FOCUS_BGCOLOR : DISABLE_COLOR);
if (hasFocus())
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
else
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FIELD_FRAME_COLOR);
}
void GVarButton::drawFlightMode(BitmapBuffer * dc, coord_t x, coord_t y, int fm, LcdFlags attr)
@@ -131,17 +144,17 @@ void GVarRenderer::paint(BitmapBuffer * dc)
lastFlightMode = getFlightMode();
FlightModeData * fmData = &g_model.flightModeData[lastFlightMode];
lastGVar = fmData->gvars[index];
coord_t x = drawStringWithIndex(dc, 0, FIELD_PADDING_TOP, STR_GV, index + 1, MENU_COLOR, nullptr, "=");
coord_t x = drawStringWithIndex(dc, 0, FIELD_PADDING_TOP, STR_GV, index + 1,
FOCUS_COLOR, nullptr, "=");
if (lastGVar > GVAR_MAX) {
uint8_t fm = lastGVar - GVAR_MAX - 1;
if (fm >= lastFlightMode)
fm++;
char label[16];
getFlightModeString(label, fm + 1);
dc->drawSizedText(x, FIELD_PADDING_TOP, label, strlen(label), MENU_COLOR);
}
else {
drawGVarValue(dc, x, FIELD_PADDING_TOP, index, lastGVar, MENU_COLOR);
dc->drawSizedText(x, FIELD_PADDING_TOP, label, strlen(label), FOCUS_COLOR);
} else {
drawGVarValue(dc, x, FIELD_PADDING_TOP, index, lastGVar, FOCUS_COLOR);
}
}
@@ -167,8 +180,15 @@ bool GVarRenderer::isUpdated()
void GVarEditWindow::buildHeader(Window * window)
{
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_GLOBAL_VAR, 0, MENU_COLOR);
gVarInHeader = new GVarRenderer(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, index);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_GLOBAL_VAR, 0, FOCUS_COLOR);
gVarInHeader =
new GVarRenderer(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
index);
}
void GVarEditWindow::checkEvents()
@@ -357,4 +377,4 @@ void ModelGVarsPage::build(FormWindow * window)
grid.nextLine(button->height());
}
window->setInnerHeight(grid.getWindowHeight());
}
}
+188 -139
View File
@@ -91,94 +91,104 @@ void deleteExpo(uint8_t idx)
storageDirty(EE_MODEL);
}
class InputEditWindow: public Page
class InputEditWindow : public Page
{
public:
InputEditWindow(int8_t input, uint8_t index):
public:
InputEditWindow(int8_t input, uint8_t index) :
Page(ICON_MODEL_INPUTS),
input(input),
index(index),
preview(this, {INPUT_EDIT_CURVE_LEFT, INPUT_EDIT_CURVE_TOP, INPUT_EDIT_CURVE_WIDTH, INPUT_EDIT_CURVE_HEIGHT},
[=](int x) -> int {
ExpoData * line = expoAddress(index);
int16_t anas[MAX_INPUTS] = {0};
applyExpos(anas, e_perout_mode_inactive_flight_mode, line->srcRaw, x);
return anas[line->chn];
},
[=]() -> int {
return getValue(expoAddress(index)->srcRaw);
})
{
preview(
this,
{INPUT_EDIT_CURVE_LEFT, INPUT_EDIT_CURVE_TOP, INPUT_EDIT_CURVE_WIDTH,
INPUT_EDIT_CURVE_HEIGHT},
[=](int x) -> int {
ExpoData *line = expoAddress(index);
int16_t anas[MAX_INPUTS] = {0};
applyExpos(anas, e_perout_mode_inactive_flight_mode, line->srcRaw,
x);
return anas[line->chn];
},
[=]() -> int { return getValue(expoAddress(index)->srcRaw); })
{
#if LCD_W > LCD_H
body.setWidth(LCD_W - 170);
body.setWidth(LCD_W - preview.width() - PAGE_PADDING);
body.setLeft(preview.width() + PAGE_PADDING);
#else
body.setRect({0, INPUT_EDIT_CURVE_TOP + INPUT_EDIT_CURVE_HEIGHT, LCD_W, LCD_H - INPUT_EDIT_CURVE_TOP - INPUT_EDIT_CURVE_HEIGHT});
body.setRect({0, INPUT_EDIT_CURVE_TOP + INPUT_EDIT_CURVE_HEIGHT, LCD_W,
LCD_H - INPUT_EDIT_CURVE_TOP - INPUT_EDIT_CURVE_HEIGHT});
#endif
buildBody(&body);
buildHeader(&header);
}
buildBody(&body);
buildHeader(&header);
}
void deleteLater(bool detach = true, bool trash = true) override
{
if (_deleted)
return;
void deleteLater(bool detach = true, bool trash = true) override
{
if (_deleted) return;
preview.deleteLater(true, false);
preview.deleteLater(true, false);
Page::deleteLater(detach, trash);
}
Page::deleteLater(detach, trash);
}
protected:
uint8_t input;
uint8_t index;
Curve preview;
Choice * trimChoice = nullptr;
FormGroup * curveParamField = nullptr;
protected:
uint8_t input;
uint8_t index;
Curve preview;
Choice *trimChoice = nullptr;
FormGroup *curveParamField = nullptr;
void buildHeader(Window * window)
{
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUINPUTS, 0, MENU_COLOR);
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSourceString(MIXSRC_FIRST_INPUT + input), 0, MENU_COLOR);
}
void buildHeader(Window *window)
{
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_MENUINPUTS, 0, FOCUS_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
getSourceString(MIXSRC_FIRST_INPUT + input), 0, FOCUS_COLOR);
}
// TODO share this code with MIXER
void updateCurveParamField(ExpoData * line)
{
curveParamField->clear();
// TODO share this code with MIXER
void updateCurveParamField(ExpoData *line)
{
curveParamField->clear();
const rect_t rect = {0, 0, curveParamField->width(), curveParamField->height()};
const rect_t rect = {0, 0, curveParamField->width(),
curveParamField->height()};
switch (line->curve.type) {
case CURVE_REF_DIFF:
case CURVE_REF_EXPO:
{
GVarNumberEdit * edit = new GVarNumberEdit(curveParamField, rect, -100, 100, GET_SET_DEFAULT(line->curve.value));
edit->setSuffix("%");
break;
}
switch (line->curve.type) {
case CURVE_REF_DIFF:
case CURVE_REF_EXPO: {
GVarNumberEdit *edit =
new GVarNumberEdit(curveParamField, rect, -100, 100,
GET_SET_DEFAULT(line->curve.value));
edit->setSuffix("%");
break;
}
case CURVE_REF_FUNC:
new Choice(curveParamField, rect, STR_VCURVEFUNC, 0, CURVE_BASE - 1, GET_SET_DEFAULT(line->curve.value));
break;
case CURVE_REF_FUNC:
new Choice(curveParamField, rect, STR_VCURVEFUNC, 0, CURVE_BASE - 1,
GET_SET_DEFAULT(line->curve.value));
break;
case CURVE_REF_CUSTOM:
{
auto choice = new Choice(curveParamField, rect, -MAX_CURVES, MAX_CURVES, GET_SET_DEFAULT(line->curve.value));
choice->setTextHandler([](int value) {
return getCurveString(value);
});
break;
}
case CURVE_REF_CUSTOM: {
auto choice = new Choice(curveParamField, rect, -MAX_CURVES, MAX_CURVES,
GET_SET_DEFAULT(line->curve.value));
choice->setTextHandler([](int value) { return getCurveString(value); });
break;
}
}
}
void buildBody(FormWindow * window)
{
FormGridLayout grid;
grid.setLabelWidth(INPUT_EDIT_LABELS_WIDTH);
grid.spacer(PAGE_PADDING);
void buildBody(FormWindow *window)
{
FormGridLayout grid;
grid.setLabelWidth(INPUT_EDIT_LABELS_WIDTH);
grid.spacer(PAGE_PADDING);
ExpoData * line = expoAddress(index) ;
ExpoData *line = expoAddress(index);
#if LCD_W > LCD_H
grid.setMarginRight(180);
@@ -302,19 +312,23 @@ void CommonInputOrMixButton::checkEvents()
Button::checkEvents();
}
void CommonInputOrMixButton::drawFlightModes(BitmapBuffer *dc, FlightModesType value)
void CommonInputOrMixButton::drawFlightModes(BitmapBuffer *dc,
FlightModesType value,
LcdFlags textColor)
{
dc->drawMask(146, 2 + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupFlightmodeIcon, DEFAULT_COLOR);
dc->drawMask(146, 2 + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupFlightmodeIcon, textColor);
coord_t x = 166;
for (int i = 0; i < MAX_FLIGHT_MODES; i++) {
char s[] = " ";
s[0] = '0' + i;
if (value & (1 << i)) {
dc->drawText(x, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP + 2, s, FONT(XS) | TEXT_DISABLE_COLOR);
}
else {
dc->drawSolidFilledRect(x, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP + 2, 8, 3, CHECKBOX_COLOR);
dc->drawText(x, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP + 2, s, FONT(XS));
dc->drawText(x, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP + 2, s,
FONT(XS) | TEXT_DISABLE_COLOR);
} else {
dc->drawSolidFilledRect(x, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP + 2, 8, 3,
FOCUS_BGCOLOR);
dc->drawText(x, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP + 2, s, FONT(XS) | textColor);
}
x += 8;
}
@@ -322,56 +336,68 @@ void CommonInputOrMixButton::drawFlightModes(BitmapBuffer *dc, FlightModesType v
void CommonInputOrMixButton::paint(BitmapBuffer * dc)
{
if (active)
dc->drawSolidFilledRect(2, 2, rect.w - 4, rect.h - 4, HIGHLIGHT_COLOR);
dc->drawSolidFilledRect(0, 0, width(), height(),
/*hasFocus() ? FOCUS_BGCOLOR :*/ FIELD_BGCOLOR);
paintBody(dc);
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
if (!hasFocus())
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
else
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
}
class InputLineButton : public CommonInputOrMixButton {
public:
InputLineButton(FormGroup * parent, const rect_t & rect, uint8_t index):
class InputLineButton : public CommonInputOrMixButton
{
public:
InputLineButton(FormGroup *parent, const rect_t &rect, uint8_t index) :
CommonInputOrMixButton(parent, rect, index)
{
const ExpoData & line = g_model.expoData[index];
if (line.swtch || line.curve.value != 0 || line.flightModes) {
setHeight(height() + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP);
}
{
const ExpoData &line = g_model.expoData[index];
if (line.swtch || line.curve.value != 0 || line.flightModes) {
setHeight(height() + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP);
}
}
bool isActive() const override { return isExpoActive(index); }
void paintBody(BitmapBuffer *dc) override
{
const ExpoData &line = g_model.expoData[index];
LcdFlags textColor = DEFAULT_COLOR;
// if (hasFocus())
// textColor = FOCUS_COLOR;
// first line ...
drawValueOrGVar(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, line.weight,
-100, 100, textColor);
drawSource(dc, 60, FIELD_PADDING_TOP, line.srcRaw, textColor);
if (line.name[0]) {
dc->drawMask(146, FIELD_PADDING_TOP, mixerSetupLabelIcon, textColor);
dc->drawSizedText(166, FIELD_PADDING_TOP, line.name, sizeof(line.name),
textColor);
}
bool isActive() const override
{
return isExpoActive(index);
// second line ...
if (line.swtch) {
dc->drawMask(3, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupSwitchIcon, textColor);
drawSwitch(dc, 21, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.swtch,
textColor);
}
void paintBody(BitmapBuffer * dc) override
{
const ExpoData & line = g_model.expoData[index];
// first line ...
drawValueOrGVar(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, line.weight, -100, 100);
drawSource(dc, 60, FIELD_PADDING_TOP, line.srcRaw);
if (line.name[0]) {
dc->drawMask(146, FIELD_PADDING_TOP, mixerSetupLabelIcon, DEFAULT_COLOR);
dc->drawSizedText(166, FIELD_PADDING_TOP, line.name, sizeof(line.name));
}
// second line ...
if (line.swtch) {
dc->drawMask(3, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupSwitchIcon, DEFAULT_COLOR);
drawSwitch(dc, 21, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.swtch);
}
if (line.curve.value != 0 ) {
dc->drawMask(60, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupCurveIcon, DEFAULT_COLOR);
drawCurveRef(dc, 80, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.curve);
}
if (line.flightModes) {
drawFlightModes(dc, line.flightModes);
}
if (line.curve.value != 0) {
dc->drawMask(60, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupCurveIcon, textColor);
drawCurveRef(dc, 80, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.curve,
textColor);
}
if (line.flightModes) {
drawFlightModes(dc, line.flightModes, textColor);
}
}
};
ModelInputsPage::ModelInputsPage():
@@ -396,27 +422,29 @@ void ModelInputsPage::editInput(FormWindow * window, uint8_t input, uint8_t inde
});
}
void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
void ModelInputsPage::build(FormWindow *window, int8_t focusIndex)
{
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
grid.setLabelWidth(66);
int inputIndex = 0;
ExpoData * line = g_model.expoData;
ExpoData *line = g_model.expoData;
for (uint8_t input = 0; input < MAX_INPUTS; input++) {
if (inputIndex < MAX_EXPOS && line->chn == input && EXPO_VALID(line)) {
new StaticText(window, grid.getLabelSlot(), getSourceString(MIXSRC_FIRST_INPUT + input), BUTTON_BACKGROUND, CENTERED);
coord_t h = grid.getWindowHeight();
auto txt = new StaticText(window, grid.getLabelSlot(),
getSourceString(MIXSRC_FIRST_INPUT + input),
BUTTON_BACKGROUND, CENTERED);
while (inputIndex < MAX_EXPOS && line->chn == input && EXPO_VALID(line)) {
Button * button = new InputLineButton(window, grid.getFieldSlot(), inputIndex);
if (focusIndex == inputIndex)
button->setFocus(SET_FOCUS_DEFAULT);
Button *button =
new InputLineButton(window, grid.getFieldSlot(), inputIndex);
button->setPressHandler([=]() -> uint8_t {
button->bringToTop();
Menu * menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() {
editInput(window, input, inputIndex);
});
Menu *menu = new Menu(window);
menu->addLine(STR_EDIT,
[=]() { editInput(window, input, inputIndex); });
if (!reachExposLimit()) {
menu->addLine(STR_INSERT_BEFORE, [=]() {
insertExpo(inputIndex, input);
@@ -434,7 +462,8 @@ void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
menu->addLine(STR_PASTE_BEFORE, [=]() {
copyExpo(s_copySrcIdx, inputIndex, PASTE_BEFORE);
if (s_copyMode == MOVE_MODE) {
deleteExpo((s_copySrcIdx > inputIndex) ? s_copySrcIdx+1 : s_copySrcIdx);
deleteExpo((s_copySrcIdx > inputIndex) ? s_copySrcIdx + 1
: s_copySrcIdx);
s_copyMode = 0;
}
rebuild(window, inputIndex);
@@ -442,10 +471,11 @@ void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
menu->addLine(STR_PASTE_AFTER, [=]() {
copyExpo(s_copySrcIdx, inputIndex, PASTE_AFTER);
if (s_copyMode == MOVE_MODE) {
deleteExpo((s_copySrcIdx > inputIndex) ? s_copySrcIdx+1 : s_copySrcIdx);
deleteExpo((s_copySrcIdx > inputIndex) ? s_copySrcIdx + 1
: s_copySrcIdx);
s_copyMode = 0;
}
rebuild(window, inputIndex+1);
rebuild(window, inputIndex + 1);
});
}
}
@@ -459,22 +489,40 @@ void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
});
return 0;
});
button->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
if (focus) button->bringToTop();
});
grid.spacer(button->height() - 2);
if (focusIndex == inputIndex) {
button->setFocus(SET_FOCUS_DEFAULT);
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
txt->invalidate();
}
grid.spacer(button->height() - 1);
++inputIndex;
++line;
}
h = grid.getWindowHeight() - h + 1;
txt->setHeight(h);
grid.spacer(7);
}
else {
auto button = new TextButton(window, grid.getLabelSlot(), getSourceString(MIXSRC_FIRST_INPUT + input));
if (focusIndex == inputIndex)
button->setFocus(SET_FOCUS_DEFAULT);
} else {
auto button = new TextButton(window, grid.getLabelSlot(),
getSourceString(MIXSRC_FIRST_INPUT + input));
if (focusIndex == inputIndex) button->setFocus(SET_FOCUS_DEFAULT);
button->setPressHandler([=]() -> uint8_t {
button->bringToTop();
Menu * menu = new Menu(window);
Menu *menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() {
insertExpo(inputIndex, input);
editInput(window, input, inputIndex);
@@ -484,8 +532,9 @@ void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
if (s_copyMode != 0) {
menu->addLine(STR_PASTE, [=]() {
copyExpo(s_copySrcIdx, inputIndex, input);
if(s_copyMode == MOVE_MODE) {
deleteExpo((s_copySrcIdx >= inputIndex) ? s_copySrcIdx+1 : s_copySrcIdx);
if (s_copyMode == MOVE_MODE) {
deleteExpo((s_copySrcIdx >= inputIndex) ? s_copySrcIdx + 1
: s_copySrcIdx);
s_copyMode = 0;
}
rebuild(window, -1);
@@ -500,7 +549,7 @@ void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
}
}
Window * focus = Window::getFocus();
Window *focus = Window::getFocus();
if (focus) {
focus->bringToTop();
}
+1 -1
View File
@@ -56,7 +56,7 @@ class CommonInputOrMixButton : public Button {
void checkEvents() override;
void drawFlightModes(BitmapBuffer *dc, FlightModesType value);
void drawFlightModes(BitmapBuffer *dc, FlightModesType value, LcdFlags textColor);
void paint(BitmapBuffer * dc) override;
+130 -104
View File
@@ -73,8 +73,15 @@ class LogicalSwitchEditPage: public Page
void buildHeader(Window * window)
{
new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT }, STR_MENULOGICALSWITCHES, 0, MENU_COLOR);
headerSwitchName = new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT }, getSwitchPositionName(SWSRC_SW1 + index), 0, MENU_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_MENULOGICALSWITCHES, 0, FOCUS_COLOR);
headerSwitchName = new StaticText(
window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
getSwitchPositionName(SWSRC_SW1 + index), 0, FOCUS_COLOR);
}
void updateLogicalSwitchOneWindow()
@@ -234,93 +241,97 @@ static constexpr coord_t col1 = 20;
static constexpr coord_t col2 = (LCD_W - 100) / 3 + col1;
static constexpr coord_t col3 = ((LCD_W - 100) / 3) * 2 + col1;
class LogicalSwitchButton : public Button {
public:
LogicalSwitchButton(FormGroup * parent, const rect_t & rect, int lsIndex):
Button(parent, rect),
lsIndex(lsIndex),
active(isActive())
{
LogicalSwitchData * ls = lswAddress(lsIndex);
if (ls->andsw != SWSRC_NONE || ls->duration != 0 || ls->delay != 0)
setHeight(height() + 20);
if (lswFamily(ls->func) == LS_FAMILY_EDGE)
setHeight(height() + 20);
class LogicalSwitchButton : public Button
{
public:
LogicalSwitchButton(FormGroup* parent, const rect_t& rect, int lsIndex) :
Button(parent, rect), lsIndex(lsIndex), active(isActive())
{
LogicalSwitchData* ls = lswAddress(lsIndex);
if (ls->andsw != SWSRC_NONE || ls->duration != 0 || ls->delay != 0)
setHeight(height() + 20);
if (lswFamily(ls->func) == LS_FAMILY_EDGE) setHeight(height() + 20);
}
bool isActive() const
{
return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + lsIndex);
}
void checkEvents() override
{
if (active != isActive()) {
invalidate();
active = !active;
}
bool isActive() const
{
return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + lsIndex);
Button::checkEvents();
}
void paintLogicalSwitchLine(BitmapBuffer* dc)
{
LogicalSwitchData* ls = lswAddress(lsIndex);
uint8_t lsFamily = lswFamily(ls->func);
// CSW func
dc->drawTextAtIndex(col1, line1, STR_VCSWFUNC, ls->func);
// CSW params
if (lsFamily == LS_FAMILY_BOOL || lsFamily == LS_FAMILY_STICKY) {
drawSwitch(dc, col2, line1, ls->v1);
drawSwitch(dc, col3, line1, ls->v2);
} else if (lsFamily == LS_FAMILY_EDGE) {
drawSwitch(dc, col1, line2, ls->v1);
putsEdgeDelayParam(dc, col2, line2, ls);
} else if (lsFamily == LS_FAMILY_COMP) {
drawSource(dc, col2, line1, ls->v1, 0);
drawSource(dc, col3, line1, ls->v2, 0);
} else if (lsFamily == LS_FAMILY_TIMER) {
dc->drawNumber(col2, line1, lswTimerValue(ls->v1), LEFT | PREC1);
dc->drawNumber(col3, line1, lswTimerValue(ls->v2), LEFT | PREC1);
} else {
drawSource(dc, col2, line1, ls->v1, 0);
drawSourceCustomValue(
dc, col3, line1, ls->v1,
(ls->v1 <= MIXSRC_LAST_CH ? calc100toRESX(ls->v2) : ls->v2), 0);
}
void checkEvents() override
{
if (active != isActive()) {
invalidate();
active = !active;
}
// AND switch
drawSwitch(dc, col1, (lsFamily == LS_FAMILY_EDGE) ? line3 : line2,
ls->andsw, 0);
Button::checkEvents();
// CSW duration
if (ls->duration > 0) {
dc->drawNumber(col2, (lsFamily == LS_FAMILY_EDGE) ? line3 : line2,
ls->duration, PREC1 | LEFT);
}
void paintLogicalSwitchLine(BitmapBuffer * dc)
{
LogicalSwitchData * ls = lswAddress(lsIndex);
uint8_t lsFamily = lswFamily(ls->func);
// CSW func
dc->drawTextAtIndex(col1, line1, STR_VCSWFUNC, ls->func);
// CSW params
if (lsFamily == LS_FAMILY_BOOL || lsFamily == LS_FAMILY_STICKY) {
drawSwitch(dc, col2, line1, ls->v1);
drawSwitch(dc, col3, line1, ls->v2);
}
else if (lsFamily == LS_FAMILY_EDGE) {
drawSwitch(dc, col1, line2, ls->v1);
putsEdgeDelayParam(dc, col2, line2, ls);
}
else if (lsFamily == LS_FAMILY_COMP) {
drawSource(dc, col2, line1, ls->v1, 0);
drawSource(dc, col3, line1, ls->v2, 0);
}
else if (lsFamily == LS_FAMILY_TIMER) {
dc->drawNumber(col2, line1, lswTimerValue(ls->v1), LEFT|PREC1);
dc->drawNumber(col3, line1, lswTimerValue(ls->v2), LEFT|PREC1);
}
else {
drawSource(dc, col2, line1, ls->v1, 0);
drawSourceCustomValue(dc, col3, line1, ls->v1, (ls->v1 <= MIXSRC_LAST_CH ? calc100toRESX(ls->v2) : ls->v2), 0);
}
// AND switch
drawSwitch(dc, col1, (lsFamily == LS_FAMILY_EDGE) ? line3 : line2, ls->andsw, 0);
// CSW duration
if (ls->duration > 0) {
dc->drawNumber(col2, (lsFamily == LS_FAMILY_EDGE) ? line3 : line2, ls->duration, PREC1 | LEFT);
}
// CSW delay
if (lsFamily != LS_FAMILY_EDGE && ls->delay > 0) {
dc->drawNumber(col3, (lsFamily == LS_FAMILY_EDGE) ? line3 : line2, ls->delay, PREC1 | LEFT);
}
// CSW delay
if (lsFamily != LS_FAMILY_EDGE && ls->delay > 0) {
dc->drawNumber(col3, (lsFamily == LS_FAMILY_EDGE) ? line3 : line2,
ls->delay, PREC1 | LEFT);
}
}
void paint(BitmapBuffer * dc) override
{
if (active)
dc->drawSolidFilledRect(2, 2, rect.w-4, rect.h-4, HIGHLIGHT_COLOR);
void paint(BitmapBuffer* dc) override
{
if (active)
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, HIGHLIGHT_COLOR);
else
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, FIELD_BGCOLOR);
paintLogicalSwitchLine(dc);
paintLogicalSwitchLine(dc);
// The bounding rect
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
}
// The bounding rect
if (hasFocus())
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
else
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
}
protected:
uint8_t lsIndex;
bool active;
protected:
uint8_t lsIndex;
bool active;
};
ModelLogicalSwitchesPage::ModelLogicalSwitchesPage():
@@ -344,17 +355,18 @@ void ModelLogicalSwitchesPage::editLogicalSwitch(FormWindow * window, uint8_t ls
});
}
void ModelLogicalSwitchesPage::build(FormWindow * window, int8_t focusIndex)
void ModelLogicalSwitchesPage::build(FormWindow* window, int8_t focusIndex)
{
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
grid.setLabelWidth(66);
for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) {
LogicalSwitchData * ls = lswAddress(i);
LogicalSwitchData* ls = lswAddress(i);
if (ls->func == LS_FUNC_NONE) {
auto button = new TextButton(window, grid.getLabelSlot(), getSwitchPositionName(SWSRC_SW1+i));
auto button = new TextButton(window, grid.getLabelSlot(),
getSwitchPositionName(SWSRC_SW1 + i));
button->setPressHandler([=]() {
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH) {
Menu* menu = new Menu(window);
@@ -370,40 +382,54 @@ void ModelLogicalSwitchesPage::build(FormWindow * window, int8_t focusIndex)
return 0;
});
grid.spacer(button->height() + 5);
}
else {
new StaticText(window, grid.getLabelSlot(), getSwitchPositionName(SWSRC_SW1 + i), BUTTON_BACKGROUND, CENTERED);
} else {
auto txt = new StaticText(window, grid.getLabelSlot(),
getSwitchPositionName(SWSRC_SW1 + i),
BUTTON_BACKGROUND, CENTERED);
auto button = new LogicalSwitchButton(window, grid.getFieldSlot(), i);
button->setPressHandler([=]() {
Menu * menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() {
editLogicalSwitch(window, i);
Menu* menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() { editLogicalSwitch(window, i); });
if (ls->func)
menu->addLine(STR_COPY, [=]() {
clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH;
clipboard.data.csw = *ls;
});
if (ls->func)
menu->addLine(STR_COPY, [=]() {
clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH;
clipboard.data.csw = *ls;
});
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH)
menu->addLine(STR_PASTE, [=]() {
*ls = clipboard.data.csw;
storageDirty(EE_MODEL);
rebuild(window, i);
});
if (ls->func || ls->v1 || ls->v2 || ls->delay || ls->duration || ls->andsw)
menu->addLine(STR_CLEAR, [=]() {
memset(ls, 0, sizeof(LogicalSwitchData));
storageDirty(EE_MODEL);
rebuild(window, i);
});
return 0;
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH)
menu->addLine(STR_PASTE, [=]() {
*ls = clipboard.data.csw;
storageDirty(EE_MODEL);
rebuild(window, i);
});
if (ls->func || ls->v1 || ls->v2 || ls->delay || ls->duration ||
ls->andsw)
menu->addLine(STR_CLEAR, [=]() {
memset(ls, 0, sizeof(LogicalSwitchData));
storageDirty(EE_MODEL);
rebuild(window, i);
});
return 0;
});
button->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
if (focusIndex == i) {
button->setFocus(SET_FOCUS_DEFAULT);
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
txt->invalidate();
}
txt->setHeight(button->height());
grid.spacer(button->height() + 5);
}
}
@@ -29,7 +29,7 @@ public:
virtual void build(FormWindow * window) override
{
build(window, -1);
build(window, 0);
}
protected:
+263 -199
View File
@@ -53,235 +53,253 @@ bool reachMixesLimit()
return false;
}
class MixEditWindow : public Page {
public:
MixEditWindow(int8_t channel, uint8_t mixIndex) :
Page(ICON_MODEL_MIXER),
channel(channel),
mixIndex(mixIndex)
{
buildBody(&body);
buildHeader(&header);
class MixEditWindow : public Page
{
public:
MixEditWindow(int8_t channel, uint8_t mixIndex) :
Page(ICON_MODEL_MIXER), channel(channel), mixIndex(mixIndex)
{
buildBody(&body);
buildHeader(&header);
}
protected:
uint8_t channel;
uint8_t mixIndex;
FormGroup *curveParamField = nullptr;
void buildHeader(Window *window)
{
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_MIXES, 0, FOCUS_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
getSourceString(MIXSRC_CH1 + channel), 0, FOCUS_COLOR);
}
void buildBody(FormWindow *window)
{
FormGridLayout grid;
grid.spacer(8);
MixData *mix = mixAddress(mixIndex);
// Mix name
new StaticText(window, grid.getLabelSlot(), STR_MIXNAME);
new RadioTextEdit(window, grid.getFieldSlot(), mix->name,
sizeof(mix->name));
grid.nextLine();
// Source
new StaticText(window, grid.getLabelSlot(), STR_SOURCE);
new SourceChoice(window, grid.getFieldSlot(), 0, MIXSRC_LAST,
GET_SET_DEFAULT(mix->srcRaw));
grid.nextLine();
// Weight
new StaticText(window, grid.getLabelSlot(), STR_WEIGHT);
auto gvar =
new GVarNumberEdit(window, grid.getFieldSlot(), MIX_WEIGHT_MIN,
MIX_WEIGHT_MAX, GET_SET_DEFAULT(mix->weight));
gvar->setSuffix("%");
grid.nextLine();
// Offset
new StaticText(window, grid.getLabelSlot(), STR_OFFSET);
gvar = new GVarNumberEdit(window, grid.getFieldSlot(), MIX_OFFSET_MIN,
MIX_OFFSET_MAX, GET_SET_DEFAULT(mix->offset));
gvar->setSuffix("%");
grid.nextLine();
// Trim
new StaticText(window, grid.getLabelSlot(), STR_TRIM);
new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(mix->carryTrim));
grid.nextLine();
// Curve
new StaticText(&body, grid.getLabelSlot(), STR_CURVE);
new Choice(&body, grid.getFieldSlot(2, 0), "\004DiffExpoFuncCstm", 0,
CURVE_REF_CUSTOM, GET_DEFAULT(mix->curve.type),
[=](int32_t newValue) {
mix->curve.type = newValue;
mix->curve.value = 0;
SET_DIRTY();
updateCurveParamField(mix);
});
curveParamField =
new FormGroup(&body, grid.getFieldSlot(2, 1), FORM_FORWARD_FOCUS);
updateCurveParamField(mix);
grid.nextLine();
// Flight modes
new StaticText(window, grid.getLabelSlot(), STR_FLMODE);
for (uint8_t i = 0; i < MAX_FLIGHT_MODES; i++) {
char fm[2] = {char('0' + i), '\0'};
if (i > 0 && (i % 4) == 0) grid.nextLine();
new TextButton(
window, grid.getFieldSlot(4, i % 4), fm,
[=]() -> uint8_t {
BFBIT_FLIP(mix->flightModes, bfBit<uint8_t>(i));
SET_DIRTY();
return !(bfSingleBitGet(mix->flightModes, i));
},
OPAQUE | (bfSingleBitGet(mix->flightModes, i) ? 0 : BUTTON_CHECKED));
}
grid.nextLine();
protected:
uint8_t channel;
uint8_t mixIndex;
FormGroup * curveParamField = nullptr;
// Switch
new StaticText(window, grid.getLabelSlot(), STR_SWITCH);
new SwitchChoice(window, grid.getFieldSlot(), SWSRC_FIRST_IN_MIXES,
SWSRC_LAST_IN_MIXES, GET_SET_DEFAULT(mix->swtch));
grid.nextLine();
void buildHeader(Window * window)
{
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MIXES, 0, MENU_COLOR);
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSourceString(MIXSRC_CH1 + channel), 0, MENU_COLOR);
}
// Warning
new StaticText(window, grid.getLabelSlot(), STR_MIXWARNING);
auto edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, 3,
GET_SET_DEFAULT(mix->mixWarn));
edit->setZeroText(STR_OFF);
grid.nextLine();
void buildBody(FormWindow * window)
{
FormGridLayout grid;
grid.spacer(8);
// Multiplex
new StaticText(window, grid.getLabelSlot(), STR_MULTPX);
new Choice(window, grid.getFieldSlot(), STR_VMLTPX, 0, 2,
GET_SET_DEFAULT(mix->mltpx));
grid.nextLine();
MixData * mix = mixAddress(mixIndex);
// Delay up
new StaticText(window, grid.getLabelSlot(), STR_DELAYUP);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->delayUp),
SET_VALUE(mix->delayUp, newValue), 0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Mix name
new StaticText(window, grid.getLabelSlot(), STR_MIXNAME);
new RadioTextEdit(window, grid.getFieldSlot(), mix->name, sizeof(mix->name));
grid.nextLine();
// Delay down
new StaticText(window, grid.getLabelSlot(), STR_DELAYDOWN);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->delayDown),
SET_VALUE(mix->delayDown, newValue), 0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Source
new StaticText(window, grid.getLabelSlot(), STR_SOURCE);
new SourceChoice(window, grid.getFieldSlot(), 0, MIXSRC_LAST, GET_SET_DEFAULT(mix->srcRaw));
grid.nextLine();
// Slow up
new StaticText(window, grid.getLabelSlot(), STR_SLOWUP);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->speedUp),
SET_VALUE(mix->speedUp, newValue), 0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Weight
new StaticText(window, grid.getLabelSlot(), STR_WEIGHT);
auto gvar = new GVarNumberEdit(window, grid.getFieldSlot(), MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, GET_SET_DEFAULT(mix->weight));
gvar->setSuffix("%");
grid.nextLine();
// Slow down
new StaticText(window, grid.getLabelSlot(), STR_SLOWDOWN);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->speedDown),
SET_VALUE(mix->speedDown, newValue), 0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Offset
new StaticText(window, grid.getLabelSlot(), STR_OFFSET);
gvar = new GVarNumberEdit(window, grid.getFieldSlot(), MIX_OFFSET_MIN, MIX_OFFSET_MAX, GET_SET_DEFAULT(mix->offset));
gvar->setSuffix("%");
grid.nextLine();
window->setInnerHeight(grid.getWindowHeight());
}
// Trim
new StaticText(window, grid.getLabelSlot(), STR_TRIM);
new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(mix->carryTrim));
grid.nextLine();
// TODO share this code with INPUT
void updateCurveParamField(MixData *line)
{
curveParamField->clear();
// Curve
new StaticText(&body, grid.getLabelSlot(), STR_CURVE);
new Choice(&body, grid.getFieldSlot(2, 0), "\004DiffExpoFuncCstm", 0, CURVE_REF_CUSTOM,
GET_DEFAULT(mix->curve.type),
[=](int32_t newValue) {
mix->curve.type = newValue;
mix->curve.value = 0;
SET_DIRTY();
updateCurveParamField(mix);
});
curveParamField = new FormGroup(&body, grid.getFieldSlot(2, 1), FORM_FORWARD_FOCUS);
updateCurveParamField(mix);
grid.nextLine();
const rect_t rect = {0, 0, curveParamField->width(),
curveParamField->height()};
// Flight modes
new StaticText(window, grid.getLabelSlot(), STR_FLMODE);
for (uint8_t i = 0; i < MAX_FLIGHT_MODES; i++) {
char fm[2] = {char('0' + i), '\0'};
if (i > 0 && (i % 4) == 0)
grid.nextLine();
new TextButton(window, grid.getFieldSlot(4, i % 4), fm,
[=]() -> uint8_t {
BFBIT_FLIP(mix->flightModes, bfBit<uint8_t>(i));
SET_DIRTY();
return !(bfSingleBitGet(mix->flightModes, i));
},
OPAQUE | (bfSingleBitGet(mix->flightModes, i) ? 0 : BUTTON_CHECKED));
switch (line->curve.type) {
case CURVE_REF_DIFF:
case CURVE_REF_EXPO: {
GVarNumberEdit *edit =
new GVarNumberEdit(curveParamField, rect, -100, 100,
GET_SET_DEFAULT(line->curve.value));
edit->setSuffix("%");
break;
}
grid.nextLine();
// Switch
new StaticText(window, grid.getLabelSlot(), STR_SWITCH);
new SwitchChoice(window, grid.getFieldSlot(), SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, GET_SET_DEFAULT(mix->swtch));
grid.nextLine();
case CURVE_REF_FUNC:
new Choice(curveParamField, rect, STR_VCURVEFUNC, 0, CURVE_BASE - 1,
GET_SET_DEFAULT(line->curve.value));
break;
// Warning
new StaticText(window, grid.getLabelSlot(), STR_MIXWARNING);
auto edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, 3, GET_SET_DEFAULT(mix->mixWarn));
edit->setZeroText(STR_OFF);
grid.nextLine();
// Multiplex
new StaticText(window, grid.getLabelSlot(), STR_MULTPX);
new Choice(window, grid.getFieldSlot(), STR_VMLTPX, 0, 2, GET_SET_DEFAULT(mix->mltpx));
grid.nextLine();
// Delay up
new StaticText(window, grid.getLabelSlot(), STR_DELAYUP);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->delayUp),
SET_VALUE(mix->delayUp, newValue),
0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Delay down
new StaticText(window, grid.getLabelSlot(), STR_DELAYDOWN);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->delayDown),
SET_VALUE(mix->delayDown, newValue),
0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Slow up
new StaticText(window, grid.getLabelSlot(), STR_SLOWUP);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->speedUp),
SET_VALUE(mix->speedUp, newValue),
0, PREC1);
edit->setSuffix("s");
grid.nextLine();
// Slow down
new StaticText(window, grid.getLabelSlot(), STR_SLOWDOWN);
edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX,
GET_DEFAULT(mix->speedDown),
SET_VALUE(mix->speedDown, newValue),
0, PREC1);
edit->setSuffix("s");
grid.nextLine();
window->setInnerHeight(grid.getWindowHeight());
}
// TODO share this code with INPUT
void updateCurveParamField(MixData * line)
{
curveParamField->clear();
const rect_t rect = {0, 0, curveParamField->width(), curveParamField->height()};
switch (line->curve.type) {
case CURVE_REF_DIFF:
case CURVE_REF_EXPO:
{
GVarNumberEdit * edit = new GVarNumberEdit(curveParamField, rect, -100, 100, GET_SET_DEFAULT(line->curve.value));
edit->setSuffix("%");
break;
}
case CURVE_REF_FUNC:
new Choice(curveParamField, rect, STR_VCURVEFUNC, 0, CURVE_BASE - 1, GET_SET_DEFAULT(line->curve.value));
break;
case CURVE_REF_CUSTOM:
{
auto choice = new Choice(curveParamField, rect, -MAX_CURVES, MAX_CURVES, GET_SET_DEFAULT(line->curve.value));
choice->setTextHandler([](int value) {
return getCurveString(value);
});
break;
}
case CURVE_REF_CUSTOM: {
auto choice = new Choice(curveParamField, rect, -MAX_CURVES, MAX_CURVES,
GET_SET_DEFAULT(line->curve.value));
choice->setTextHandler([](int value) { return getCurveString(value); });
break;
}
}
}
};
class MixLineButton : public CommonInputOrMixButton {
public:
MixLineButton(FormGroup * parent, const rect_t & rect, uint8_t index) :
class MixLineButton : public CommonInputOrMixButton
{
public:
MixLineButton(FormGroup *parent, const rect_t &rect, uint8_t index) :
CommonInputOrMixButton(parent, rect, index)
{
const MixData & mix = g_model.mixData[index];
if (mix.swtch || mix.curve.value != 0 || mix.flightModes) {
setHeight(height() + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP);
}
{
const MixData &mix = g_model.mixData[index];
if (mix.swtch || mix.curve.value != 0 || mix.flightModes) {
setHeight(height() + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP);
}
}
bool isActive() const override { return isMixActive(index); }
void paintBody(BitmapBuffer *dc) override
{
const MixData &line = g_model.mixData[index];
LcdFlags textColor = DEFAULT_COLOR;
// first line ...
drawValueOrGVar(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, line.weight,
MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, textColor);
drawSource(dc, 60, FIELD_PADDING_TOP, line.srcRaw, textColor);
if (line.name[0]) {
dc->drawMask(146, FIELD_PADDING_TOP, mixerSetupLabelIcon, textColor);
dc->drawSizedText(166, FIELD_PADDING_TOP, line.name, sizeof(line.name),
textColor);
}
bool isActive() const override
{
return isMixActive(index);
// second line ...
if (line.swtch) {
dc->drawMask(3, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupSwitchIcon, textColor);
drawSwitch(dc, 21, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.swtch,
textColor);
}
void paintBody(BitmapBuffer * dc) override
{
const MixData & line = g_model.mixData[index];
// first line ...
drawValueOrGVar(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, line.weight, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX);
drawSource(dc, 60, FIELD_PADDING_TOP, line.srcRaw);
if (line.name[0]) {
dc->drawMask(146, FIELD_PADDING_TOP, mixerSetupLabelIcon, DEFAULT_COLOR);
dc->drawSizedText(166, FIELD_PADDING_TOP, line.name, sizeof(line.name));
}
// second line ...
if (line.swtch) {
dc->drawMask(3, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupSwitchIcon, DEFAULT_COLOR);
drawSwitch(dc, 21, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.swtch);
}
if (line.curve.value) {
dc->drawMask(60, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupCurveIcon, DEFAULT_COLOR);
drawCurveRef(dc, 80, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.curve, 0);
}
if (line.flightModes) {
drawFlightModes(dc, line.flightModes);
}
if (line.curve.value) {
dc->drawMask(60, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupCurveIcon, textColor);
drawCurveRef(dc, 80, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, line.curve,
textColor);
}
if (line.flightModes) {
drawFlightModes(dc, line.flightModes, textColor);
}
}
};
void insertMix(uint8_t idx, uint8_t channel)
{
pauseMixerCalculations();
MixData * mix = mixAddress(idx);
MixData *mix = mixAddress(idx);
memmove(mix + 1, mix, (MAX_MIXERS - (idx + 1)) * sizeof(MixData));
memclear(mix, sizeof(MixData));
mix->destCh = channel;
mix->srcRaw = channel + 1;
if (!isSourceAvailable(mix->srcRaw)) {
mix->srcRaw = (channel > 3 ? MIXSRC_Rud - 1 + channel : MIXSRC_Rud - 1 + channelOrder(channel));
mix->srcRaw = (channel > 3 ? MIXSRC_Rud - 1 + channel
: MIXSRC_Rud - 1 + channelOrder(channel));
while (!isSourceAvailable(mix->srcRaw)) {
mix->srcRaw += 1;
}
@@ -313,6 +331,21 @@ void ModelMixesPage::editMix(FormWindow * window, uint8_t channel, uint8_t mixIn
});
}
class MixLineTitle : public StaticText
{
public:
using StaticText::StaticText;
void setTextFlags(LcdFlags flags)
{
textFlags = flags;
for (auto child : children) {
auto bitmap = dynamic_cast<StaticBitmap*>(child);
if (bitmap) bitmap->setMaskColor(flags & 0xFFFF0000);
}
}
};
void ModelMixesPage::build(FormWindow * window, int8_t focusMixIndex)
{
FormGridLayout grid;
@@ -329,12 +362,15 @@ void ModelMixesPage::build(FormWindow * window, int8_t focusMixIndex)
MixData * mix = g_model.mixData;
for (uint8_t ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) {
if (mixIndex < MAX_MIXERS && mix->srcRaw > 0 && mix->destCh == ch) {
new StaticText(window, grid.getLabelSlot(), getSourceString(MIXSRC_CH1 + ch), BUTTON_BACKGROUND, CENTERED);
coord_t h = grid.getWindowHeight();
auto txt = new MixLineTitle(window, grid.getLabelSlot(),
getSourceString(MIXSRC_CH1 + ch),
BUTTON_BACKGROUND, CENTERED);
uint8_t count = 0;
while (mixIndex < MAX_MIXERS && mix->srcRaw > 0 && mix->destCh == ch) {
Button * button = new MixLineButton(window, grid.getFieldSlot(), mixIndex);
if (focusMixIndex == mixIndex)
button->setFocus(SET_FOCUS_DEFAULT);
button->setPressHandler([=]() -> uint8_t {
button->bringToTop();
Menu * menu = new Menu(window);
@@ -385,14 +421,42 @@ void ModelMixesPage::build(FormWindow * window, int8_t focusMixIndex)
});
if (count++ > 0) {
new StaticBitmap(window, {35, button->top() + (button->height() - 18) / 2, 25, 17}, mixerMultiplexBitmap[mix->mltpx]);
new StaticBitmap(
txt,
{35 - txt->left(),
button->top() - txt->top() + (button->height() - 18) / 2, 25,
17},
mixerMultiplexBitmap[mix->mltpx], DEFAULT_COLOR);
}
grid.spacer(button->height() - 2);
button->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
if (focus) button->bringToTop();
});
if (focusMixIndex == mixIndex) {
button->setFocus(SET_FOCUS_DEFAULT);
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
txt->invalidate();
}
grid.spacer(button->height() - 1);
++mixIndex;
++mix;
}
h = grid.getWindowHeight() - h + 1;
txt->setHeight(h);
grid.spacer(7);
}
else {
+52 -14
View File
@@ -39,8 +39,14 @@ class OutputEditWindow : public Page {
void buildHeader(Window * window)
{
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENULIMITS, 0, MENU_COLOR);
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, getSourceString(MIXSRC_CH1 + channel), 0, MENU_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_MENULIMITS, 0, FOCUS_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
getSourceString(MIXSRC_CH1 + channel), 0, FOCUS_COLOR);
}
void buildBody(FormWindow * window)
@@ -120,28 +126,44 @@ class OutputLineButton : public Button {
void paint(BitmapBuffer * dc) override
{
LcdFlags textColor = DEFAULT_COLOR;
LcdFlags bgColor = FIELD_BGCOLOR;
dc->drawSolidFilledRect(0, 0, width(), height(), bgColor);
// first line
dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, output->min - 1000, PREC1);
dc->drawNumber(68, FIELD_PADDING_TOP, output->max + 1000, PREC1);
dc->drawNumber(132, FIELD_PADDING_TOP, output->offset, PREC1);
dc->drawNumber(226, FIELD_PADDING_TOP, PPM_CENTER + output->ppmCenter, RIGHT);
dc->drawText(228, FIELD_PADDING_TOP, output->symetrical ? "=" : "\210");
dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, output->min - 1000,
PREC1 | textColor);
dc->drawNumber(68, FIELD_PADDING_TOP, output->max + 1000, PREC1 | textColor);
dc->drawNumber(132, FIELD_PADDING_TOP, output->offset, PREC1 | textColor);
dc->drawNumber(226, FIELD_PADDING_TOP, PPM_CENTER + output->ppmCenter,
RIGHT | textColor);
dc->drawText(228, FIELD_PADDING_TOP, output->symetrical ? "=" : "\210",
textColor);
// second line
if (output->revert) {
dc->drawTextAtIndex(4, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, STR_MMMINV, output->revert);
dc->drawTextAtIndex(4, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, STR_MMMINV,
output->revert, textColor);
}
if (output->curve) {
dc->drawMask(68, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupCurveIcon, DEFAULT_COLOR);
dc->drawText(88, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, getCurveString(output->curve));
dc->drawMask(68, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupCurveIcon, textColor);
dc->drawText(88, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
getCurveString(output->curve), textColor);
}
if (output->name[0]) {
dc->drawMask(146, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, mixerSetupLabelIcon, DEFAULT_COLOR);
dc->drawSizedText(166, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, output->name, sizeof(output->name));
dc->drawMask(146, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
mixerSetupLabelIcon, textColor);
dc->drawSizedText(166, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP,
output->name, sizeof(output->name), textColor);
}
// bounding rect
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
if (hasFocus())
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
else
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
}
protected:
@@ -171,7 +193,9 @@ void ModelOutputsPage::build(FormWindow * window, int8_t focusChannel)
LimitData * output = limitAddress(ch);
// Channel label
new StaticText(window, grid.getLabelSlot(), getSourceString(MIXSRC_CH1 + ch), BUTTON_BACKGROUND, CENTERED);
auto txt = new StaticText(window, grid.getLabelSlot(),
getSourceString(MIXSRC_CH1 + ch),
BUTTON_BACKGROUND, CENTERED);
// Channel settings
Button * button = new OutputLineButton(window, grid.getFieldSlot(), output);
@@ -203,11 +227,25 @@ void ModelOutputsPage::build(FormWindow * window, int8_t focusChannel)
});
return 0;
});
button->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
if (focusChannel == ch) {
button->setFocus(SET_FOCUS_DEFAULT);
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
txt->invalidate();
}
txt->setHeight(button->height());
grid.spacer(button->height() + 5);
}
+1 -1
View File
@@ -29,7 +29,7 @@ class ModelOutputsPage: public PageTab {
virtual void build(FormWindow * window) override
{
build(window, -1);
build(window, 0);
}
protected:
+241 -269
View File
@@ -24,9 +24,23 @@
#include "storage/modelslist.h"
#include "libopenui.h"
#define CATEGORIES_WIDTH 120
#define MODELS_LEFT 123
#define MODELS_COLUMN_WIDTH 174
#if LCD_W > LCD_H
constexpr int MODEL_CELLS_PER_LINE = 3;
#else
constexpr int MODEL_CELLS_PER_LINE = 2;
#endif
constexpr coord_t MODEL_CELL_PADDING = 6;
constexpr coord_t MODEL_SELECT_CELL_WIDTH =
(LCD_W - (MODEL_CELLS_PER_LINE + 1) * MODEL_CELL_PADDING) /
MODEL_CELLS_PER_LINE;
constexpr coord_t MODEL_SELECT_CELL_HEIGHT = 92;
constexpr coord_t MODEL_IMAGE_WIDTH = MODEL_SELECT_CELL_WIDTH;
constexpr coord_t MODEL_IMAGE_HEIGHT = 72;
enum ModelSelectMode {
MODE_SELECT_MODEL,
@@ -66,310 +80,268 @@ void setCurrentCategory(unsigned int index)
}
#endif
class ModelButton: public Button {
public:
ModelButton(FormGroup * parent, const rect_t & rect, ModelCell * modelCell, Window * footer) :
Button(parent, rect),
modelCell(modelCell)
{
load();
}
class ModelButton : public Button
{
public:
ModelButton(FormGroup *parent, const rect_t &rect, ModelCell *modelCell) :
Button(parent, rect), modelCell(modelCell)
{
load();
}
void load()
{
uint8_t version;
~ModelButton()
{
if (buffer) { delete buffer; }
}
void load()
{
uint8_t version;
PACK(struct {
ModelHeader header;
TimerData timers[MAX_TIMERS];
}) partialModel;
const char * error = nullptr;
PACK(struct {
ModelHeader header;
TimerData timers[MAX_TIMERS];
})
partialModel;
const char *error = nullptr;
if (strncmp(modelCell->modelFilename, g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME) == 0) {
memcpy(&partialModel.header, &g_model.header, sizeof(partialModel));
}
else {
error = readModel(modelCell->modelFilename, (uint8_t *)&partialModel.header, sizeof(partialModel), &version);
if (!error) {
if (modelCell->modelName[0] == '\0'
&& partialModel.header.name[0] != '\0') {
modelCell->setModelName(partialModel.header.name);
}
if (strncmp(modelCell->modelFilename, g_eeGeneral.currModelFilename,
LEN_MODEL_FILENAME) == 0) {
memcpy(&partialModel.header, &g_model.header, sizeof(partialModel));
} else {
error =
readModel(modelCell->modelFilename, (uint8_t *)&partialModel.header,
sizeof(partialModel), &version);
if (!error) {
if (modelCell->modelName[0] == '\0' &&
partialModel.header.name[0] != '\0') {
modelCell->setModelName(partialModel.header.name);
}
}
buffer = new BitmapBuffer(BMP_RGB565, MODELCELL_WIDTH, MODELCELL_HEIGHT);
if (buffer == nullptr) {
return;
}
buffer->clear(DEFAULT_BGCOLOR);
if (error) {
buffer->drawText(5, 2, "(Invalid Model)", DEFAULT_COLOR);
buffer->drawBitmapPattern(5, 23, LBM_LIBRARY_SLOT, DEFAULT_COLOR);
}
else {
char timerName[LEN_TIMER_STRING];
buffer->drawSizedText(5, 2, modelCell->modelName, LEN_MODEL_NAME, FONT(XS) | DEFAULT_COLOR);
getTimerString(timerName, 0);
for (auto & timer : partialModel.timers) {
if (timer.mode > 0 && timer.persistent) {
getTimerString(timerName, timer.value);
break;
}
}
buffer->drawText(101, 40, timerName, DEFAULT_COLOR);
for (int i = 0; i < 4; i++) {
buffer->drawBitmapPattern(104+i*11, 25, LBM_SCORE0, TITLE_BGCOLOR);
}
GET_FILENAME(filename, BITMAPS_PATH, partialModel.header.bitmap, "");
const BitmapBuffer * bitmap = BitmapBuffer::loadBitmap(filename);
if (bitmap) {
buffer->drawScaledBitmap(bitmap, 5, 24, 56, 32);
delete bitmap;
}
else {
buffer->drawBitmapPattern(5, 23, LBM_LIBRARY_SLOT, DEFAULT_COLOR);
}
}
buffer->drawSolidHorizontalLine(5, 19, 143, LINE_COLOR);
}
void paint(BitmapBuffer * dc) override
{
FormField::paint(dc);
dc->drawBitmap(10, 2, buffer);
if (modelCell == modelslist.getCurrentModel()) {
dc->drawBitmapPattern(112, 71, LBM_ACTIVE_MODEL, TITLE_BGCOLOR);
}
}
const char * modelFilename()
{
return modelCell->modelFilename;
delete buffer;
buffer = new BitmapBuffer(BMP_RGB565, width(), height());
if (buffer == nullptr) {
return;
}
buffer->clear(FIELD_BGCOLOR);
if (error) {
buffer->drawText(width() / 2, 2, "(Invalid Model)",
DEFAULT_COLOR | CENTERED);
} else {
GET_FILENAME(filename, BITMAPS_PATH, partialModel.header.bitmap, "");
const BitmapBuffer *bitmap = BitmapBuffer::loadBitmap(filename);
if (bitmap) {
buffer->drawScaledBitmap(bitmap, 0, 0, width(), height());
delete bitmap;
} else {
buffer->drawText(width() / 2, 56, "(No Picture)",
FONT(XXS) | DEFAULT_COLOR | CENTERED);
}
}
}
void paint(BitmapBuffer *dc) override
{
FormField::paint(dc);
if (buffer)
dc->drawBitmap(0, 0, buffer);
if (modelCell == modelslist.getCurrentModel()) {
dc->drawSolidFilledRect(0, 0, width(), 20, HIGHLIGHT_COLOR);
dc->drawSizedText(width() / 2, 2, modelCell->modelName,
LEN_MODEL_NAME,
DEFAULT_COLOR | CENTERED);
} else {
LcdFlags textColor;
// if (hasFocus()) {
// dc->drawFilledRect(0, 0, width(), 20, SOLID, FOCUS_BGCOLOR, 5);
// textColor = FOCUS_COLOR;
// }
// else {
dc->drawFilledRect(0, 0, width(), 20, SOLID, FIELD_BGCOLOR, 5);
textColor = DEFAULT_COLOR;
// }
dc->drawSizedText(width() / 2, 2, modelCell->modelName,
LEN_MODEL_NAME,
textColor | CENTERED);
}
protected:
ModelCell * modelCell;
BitmapBuffer * buffer = nullptr;
if (!hasFocus()) {
dc->drawSolidRect(0, 0, width(), height(), 1, FIELD_FRAME_COLOR);
} else {
dc->drawSolidRect(0, 0, width(), height(), 2, FOCUS_BGCOLOR);
}
}
const char *modelFilename() { return modelCell->modelFilename; }
protected:
ModelCell *modelCell;
BitmapBuffer *buffer = nullptr;
};
class ModelSelectFooter: public Window {
public:
explicit ModelSelectFooter(Window * parent):
Window(parent, {0, parent->height() - MODEL_SELECT_FOOTER_HEIGHT, LCD_W, MODEL_SELECT_FOOTER_HEIGHT}, OPAQUE)
{
}
class ModelCategoryPageBody : public FormWindow
{
public:
ModelCategoryPageBody(FormWindow *parent, const rect_t &rect,
ModelsCategory *category) :
FormWindow(parent, rect, FORM_FORWARD_FOCUS), category(category)
{
update();
}
void setCurrentModel(ModelCell * model)
{
currentModel = model;
invalidate();
}
void update(int selected = 0)
{
clear();
void paint(BitmapBuffer * dc) override
{
dc->drawSolidFilledRect(0, 0, width(), height(), DISABLE_COLOR);
uint32_t size = sdGetSize() / 100;
coord_t x = 7;
if (modelselSdFreeBitmap) {
dc->drawMask(7, 4, modelselSdFreeBitmap, DEFAULT_COLOR);
x += modelselSdFreeBitmap->width() + 3;
}
x = dc->drawNumber(x, 3, size, PREC1|FONT(XS), 0, nullptr, "GB");
x += 20;
if (modelselModelQtyBitmap) {
dc->drawMask(x, 4, modelselModelQtyBitmap, DEFAULT_COLOR);
x += modelselModelQtyBitmap->width() + 3;
}
x = dc->drawNumber(x, 3, modelslist.getModelsCount(), FONT(XS));
if (currentModel) {
x += 20;
if (modelselModelNameBitmap) {
dc->drawMask(x, 4, modelselModelNameBitmap, DEFAULT_COLOR);
x += modelselModelNameBitmap->width() + 3;
}
dc->drawText(x, 3, currentModel->modelFilename, FONT(XS) | DEFAULT_COLOR);
}
}
int index = 0;
coord_t y = MODEL_CELL_PADDING;
coord_t x = MODEL_CELL_PADDING;
protected:
ModelCell * currentModel = nullptr;
};
for (auto &model : *category) {
auto button = new ModelButton(
this, {x, y, MODEL_SELECT_CELL_WIDTH, MODEL_SELECT_CELL_HEIGHT},
model);
button->setPressHandler([=]() -> uint8_t {
if (button->hasFocus()) {
Menu *menu = new Menu(parent);
if (model != modelslist.getCurrentModel()) {
menu->addLine(STR_SELECT_MODEL, [=]() {
// we store the latest changes if any
storageFlushCurrentModel();
storageCheck(true);
memcpy(g_eeGeneral.currModelFilename, model->modelFilename,
LEN_MODEL_FILENAME);
loadModel(g_eeGeneral.currModelFilename, false);
storageDirty(EE_GENERAL);
storageCheck(true);
#if LCD_W > LCD_H
constexpr coord_t MODEL_SELECT_CELL_WIDTH = (LCD_W - 3 * PAGE_PADDING) / 2;
#else
constexpr coord_t MODEL_SELECT_CELL_WIDTH = LCD_W - 2 * PAGE_PADDING;
#endif
constexpr coord_t MODEL_SELECT_CELL_HEIGHT = 94;
class ModelCategoryPageBody: public FormWindow {
public:
ModelCategoryPageBody(FormWindow * parent, const rect_t & rect, ModelsCategory * category, ModelSelectFooter * footer):
FormWindow(parent, rect, FORM_FORWARD_FOCUS),
category(category),
footer(footer)
{
update();
}
void update(int selected = 0)
{
clear();
int index = 0;
coord_t y = PAGE_PADDING;
coord_t x = PAGE_PADDING;
coord_t h = PAGE_PADDING;
for (auto & model: * category) {
auto button = new ModelButton(this, {x, y, MODEL_SELECT_CELL_WIDTH, MODEL_SELECT_CELL_HEIGHT}, model, nullptr);
button->setFocusHandler([=](bool active) {
if (active) {
footer->setCurrentModel(model);
modelslist.setCurrentModel(model);
update(); // modelslist.getModelIndex(modelCell));
});
}
});
button->setPressHandler([=]() -> uint8_t {
if (button->hasFocus()) {
Menu * menu = new Menu(parent);
if (model != modelslist.getCurrentModel()) {
menu->addLine(STR_SELECT_MODEL, [=]() {
// we store the latest changes if any
storageFlushCurrentModel();
storageCheck(true);
memcpy(g_eeGeneral.currModelFilename, model->modelFilename, LEN_MODEL_FILENAME);
loadModel(g_eeGeneral.currModelFilename, false);
storageDirty(EE_GENERAL);
storageCheck(true);
modelslist.setCurrentModel(model);
update(); // modelslist.getModelIndex(modelCell));
});
}
menu->addLine(STR_CREATE_MODEL, getCreateModelAction());
menu->addLine(STR_DUPLICATE_MODEL, [=]() {
char duplicatedFilename[LEN_MODEL_FILENAME + 1];
memcpy(duplicatedFilename, model->modelFilename, sizeof(duplicatedFilename));
if (findNextFileIndex(duplicatedFilename, LEN_MODEL_FILENAME, MODELS_PATH)) {
sdCopyFile(model->modelFilename, MODELS_PATH, duplicatedFilename, MODELS_PATH);
modelslist.addModel(category, duplicatedFilename);
update(index);
}
else {
POPUP_WARNING("Invalid File");
}
});
// menu->addLine(STR_MOVE_MODEL);
if (model != modelslist.getCurrentModel()) {
menu->addLine(STR_DELETE_MODEL, [=]() {
new ConfirmDialog(parent, STR_DELETE_MODEL, std::string(model->modelName, sizeof(model->modelName)).c_str(), [=] {
modelslist.removeModel(category, model);
update(index > 0 ? index - 1 : 0);
menu->addLine(STR_CREATE_MODEL, getCreateModelAction());
menu->addLine(STR_DUPLICATE_MODEL, [=]() {
char duplicatedFilename[LEN_MODEL_FILENAME + 1];
memcpy(duplicatedFilename, model->modelFilename,
sizeof(duplicatedFilename));
if (findNextFileIndex(duplicatedFilename, LEN_MODEL_FILENAME,
MODELS_PATH)) {
sdCopyFile(model->modelFilename, MODELS_PATH, duplicatedFilename,
MODELS_PATH);
modelslist.addModel(category, duplicatedFilename);
update(index);
} else {
POPUP_WARNING("Invalid File");
}
});
// menu->addLine(STR_MOVE_MODEL);
if (model != modelslist.getCurrentModel()) {
menu->addLine(STR_DELETE_MODEL, [=]() {
new ConfirmDialog(
parent, STR_DELETE_MODEL,
std::string(model->modelName, sizeof(model->modelName))
.c_str(),
[=] {
modelslist.removeModel(category, model);
update(index > 0 ? index - 1 : 0);
});
});
}
}
else {
button->setFocus(SET_FOCUS_DEFAULT);
}
return 1;
});
if (selected == index) {
});
}
} else {
button->setFocus(SET_FOCUS_DEFAULT);
footer->setCurrentModel(model);
}
return 1;
});
if (selected == index) {
button->setFocus(SET_FOCUS_DEFAULT);
}
index++;
#if LCD_W > LCD_H
if (index % 2 == 0) {
x = PAGE_PADDING + MODEL_SELECT_CELL_WIDTH + PAGE_PADDING;
h += MODEL_SELECT_CELL_HEIGHT + PAGE_PADDING;
}
else {
x = PAGE_PADDING;
y += MODEL_SELECT_CELL_HEIGHT + PAGE_PADDING;
}
if (index % MODEL_CELLS_PER_LINE == 0) {
x = MODEL_CELL_PADDING;
y += MODEL_SELECT_CELL_HEIGHT + MODEL_CELL_PADDING;
} else {
x += MODEL_CELL_PADDING + MODEL_SELECT_CELL_WIDTH;
}
#else
h += MODEL_SELECT_CELL_HEIGHT + PAGE_PADDING;
y += MODEL_SELECT_CELL_HEIGHT + PAGE_PADDING;
y += MODEL_SELECT_CELL_HEIGHT + MODEL_CELL_PADDING;
#endif
index++;
}
setInnerHeight(h);
if (category->empty()) {
setFocus();
}
}
y += MODEL_SELECT_CELL_HEIGHT + MODEL_CELL_PADDING;
setInnerHeight(y);
if (category->empty()) {
setFocus();
}
}
#if defined(HARDWARE_KEYS)
void onEvent(event_t event) override
{
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
Menu * menu = new Menu(this);
menu->addLine(STR_CREATE_MODEL, getCreateModelAction());
//TODO: create category?
}
else {
FormWindow::onEvent(event);
}
void onEvent(event_t event) override
{
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
Menu *menu = new Menu(this);
menu->addLine(STR_CREATE_MODEL, getCreateModelAction());
// TODO: create category?
} else {
FormWindow::onEvent(event);
}
}
#endif
void setFocus(uint8_t flag = SET_FOCUS_DEFAULT, Window * from = nullptr) override
{
if (category->empty()) {
// use Window::setFocus() to avoid forwarding focus to nowhere
// this crashes currently in libopenui
Window::setFocus(flag, from);
}
else {
FormWindow::setFocus(flag, from);
}
void setFocus(uint8_t flag = SET_FOCUS_DEFAULT,
Window *from = nullptr) override
{
if (category->empty()) {
// use Window::setFocus() to avoid forwarding focus to nowhere
// this crashes currently in libopenui
Window::setFocus(flag, from);
} else {
FormWindow::setFocus(flag, from);
}
}
protected:
ModelsCategory * category;
ModelSelectFooter * footer;
std::function<void(void)> getCreateModelAction()
{
return [=]() {
storageCheck(true);
modelslist.setCurrentModel(modelslist.addModel(category, createModel()));
#if defined(LUA)
// chainMenu(menuModelWizard);
#endif
update(category->size() - 1);
};
}
protected:
ModelsCategory *category;
std::function<void(void)> getCreateModelAction()
{
return [=]() {
storageCheck(true);
modelslist.setCurrentModel(modelslist.addModel(category, createModel()));
update(category->size() - 1);
};
}
};
class ModelCategoryPage: public PageTab {
public:
explicit ModelCategoryPage(ModelsCategory * category) :
PageTab(category->name, ICON_MODEL),
category(category)
{
}
class ModelCategoryPage : public PageTab
{
public:
explicit ModelCategoryPage(ModelsCategory *category) :
PageTab(category->name, ICON_MODEL), category(category)
{
}
protected:
ModelsCategory * category;
protected:
ModelsCategory *category;
void build(FormWindow * window) override
{
auto footer = new ModelSelectFooter(window);
new ModelCategoryPageBody(window, {0, 0, LCD_W, window->height() - MODEL_SELECT_FOOTER_HEIGHT}, category, footer);
}
void build(FormWindow *window) override
{
new ModelCategoryPageBody(
window, {0, 0, LCD_W, window->height()},
category);
}
};
ModelSelectMenu::ModelSelectMenu():
TabsGroup(ICON_MODEL)
{
+17 -21
View File
@@ -34,7 +34,11 @@ std::string switchWarninglabel(swsrc_t index)
CHAR_DOWN
};
return TEXT_AT_INDEX(STR_VSRCRAW, (index + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1)) + std::string(&switchPositions[g_model.switchWarningState >> (3*index) & 0x07], 1);
return TEXT_AT_INDEX(STR_VSRCRAW,
(index + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1)) +
std::string(
&switchPositions[g_model.switchWarningState >> (3 * index) & 0x07],
1);
}
class ChannelFailsafeBargraph: public Window {
@@ -80,7 +84,7 @@ class ChannelFailsafeBargraph: public Window {
class FailSafeBody : public FormGroup {
public:
FailSafeBody(FormGroup * parent, const rect_t & rect, uint8_t moduleIdx) :
FormGroup(parent, rect),
FormGroup(parent, rect, FORM_FORWARD_FOCUS),
moduleIdx(moduleIdx)
{
build();
@@ -106,16 +110,17 @@ class FailSafeBody : public FormGroup {
new StaticText(this, grid.getLabelSlot(), getSourceString(MIXSRC_CH1 + ch));
// Channel numeric value
new NumberEdit(this, grid.getFieldSlot(3, 0), -lim, lim,
GET_DEFAULT(calcRESXto1000(g_model.failsafeChannels[ch])),
new NumberEdit(this, grid.getFieldSlot(8, 0), -lim, lim,
GET_DEFAULT(g_model.failsafeChannels[ch]),
SET_VALUE(g_model.failsafeChannels[ch], newValue),
0, PREC1);
0, PREC1 | RIGHT);
// Channel bargraph
new ChannelFailsafeBargraph(this, {150, grid.getWindowHeight(), 150, PAGE_LINE_HEIGHT}, moduleIdx, ch);
new ChannelFailsafeBargraph(this, {180, grid.getWindowHeight(), 150, PAGE_LINE_HEIGHT}, moduleIdx, ch);
grid.nextLine();
}
grid.spacer();
auto out2fail = new TextButton(this, grid.getLineSlot(), STR_CHANNELS2FAILSAFE);
out2fail->setPressHandler([=]() {
setCustomFailsafe(moduleIdx);
@@ -124,33 +129,24 @@ class FailSafeBody : public FormGroup {
});
grid.nextLine();
setInnerHeight(grid.getWindowHeight());
setInnerHeight(grid.getWindowHeight() + PAGE_PADDING);
}
protected:
uint8_t moduleIdx;
};
class FailSafeFooter : public Window {
public:
FailSafeFooter(Window * parent, const rect_t & rect) :
Window(parent, rect)
{
}
void paint(BitmapBuffer * dc) override
{
}
};
class FailSafePage : public Page {
public:
explicit FailSafePage(uint8_t moduleIdx) :
Page(ICON_STATS_ANALOGS),
moduleIdx(moduleIdx)
{
new FailSafeBody(&body, {0, 0, LCD_W, height() - footerHeight}, moduleIdx);
new FailSafeFooter(&body, {0, height() - footerHeight, LCD_W, footerHeight});
new FailSafeBody(&body, {0, 0, LCD_W, body.height()}, moduleIdx);
new StaticText(&header,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_FAILSAFESET, 0, FOCUS_COLOR);
}
protected:
+16 -4
View File
@@ -61,6 +61,12 @@ class SensorButton : public Button {
void checkEvents() override
{
uint32_t now = RTOS_GET_MS();
if (now - lastRefresh >= 200) {
// update at least every 200ms
invalidate();
}
TelemetryItem & telemetryItem = telemetryItems[index];
if (telemetryItem.isFresh()) {
invalidate();
@@ -73,9 +79,10 @@ class SensorButton : public Button {
{
TelemetryItem &telemetryItem = telemetryItems[index];
if (telemetryItem.isFresh()) {
if (telemetryItem.isFresh())
dc->drawSolidFilledRect(2, 2, rect.w - 4, rect.h - 4, HIGHLIGHT_COLOR);
}
else
dc->drawSolidFilledRect(2, 2, rect.w - 4, rect.h - 4, FIELD_BGCOLOR);
dc->drawNumber(2, 1, number, LEFT, 0, nullptr, ":");
@@ -86,7 +93,7 @@ class SensorButton : public Button {
drawSensorCustomValue(dc, SENSOR_COL2, line1, index, getValue(MIXSRC_FIRST_TELEM + 3 * index), LEFT | color);
}
else {
dc->drawText(SENSOR_COL2, line1, "---", CURVE_COLOR);
dc->drawText(SENSOR_COL2, line1, "---", DEFAULT_COLOR);
}
TelemetrySensor * sensor = & g_model.telemetrySensors[index];
@@ -96,12 +103,17 @@ class SensorButton : public Button {
else if (sensor->type == TELEM_TYPE_CUSTOM && !g_model.ignoreSensorIds) {
dc->drawNumber(SENSOR_COL3, line1, sensor->instance, LEFT);
}
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
if (hasFocus())
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
else
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
}
protected:
uint8_t index;
uint8_t number;
uint32_t lastRefresh = 0;
};
class SensorEditWindow : public Page {
+5 -4
View File
@@ -26,19 +26,20 @@ PageHeader::PageHeader(Page * parent, uint8_t icon):
FormGroup(parent, { 0, 0, LCD_W, MENU_HEADER_HEIGHT }, OPAQUE),
icon(icon)
#if defined(HARDWARE_TOUCH)
, back(this, { 0, 0, MENU_HEADER_BUTTON_WIDTH, MENU_HEADER_BUTTON_WIDTH }, ICON_BACK,
, back(this, { 0, 0, MENU_HEADER_BUTTON_WIDTH, MENU_HEADER_BUTTON_WIDTH },
[=]() -> uint8_t {
parent->deleteLater();
return 0;
}, NO_FOCUS)
}, NO_FOCUS | FORM_NO_BORDER)
#endif
{
}
void PageHeader::paint(BitmapBuffer * dc)
{
OpenTxTheme::instance()->drawMenuBackground(dc, getIcon(), "");
dc->drawSolidFilledRect(MENU_HEADER_HEIGHT, 0, LCD_W - MENU_HEADER_HEIGHT, MENU_HEADER_HEIGHT, MENU_BGCOLOR);
OpenTxTheme::instance()->drawPageHeaderBackground(dc, getIcon(), "");
dc->drawSolidFilledRect(MENU_HEADER_HEIGHT, 0, LCD_W - MENU_HEADER_HEIGHT,
MENU_HEADER_HEIGHT, HEADER_COLOR);
}
Page::Page(unsigned icon):
+2 -2
View File
@@ -51,7 +51,7 @@ class PageHeader: public FormGroup
protected:
uint8_t icon;
#if defined(HARDWARE_TOUCH)
IconButton back;
Button back;
#endif
};
@@ -84,7 +84,7 @@ class Page: public Window
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override
{
Window::onTouchSlide(x, y, startX, startY, slideX, slideY);
Window::onTouchSlide(x, y, startX, startY, 0/*slideX*/, slideY);
return true;
}
#endif
+27 -10
View File
@@ -30,11 +30,14 @@ uint8_t menuCalibrationState;
class StickCalibrationWindow: public Window {
public:
StickCalibrationWindow(Window * parent, const rect_t & rect, uint8_t stickX, uint8_t stickY):
Window(parent, rect, REFRESH_ALWAYS),
stickX(stickX),
stickY(stickY)
{
StickCalibrationWindow(Window *parent, const rect_t &rect, uint8_t stickX,
uint8_t stickY) :
Window(parent, rect, REFRESH_ALWAYS), stickX(stickX), stickY(stickY)
{
setLeft(rect.x - calibStickBackground->width() / 2);
setTop(rect.y - calibStickBackground->height() / 2);
setWidth(calibStickBackground->width());
setHeight(calibStickBackground->height());
}
void paint(BitmapBuffer * dc) override
@@ -42,7 +45,9 @@ class StickCalibrationWindow: public Window {
dc->drawBitmap(0, 0, calibStickBackground);
int16_t x = calibratedAnalogs[CONVERT_MODE(stickX)];
int16_t y = calibratedAnalogs[CONVERT_MODE(stickY)];
dc->drawBitmap(width() / 2 - 9 + (bitmapSize / 2 * x) / RESX, height() / 2 - 9 - (bitmapSize / 2 * y) / RESX, calibStick);
dc->drawBitmap(width() / 2 - 9 + (bitmapSize / 2 * x) / RESX,
height() / 2 - 9 - (bitmapSize / 2 * y) / RESX,
calibStick);
}
protected:
@@ -61,8 +66,15 @@ RadioCalibrationPage::RadioCalibrationPage(bool initial):
void RadioCalibrationPage::buildHeader(Window * window)
{
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUCALIBRATION, 0, MENU_COLOR);
text = new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUTOSTART, 0,MENU_COLOR);
new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
PAGE_LINE_HEIGHT},
STR_MENUCALIBRATION, 0, FOCUS_COLOR);
text = new StaticText(window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT},
STR_MENUTOSTART, 0, FOCUS_COLOR);
}
void RadioCalibrationPage::buildBody(FormWindow * window)
@@ -72,8 +84,13 @@ void RadioCalibrationPage::buildBody(FormWindow * window)
// The two sticks
//TODO: dynamic placing
new StickCalibrationWindow(window, {40, 20, 90, 90}, STICK1, STICK2);
new StickCalibrationWindow(window, {LCD_W - 130, 20, 90, 90}, STICK4, STICK3);
new StickCalibrationWindow(window,
{window->width() / 3, window->height() / 2, 0, 0},
STICK1, STICK2);
new StickCalibrationWindow(window,
{(2 * window->width()) / 3, window->height() / 2, 0, 0},
STICK4, STICK3);
rect_t r = { 0, 0, window->width(), window->height() };
auto deco = new ViewMainDecoration(window, r);
+4 -3
View File
@@ -235,14 +235,15 @@ void RadioSdManagerPage::build(FormWindow * window)
// sort directories and files
directories.sort(compare_nocase);
files.sort(compare_nocase);
for (auto name: directories) {
new TextButton(window, grid.getLabelSlot(), name, [=]() -> uint8_t {
auto b = new TextButton(window, grid.getLabelSlot(), name, [=]() -> uint8_t {
f_chdir(name.data());
window->clear();
build(window);
return 0;
}, 0);
}, OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
grid.nextLine();
}
+156 -39
View File
@@ -112,10 +112,11 @@ void RadioToolsPage::rebuild(FormWindow * window)
*ext = '\0';
label = getBasename(path);
}
new StaticText(window, grid.getLabelSlot(), "lua", BUTTON_BACKGROUND, CENTERED);
auto txt = new StaticText(window, grid.getLabelSlot(), "lua",
BUTTON_BACKGROUND, CENTERED);
std::string path_str(path);
new TextButton(
auto b = new TextButton(
window, grid.getFieldSlot(1), label,
[window, path_str]() -> uint8_t {
f_chdir("/SCRIPTS/TOOLS/");
@@ -124,7 +125,18 @@ void RadioToolsPage::rebuild(FormWindow * window)
StandaloneLuaWindow::instance()->attach(window);
return 0;
},
0);
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
}
@@ -133,61 +145,166 @@ void RadioToolsPage::rebuild(FormWindow * window)
#if defined(INTERNAL_MODULE_PXX2)
// PXX2 modules tools
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) {
new StaticText(window, grid.getLabelSlot(), "access", BUTTON_BACKGROUND, CENTERED);
new TextButton(window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_INT, [=]() -> uint8_t {
new RadioSpectrumAnalyser(INTERNAL_MODULE);
return 0;
}, 0);
if (isPXX2ModuleOptionAvailable(
reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE]
.information.modelID,
MODULE_OPTION_SPECTRUM_ANALYSER)) {
auto txt = new StaticText(window, grid.getLabelSlot(), "access", BUTTON_BACKGROUND,
CENTERED);
auto b = new TextButton(
window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_INT,
[=]() -> uint8_t {
new RadioSpectrumAnalyser(INTERNAL_MODULE);
return 0;
},
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) {
new StaticText(window, grid.getLabelSlot(), "access", BUTTON_BACKGROUND, CENTERED);
new TextButton(window, grid.getFieldSlot(1), STR_POWER_METER_INT, [=]() -> uint8_t {
// new RadioPowerMeter(INTERNAL_MODULE);
return 0;
}, 0);
if (isPXX2ModuleOptionAvailable(
reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE]
.information.modelID,
MODULE_OPTION_POWER_METER)) {
auto txt = new StaticText(window, grid.getLabelSlot(), "access",
BUTTON_BACKGROUND, CENTERED);
auto b = new TextButton(
window, grid.getFieldSlot(1), STR_POWER_METER_INT,
[=]() -> uint8_t {
// new RadioPowerMeter(INTERNAL_MODULE);
return 0;
},
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
#endif
#if defined(INTERNAL_MODULE_MULTI)
new StaticText(window, grid.getLabelSlot(), "multi", BUTTON_BACKGROUND, CENTERED);
new TextButton(window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_INT, [=]() -> uint8_t {
new RadioSpectrumAnalyser(INTERNAL_MODULE);
return 0;
}, 0);
grid.nextLine();
{
auto txt = new StaticText(window, grid.getLabelSlot(), "multi",
BUTTON_BACKGROUND, CENTERED);
auto b = new TextButton(
window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_INT,
[=]() -> uint8_t {
new RadioSpectrumAnalyser(INTERNAL_MODULE);
return 0;
},
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
#endif
#if defined(PXX2)|| defined(MULTIMODULE)
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE)) {
new StaticText(window, grid.getLabelSlot(), isModuleMultimodule(EXTERNAL_MODULE) ? "multi" : "access", BUTTON_BACKGROUND, CENTERED);
new TextButton(window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_EXT, [=]() -> uint8_t {
new RadioSpectrumAnalyser(EXTERNAL_MODULE);
return 0;
}, 0);
if (isPXX2ModuleOptionAvailable(
reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE]
.information.modelID,
MODULE_OPTION_SPECTRUM_ANALYSER) ||
isModuleMultimodule(EXTERNAL_MODULE)) {
auto txt = new StaticText(window, grid.getLabelSlot(),
isModuleMultimodule(EXTERNAL_MODULE) ? "multi" : "access",
BUTTON_BACKGROUND, CENTERED);
auto b = new TextButton(
window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_EXT,
[=]() -> uint8_t {
new RadioSpectrumAnalyser(EXTERNAL_MODULE);
return 0;
},
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
#endif
#if defined(PXX2)
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) {
new StaticText(window, grid.getLabelSlot(), "access", BUTTON_BACKGROUND, CENTERED);
new TextButton(window, grid.getFieldSlot(1), STR_POWER_METER_EXT, [=]() -> uint8_t {
// new RadioPowerMeter(EXTERNAL_MODULE);
return 0;
}, 0);
if (isPXX2ModuleOptionAvailable(
reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE]
.information.modelID,
MODULE_OPTION_POWER_METER)) {
auto txt = new StaticText(window, grid.getLabelSlot(), "access",
BUTTON_BACKGROUND, CENTERED);
auto b = new TextButton(
window, grid.getFieldSlot(1), STR_POWER_METER_EXT,
[=]() -> uint8_t {
// new RadioPowerMeter(EXTERNAL_MODULE);
return 0;
},
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
#endif
#if defined(GHOST)
if (isModuleGhost(EXTERNAL_MODULE)) {
new StaticText(window, grid.getLabelSlot(), "ghost", BUTTON_BACKGROUND, CENTERED);
new TextButton(window, grid.getFieldSlot(1), "Ghost module config", [=]() -> uint8_t {
new RadioGhostModuleConfig(EXTERNAL_MODULE);
return 0;
}, 0);
auto txt = new StaticText(window, grid.getLabelSlot(), "ghost",
BUTTON_BACKGROUND, CENTERED);
auto b = new TextButton(
window, grid.getFieldSlot(1), "Ghost module config",
[=]() -> uint8_t {
new RadioGhostModuleConfig(EXTERNAL_MODULE);
return 0;
},
OPAQUE);
b->setBgColorHandler([=]() -> LcdFlags { return FIELD_BGCOLOR; });
b->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
grid.nextLine();
}
#endif
+6 -3
View File
@@ -64,12 +64,15 @@ void SourceChoice::paint(BitmapBuffer * dc)
if (editMode)
textColor = FOCUS_COLOR;
else if (hasFocus())
textColor = FOCUS_BGCOLOR;
else if (value == 0)
textColor = DISABLE_COLOR;
textColor = FOCUS_COLOR;
// else if (value == 0)
// textColor = DISABLE_COLOR;
else
textColor = 0;
drawSource(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, textColor);
dc->drawBitmapPattern(rect.w - 20, (rect.h - 11) / 2, LBM_DROPDOWN,
textColor);
}
// defined in gui/gui_common.cpp
+487 -388
View File
@@ -24,235 +24,301 @@
#define SET_DIRTY() storageDirty(functions == g_model.customFn ? EE_MODEL : EE_GENERAL)
class SpecialFunctionEditPage : public Page {
public:
SpecialFunctionEditPage(CustomFunctionData * functions, uint8_t index) :
Page(functions == g_model.customFn ? ICON_MODEL_SPECIAL_FUNCTIONS : ICON_RADIO_GLOBAL_FUNCTIONS),
class SpecialFunctionEditPage : public Page
{
public:
SpecialFunctionEditPage(CustomFunctionData *functions, uint8_t index) :
Page(functions == g_model.customFn ? ICON_MODEL_SPECIAL_FUNCTIONS
: ICON_RADIO_GLOBAL_FUNCTIONS),
functions(functions),
index(index)
{
buildHeader(&header);
buildBody(&body);
{
buildHeader(&header);
buildBody(&body);
}
protected:
CustomFunctionData *functions;
uint8_t index;
FormGroup *specialFunctionOneWindow = nullptr;
StaticText *headerSF = nullptr;
bool active = false;
bool isActive() const
{
return ((functions == g_model.customFn
? modelFunctionsContext.activeSwitches
: globalFunctionsContext.activeSwitches) &
((MASK_CFN_TYPE)1 << index)
? 1
: 0);
}
void checkEvents() override
{
Page::checkEvents();
if (active != isActive()) {
invalidate();
headerSF->setTextFlags(isActive() ? FONT(BOLD) | HIGHLIGHT_COLOR
: MENU_COLOR);
active = !active;
}
}
protected:
CustomFunctionData * functions;
uint8_t index;
FormGroup * specialFunctionOneWindow = nullptr;
StaticText * headerSF = nullptr;
bool active = false;
void buildHeader(Window *window)
{
new StaticText(
window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, 20},
functions == g_model.customFn ? STR_MENUCUSTOMFUNC
: STR_MENUSPECIALFUNCS,
0, FOCUS_COLOR);
headerSF = new StaticText(
window,
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT,
LCD_W - PAGE_TITLE_LEFT, 20},
(functions == g_model.customFn ? "SF" : "GF") + std::to_string(index),
0, FOCUS_COLOR);
}
bool isActive() const
{
return ((functions == g_model.customFn ? modelFunctionsContext.activeSwitches : globalFunctionsContext.activeSwitches) & ((MASK_CFN_TYPE)1 << index) ? 1 : 0);
}
void updateSpecialFunctionOneWindow()
{
FormGridLayout grid;
specialFunctionOneWindow->clear();
void checkEvents() override
{
Page::checkEvents();
if (active != isActive()) {
invalidate();
headerSF->setTextFlags(isActive() ? FONT(BOLD) |HIGHLIGHT_COLOR : MENU_COLOR);
active = !active;
}
}
CustomFunctionData *cfn = &functions[index];
uint8_t func = CFN_FUNC(cfn);
void buildHeader(Window * window)
{
new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, 20 }, functions == g_model.customFn ? STR_MENUCUSTOMFUNC : STR_MENUSPECIALFUNCS, 0, MENU_COLOR);
headerSF = new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, 20 }, (functions == g_model.customFn ? "SF" : "GF" ) + std::to_string(index), 0, MENU_COLOR);
}
void updateSpecialFunctionOneWindow()
{
FormGridLayout grid;
specialFunctionOneWindow->clear();
CustomFunctionData * cfn = &functions[index];
uint8_t func = CFN_FUNC(cfn);
// Func param
switch (func) {
case FUNC_OVERRIDE_CHANNEL:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_CH);
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), 1, MAX_OUTPUT_CHANNELS, GET_SET_VALUE_WITH_OFFSET(CFN_CH_INDEX(cfn), 1));
grid.nextLine();
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), -100, 100, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_TRAINER: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
auto choice = new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0,NUM_STICKS + 1,GET_SET_DEFAULT(CFN_PARAM(cfn)));
choice->setTextHandler([=](int32_t value) {
if (value == 0)
return std::string(STR_STICKS);
else if (value == NUM_STICKS + 1)
return std::string(STR_CHANS);
else
return TEXT_AT_INDEX(STR_VSRCRAW, value);;
});
grid.nextLine();
break;
}
case FUNC_RESET:
if (CFN_PARAM(cfn) < FUNC_RESET_PARAM_FIRST_TELEM) {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_RESET);
auto choice = new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0,
FUNC_RESET_PARAM_FIRST_TELEM + lastUsedTelemetryIndex(),
GET_SET_DEFAULT(CFN_PARAM(cfn)));
choice->setAvailableHandler(isSourceAvailableInResetSpecialFunction);
choice->setTextHandler([=](int32_t value) {
if (value < FUNC_RESET_PARAM_FIRST_TELEM)
return TEXT_AT_INDEX(STR_VFSWRESET, value);
else
return std::string(g_model.telemetrySensors[value - FUNC_RESET_PARAM_FIRST_TELEM].label, TELEM_LABEL_LEN);
});
grid.nextLine();
}
break;
case FUNC_VOLUME:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VOLUME);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_CH, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_BACKLIGHT:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_CH, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_PLAY_SOUND:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new Choice(specialFunctionOneWindow, grid.getFieldSlot(), STR_FUNCSOUNDS, 0,
AU_SPECIAL_SOUND_LAST - AU_SPECIAL_SOUND_FIRST - 1, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_PLAY_TRACK:
case FUNC_BACKGND_MUSIC:
case FUNC_PLAY_SCRIPT:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new FileChoice(specialFunctionOneWindow, grid.getFieldSlot(),
func == FUNC_PLAY_SCRIPT ? SCRIPTS_FUNCS_PATH : std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) +
std::string(currentLanguagePack->id, 2),
func == FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT,
sizeof(cfn->play.name),
[=]() {
return std::string(cfn->play.name, ZLEN(cfn->play.name));
},
[=](std::string newValue) {
strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name));
SET_DIRTY();
}, true); // strip extension
grid.nextLine();
break;
case FUNC_SET_TIMER: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_TIMER);
auto timerchoice = new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0, TIMERS - 1, GET_SET_DEFAULT(CFN_TIMER_INDEX(cfn)));
timerchoice->setTextHandler([](int32_t value) {
return std::string(STR_TIMER) + std::to_string(value + 1);
});
grid.nextLine();
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new TimeEdit(specialFunctionOneWindow, grid.getFieldSlot(), 0, 9 * 60 * 60 - 1, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
}
case FUNC_SET_FAILSAFE:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_MODULE);
new Choice(specialFunctionOneWindow, grid.getFieldSlot(), "\004Int.Ext.", 0, NUM_MODULES - 1, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_PLAY_VALUE:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_TELEM, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_HAPTIC:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), 0, 3, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_LOGS: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
auto edit = new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), 0, 255, GET_SET_DEFAULT(CFN_PARAM(cfn)));
edit->setDisplayHandler([=](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
dc->drawNumber(2, 2, CFN_PARAM(cfn), PREC1, sizeof(CFN_PARAM(cfn)), nullptr, "s");
});
break;
}
}
if (HAS_ENABLE_PARAM(func)) {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_ENABLE);
new CheckBox(specialFunctionOneWindow, grid.getFieldSlot(), GET_SET_DEFAULT(CFN_ACTIVE(cfn)));
// Func param
switch (func) {
case FUNC_OVERRIDE_CHANNEL:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_CH);
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), 1,
MAX_OUTPUT_CHANNELS,
GET_SET_VALUE_WITH_OFFSET(CFN_CH_INDEX(cfn), 1));
grid.nextLine();
}
else if (HAS_REPEAT_PARAM(func)) { // !1x 1x 1s 2s 3s ...
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_REPEAT);
auto repeat = new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(2, 1), -1, 60/CFN_PLAY_REPEAT_MUL, GET_SET_DEFAULT(CFN_PLAY_REPEAT(cfn)));
repeat->setDisplayHandler([](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), -100, 100,
GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_TRAINER: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
auto choice =
new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0,
NUM_STICKS + 1, GET_SET_DEFAULT(CFN_PARAM(cfn)));
choice->setTextHandler([=](int32_t value) {
if (value == 0)
dc->drawText(3, 0, "1x", flags);
else if (value == CFN_PLAY_REPEAT_NOSTART)
dc->drawText(3, 0, "!1x", flags);
return std::string(STR_STICKS);
else if (value == NUM_STICKS + 1)
return std::string(STR_CHANS);
else
dc->drawNumber(3, 0, value * CFN_PLAY_REPEAT_MUL, flags, 0, nullptr, "s");
return TEXT_AT_INDEX(STR_VSRCRAW, value);
;
});
grid.nextLine();
break;
}
specialFunctionOneWindow->adjustHeight();
case FUNC_RESET:
if (CFN_PARAM(cfn) < FUNC_RESET_PARAM_FIRST_TELEM) {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_RESET);
auto choice = new Choice(
specialFunctionOneWindow, grid.getFieldSlot(), 0,
FUNC_RESET_PARAM_FIRST_TELEM + lastUsedTelemetryIndex(),
GET_SET_DEFAULT(CFN_PARAM(cfn)));
choice->setAvailableHandler(isSourceAvailableInResetSpecialFunction);
choice->setTextHandler([=](int32_t value) {
if (value < FUNC_RESET_PARAM_FIRST_TELEM)
return TEXT_AT_INDEX(STR_VFSWRESET, value);
else
return std::string(
g_model.telemetrySensors[value - FUNC_RESET_PARAM_FIRST_TELEM]
.label,
TELEM_LABEL_LEN);
});
grid.nextLine();
}
break;
case FUNC_VOLUME:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VOLUME);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0,
MIXSRC_LAST_CH, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_BACKLIGHT:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0,
MIXSRC_LAST_CH, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_PLAY_SOUND:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new Choice(specialFunctionOneWindow, grid.getFieldSlot(),
STR_FUNCSOUNDS, 0,
AU_SPECIAL_SOUND_LAST - AU_SPECIAL_SOUND_FIRST - 1,
GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_PLAY_TRACK:
case FUNC_BACKGND_MUSIC:
case FUNC_PLAY_SCRIPT:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new FileChoice(
specialFunctionOneWindow, grid.getFieldSlot(),
func == FUNC_PLAY_SCRIPT
? SCRIPTS_FUNCS_PATH
: std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) +
std::string(currentLanguagePack->id, 2),
func == FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT,
sizeof(cfn->play.name),
[=]() { return std::string(cfn->play.name, ZLEN(cfn->play.name)); },
[=](std::string newValue) {
strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name));
SET_DIRTY();
},
true); // strip extension
grid.nextLine();
break;
case FUNC_SET_TIMER: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_TIMER);
auto timerchoice =
new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0,
TIMERS - 1, GET_SET_DEFAULT(CFN_TIMER_INDEX(cfn)));
timerchoice->setTextHandler([](int32_t value) {
return std::string(STR_TIMER) + std::to_string(value + 1);
});
grid.nextLine();
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new TimeEdit(specialFunctionOneWindow, grid.getFieldSlot(), 0,
9 * 60 * 60 - 1, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
}
case FUNC_SET_FAILSAFE:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_MODULE);
new Choice(specialFunctionOneWindow, grid.getFieldSlot(),
"\004Int.Ext.", 0, NUM_MODULES - 1,
GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_PLAY_VALUE:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0,
MIXSRC_LAST_TELEM, GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_HAPTIC:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), 0, 3,
GET_SET_DEFAULT(CFN_PARAM(cfn)));
grid.nextLine();
break;
case FUNC_LOGS: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(),
STR_VALUE);
auto edit =
new NumberEdit(specialFunctionOneWindow, grid.getFieldSlot(), 0,
255, GET_SET_DEFAULT(CFN_PARAM(cfn)));
edit->setDisplayHandler(
[=](BitmapBuffer *dc, LcdFlags flags, int32_t value) {
dc->drawNumber(2, 2, CFN_PARAM(cfn), PREC1,
sizeof(CFN_PARAM(cfn)), nullptr, "s");
});
break;
}
}
void buildBody(FormWindow * window)
{
// SF.one
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
CustomFunctionData * cfn = &functions[index];
// Switch
new StaticText(window, grid.getLabelSlot(), STR_SWITCH);
auto switchChoice = new SwitchChoice(window, grid.getFieldSlot(), SWSRC_FIRST, SWSRC_LAST, GET_SET_DEFAULT(CFN_SWITCH(cfn)));
switchChoice->setAvailableHandler([=](int value) {
return (functions == g_model.customFn ? isSwitchAvailable(value, ModelCustomFunctionsContext)
: isSwitchAvailable(value,
GeneralCustomFunctionsContext));
});
if (HAS_ENABLE_PARAM(func)) {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_ENABLE);
new CheckBox(specialFunctionOneWindow, grid.getFieldSlot(),
GET_SET_DEFAULT(CFN_ACTIVE(cfn)));
grid.nextLine();
// Function
new StaticText(window, grid.getLabelSlot(), STR_FUNC);
auto functionChoice = new Choice(window, grid.getFieldSlot(), STR_VFSWFUNC, 0, FUNC_MAX - 1, GET_DEFAULT(CFN_FUNC(cfn)));
functionChoice->setSetValueHandler([=](int32_t newValue) {
CFN_FUNC(cfn) = newValue;
CFN_RESET(cfn);
SET_DIRTY();
updateSpecialFunctionOneWindow();
});
functionChoice->setAvailableHandler([=](int value) {
return isAssignableFunctionAvailable(value, functions);
});
} else if (HAS_REPEAT_PARAM(func)) { // !1x 1x 1s 2s 3s ...
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_REPEAT);
auto repeat = new NumberEdit(
specialFunctionOneWindow, grid.getFieldSlot(2, 1), -1,
60 / CFN_PLAY_REPEAT_MUL, GET_SET_DEFAULT(CFN_PLAY_REPEAT(cfn)));
repeat->setDisplayHandler(
[](BitmapBuffer *dc, LcdFlags flags, int32_t value) {
if (value == 0)
dc->drawText(3, 0, "1x", flags);
else if (value == CFN_PLAY_REPEAT_NOSTART)
dc->drawText(3, 0, "!1x", flags);
else
dc->drawNumber(3, 0, value * CFN_PLAY_REPEAT_MUL, flags, 0,
nullptr, "s");
});
grid.nextLine();
}
specialFunctionOneWindow = new FormGroup(window, {0, grid.getWindowHeight(), LCD_W, 0}, FORM_FORWARD_FOCUS);
specialFunctionOneWindow->adjustHeight();
}
void buildBody(FormWindow *window)
{
// SF.one
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
CustomFunctionData *cfn = &functions[index];
// Switch
new StaticText(window, grid.getLabelSlot(), STR_SWITCH);
auto switchChoice =
new SwitchChoice(window, grid.getFieldSlot(), SWSRC_FIRST, SWSRC_LAST,
GET_SET_DEFAULT(CFN_SWITCH(cfn)));
switchChoice->setAvailableHandler([=](int value) {
return (functions == g_model.customFn
? isSwitchAvailable(value, ModelCustomFunctionsContext)
: isSwitchAvailable(value, GeneralCustomFunctionsContext));
});
grid.nextLine();
// Function
new StaticText(window, grid.getLabelSlot(), STR_FUNC);
auto functionChoice =
new Choice(window, grid.getFieldSlot(), STR_VFSWFUNC, 0, FUNC_MAX - 1,
GET_DEFAULT(CFN_FUNC(cfn)));
functionChoice->setSetValueHandler([=](int32_t newValue) {
CFN_FUNC(cfn) = newValue;
CFN_RESET(cfn);
SET_DIRTY();
updateSpecialFunctionOneWindow();
grid.addWindow(specialFunctionOneWindow);
}
});
functionChoice->setAvailableHandler([=](int value) {
return isAssignableFunctionAvailable(value, functions);
});
grid.nextLine();
specialFunctionOneWindow = new FormGroup(
window, {0, grid.getWindowHeight(), LCD_W, 0}, FORM_FORWARD_FOCUS);
updateSpecialFunctionOneWindow();
grid.addWindow(specialFunctionOneWindow);
}
};
static constexpr coord_t line1 = FIELD_PADDING_TOP;
@@ -261,161 +327,178 @@ static constexpr coord_t col1 = 20;
static constexpr coord_t col2 = (LCD_W - 100) / 3 + col1;
static constexpr coord_t col3 = ((LCD_W - 100) / 3) * 2 + col1 + 20;
class SpecialFunctionButton : public Button {
public:
SpecialFunctionButton(FormWindow * parent, const rect_t &rect, CustomFunctionData * functions, uint8_t index) :
Button(parent, rect),
functions(functions),
index(index)
{
const CustomFunctionData * cfn = &functions[index];
uint8_t func = CFN_FUNC(cfn);
if (!cfn->isEmpty() &&
(HAS_ENABLE_PARAM(func) || HAS_REPEAT_PARAM(func) || (func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC || func == FUNC_PLAY_SCRIPT))) {
setHeight(line2 + PAGE_LINE_HEIGHT);
}
class SpecialFunctionButton : public Button
{
public:
SpecialFunctionButton(FormWindow *parent, const rect_t &rect,
CustomFunctionData *functions, uint8_t index) :
Button(parent, rect), functions(functions), index(index)
{
const CustomFunctionData *cfn = &functions[index];
uint8_t func = CFN_FUNC(cfn);
if (!cfn->isEmpty() &&
(HAS_ENABLE_PARAM(func) || HAS_REPEAT_PARAM(func) ||
(func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC ||
func == FUNC_PLAY_SCRIPT))) {
setHeight(line2 + PAGE_LINE_HEIGHT);
}
}
#if defined(DEBUG_WINDOWS)
std::string getName() const override
{
return "SpecialFunctionButton";
}
std::string getName() const override { return "SpecialFunctionButton"; }
#endif
bool isActive() const
{
return ((functions == g_model.customFn ? modelFunctionsContext.activeSwitches : globalFunctionsContext.activeSwitches) & ((MASK_CFN_TYPE)1 << index) ? 1 : 0);
bool isActive() const
{
return ((functions == g_model.customFn
? modelFunctionsContext.activeSwitches
: globalFunctionsContext.activeSwitches) &
((MASK_CFN_TYPE)1 << index)
? 1
: 0);
}
void checkEvents() override
{
Button::checkEvents();
if (active != isActive()) {
invalidate();
active = !active;
}
}
void checkEvents() override
{
Button::checkEvents();
if (active != isActive()) {
invalidate();
active = !active;
}
void paintSpecialFunctionLine(BitmapBuffer *dc)
{
const CustomFunctionData *cfn = &functions[index];
if (functions[index].func == FUNC_OVERRIDE_CHANNEL &&
functions != g_model.customFn) {
functions[index].func = FUNC_OVERRIDE_CHANNEL + 1;
}
uint8_t func = CFN_FUNC(cfn);
void paintSpecialFunctionLine(BitmapBuffer * dc)
{
const CustomFunctionData * cfn = &functions[index];
if (functions[index].func == FUNC_OVERRIDE_CHANNEL && functions != g_model.customFn) {
functions[index].func = FUNC_OVERRIDE_CHANNEL + 1;
}
uint8_t func = CFN_FUNC(cfn);
drawSwitch(dc, col1, line1, CFN_SWITCH(cfn), 0);
if (cfn->isEmpty()) return;
drawSwitch(dc, col1, line1, CFN_SWITCH(cfn), 0);
if (cfn->isEmpty())
return;
dc->drawTextAtIndex(col2, line1, STR_VFSWFUNC, func, 0);
int16_t val_min = 0;
int16_t val_max = 255;
dc->drawTextAtIndex(col2, line1, STR_VFSWFUNC, func, 0);
int16_t val_min = 0;
int16_t val_max = 255;
switch (func) {
case FUNC_OVERRIDE_CHANNEL:
drawChn(dc, col1, line2, CFN_CH_INDEX(cfn) + 1, 0);
getMixSrcRange(MIXSRC_FIRST_CH, val_min, val_max);
dc->drawNumber(col2, line2, CFN_PARAM(cfn));
break;
switch (func) {
case FUNC_OVERRIDE_CHANNEL:
drawChn(dc, col1, line2, CFN_CH_INDEX(cfn) + 1, 0);
getMixSrcRange(MIXSRC_FIRST_CH, val_min, val_max);
dc->drawNumber(col2, line2, CFN_PARAM(cfn));
break;
case FUNC_TRAINER:
drawSource(
dc, col1, line2,
CFN_CH_INDEX(cfn) == 0 ? 0 : MIXSRC_Rud + CFN_CH_INDEX(cfn) - 1);
break;
case FUNC_TRAINER:
drawSource(dc, col1, line2, CFN_CH_INDEX(cfn) == 0 ? 0 : MIXSRC_Rud + CFN_CH_INDEX(cfn) - 1);
break;
case FUNC_RESET:
if (CFN_PARAM(cfn) < FUNC_RESET_PARAM_FIRST_TELEM) {
dc->drawTextAtIndex(col1, line2, STR_VFSWRESET, CFN_PARAM(cfn));
}
else {
TelemetrySensor * sensor = &g_model.telemetrySensors[CFN_PARAM(cfn) - FUNC_RESET_PARAM_FIRST_TELEM];
dc->drawSizedText(col1, line2, sensor->label, TELEM_LABEL_LEN);
}
break;
case FUNC_VOLUME:
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_BACKLIGHT:
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_PLAY_SOUND:
dc->drawTextAtIndex(col1, line2, STR_FUNCSOUNDS, CFN_PARAM(cfn));
break;
case FUNC_PLAY_TRACK:
case FUNC_BACKGND_MUSIC:
case FUNC_PLAY_SCRIPT:
if (ZEXIST(cfn->play.name))
dc->drawSizedText(col1, line2, cfn->play.name, sizeof(cfn->play.name), 0);
else
dc->drawTextAtIndex(col1, line2, STR_VCSWFUNC, 0, 0);
break;
case FUNC_SET_TIMER:
drawStringWithIndex(dc, col1, line2, STR_TIMER, CFN_TIMER_INDEX(cfn) + 1, 0);
break;
case FUNC_SET_FAILSAFE:
dc->drawTextAtIndex(col1, line2, "\004Int.Ext.", CFN_PARAM(cfn), 0);
break;
case FUNC_PLAY_VALUE:
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_HAPTIC:
dc->drawNumber(col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_LOGS:
dc->drawNumber(col3, line1, CFN_PARAM(cfn), PREC1, sizeof(CFN_PARAM(cfn)), nullptr, "s");
break;
}
if (HAS_ENABLE_PARAM(func)) {
theme->drawCheckBox(dc, CFN_ACTIVE(cfn), col3, line2);
}
else if (HAS_REPEAT_PARAM(func)) {
if (CFN_PLAY_REPEAT(cfn) == 0) {
dc->drawText(col3, line2, "1x", 0);
}
else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) {
dc->drawText(col3, line2, "!1x", 0);
}
else {
dc->drawNumber(col3 + 12, line2, CFN_PLAY_REPEAT(cfn) * CFN_PLAY_REPEAT_MUL, 0 | RIGHT, 0, nullptr, "s");
case FUNC_RESET:
if (CFN_PARAM(cfn) < FUNC_RESET_PARAM_FIRST_TELEM) {
dc->drawTextAtIndex(col1, line2, STR_VFSWRESET, CFN_PARAM(cfn));
} else {
TelemetrySensor *sensor =
&g_model.telemetrySensors[CFN_PARAM(cfn) -
FUNC_RESET_PARAM_FIRST_TELEM];
dc->drawSizedText(col1, line2, sensor->label, TELEM_LABEL_LEN);
}
break;
case FUNC_VOLUME:
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_BACKLIGHT:
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_PLAY_SOUND:
dc->drawTextAtIndex(col1, line2, STR_FUNCSOUNDS, CFN_PARAM(cfn));
break;
case FUNC_PLAY_TRACK:
case FUNC_BACKGND_MUSIC:
case FUNC_PLAY_SCRIPT:
if (ZEXIST(cfn->play.name))
dc->drawSizedText(col1, line2, cfn->play.name, sizeof(cfn->play.name),
0);
else
dc->drawTextAtIndex(col1, line2, STR_VCSWFUNC, 0, 0);
break;
case FUNC_SET_TIMER:
drawStringWithIndex(dc, col1, line2, STR_TIMER,
CFN_TIMER_INDEX(cfn) + 1, 0);
break;
case FUNC_SET_FAILSAFE:
dc->drawTextAtIndex(col1, line2, "\004Int.Ext.", CFN_PARAM(cfn), 0);
break;
case FUNC_PLAY_VALUE:
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_HAPTIC:
dc->drawNumber(col1, line2, CFN_PARAM(cfn), 0);
break;
case FUNC_LOGS:
dc->drawNumber(col3, line1, CFN_PARAM(cfn), PREC1,
sizeof(CFN_PARAM(cfn)), nullptr, "s");
break;
}
if (HAS_ENABLE_PARAM(func)) {
theme->drawCheckBox(dc, CFN_ACTIVE(cfn), col3, line2);
} else if (HAS_REPEAT_PARAM(func)) {
if (CFN_PLAY_REPEAT(cfn) == 0) {
dc->drawText(col3, line2, "1x", 0);
} else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) {
dc->drawText(col3, line2, "!1x", 0);
} else {
dc->drawNumber(col3 + 12, line2,
CFN_PLAY_REPEAT(cfn) * CFN_PLAY_REPEAT_MUL, 0 | RIGHT, 0,
nullptr, "s");
}
}
}
void paint(BitmapBuffer * dc) override
{
if (active)
dc->drawSolidFilledRect(2, 2, rect.w - 4, rect.h - 4, HIGHLIGHT_COLOR);
void paint(BitmapBuffer *dc) override
{
if (active)
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, HIGHLIGHT_COLOR);
else
dc->drawSolidFilledRect(0, 0, rect.w, rect.h, FIELD_BGCOLOR);
paintSpecialFunctionLine(dc);
paintSpecialFunctionLine(dc);
// The bounding rect
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, hasFocus() ? CHECKBOX_COLOR : DISABLE_COLOR);
}
// The bounding rect
if (hasFocus())
dc->drawSolidRect(0, 0, rect.w, rect.h, 2, FOCUS_BGCOLOR);
else
dc->drawSolidRect(0, 0, rect.w, rect.h, 1, FIELD_FRAME_COLOR);
}
protected:
CustomFunctionData * functions;
uint8_t index;
bool active = false;
protected:
CustomFunctionData *functions;
uint8_t index;
bool active = false;
};
SpecialFunctionsPage::SpecialFunctionsPage(CustomFunctionData * functions) :
PageTab(functions == g_model.customFn ? STR_MENUCUSTOMFUNC : STR_MENUSPECIALFUNCS,
functions == g_model.customFn ? ICON_MODEL_SPECIAL_FUNCTIONS : ICON_RADIO_GLOBAL_FUNCTIONS),
functions(functions)
SpecialFunctionsPage::SpecialFunctionsPage(CustomFunctionData *functions) :
PageTab(functions == g_model.customFn ? STR_MENUCUSTOMFUNC
: STR_MENUSPECIALFUNCS,
functions == g_model.customFn ? ICON_MODEL_SPECIAL_FUNCTIONS
: ICON_RADIO_GLOBAL_FUNCTIONS),
functions(functions)
{
}
void SpecialFunctionsPage::rebuild(FormWindow * window, int8_t focusSpecialFunctionIndex)
void SpecialFunctionsPage::rebuild(FormWindow *window,
int8_t focusSpecialFunctionIndex)
{
coord_t scrollPosition = window->getScrollPositionY();
window->clear();
@@ -423,15 +506,14 @@ void SpecialFunctionsPage::rebuild(FormWindow * window, int8_t focusSpecialFunct
window->setScrollPositionY(scrollPosition);
}
void SpecialFunctionsPage::editSpecialFunction(FormWindow * window, uint8_t index)
void SpecialFunctionsPage::editSpecialFunction(FormWindow *window,
uint8_t index)
{
auto editPage = new SpecialFunctionEditPage(functions, index);
editPage->setCloseHandler([=]() {
rebuild(window, index);
});
editPage->setCloseHandler([=]() { rebuild(window, index); });
}
void SpecialFunctionsPage::build(FormWindow * window, int8_t focusIndex)
void SpecialFunctionsPage::build(FormWindow *window, int8_t focusIndex)
{
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
@@ -440,11 +522,10 @@ void SpecialFunctionsPage::build(FormWindow * window, int8_t focusIndex)
Window::clearFocus();
char s[] = "SFxx";
if (functions == g_eeGeneral.customFn)
s[0] = 'G';
if (functions == g_eeGeneral.customFn) s[0] = 'G';
for (uint8_t i = 0; i < MAX_SPECIAL_FUNCTIONS; i++) {
CustomFunctionData * cfn = &functions[i];
CustomFunctionData *cfn = &functions[i];
strAppendUnsigned(&s[2], i);
if (cfn->swtch == 0) {
@@ -464,64 +545,82 @@ void SpecialFunctionsPage::build(FormWindow * window, int8_t focusIndex)
return 0;
});
grid.spacer(button->height() + 5);
}
else {
new StaticText(window, grid.getLabelSlot(), s, BUTTON_BACKGROUND, CENTERED);
} else {
auto txt = new StaticText(window, grid.getLabelSlot(), s,
BUTTON_BACKGROUND, CENTERED);
auto button = new SpecialFunctionButton(window, grid.getFieldSlot(), functions, i);
auto button =
new SpecialFunctionButton(window, grid.getFieldSlot(), functions, i);
button->setPressHandler([=]() {
button->bringToTop();
Menu * menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() {
editSpecialFunction(window, i);
button->bringToTop();
Menu *menu = new Menu(window);
menu->addLine(STR_EDIT, [=]() { editSpecialFunction(window, i); });
menu->addLine(STR_COPY, [=]() {
clipboard.type = CLIPBOARD_TYPE_CUSTOM_FUNCTION;
clipboard.data.cfn = *cfn;
});
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION) {
menu->addLine(STR_PASTE, [=]() {
*cfn = clipboard.data.cfn;
SET_DIRTY();
rebuild(window, i);
});
menu->addLine(STR_COPY, [=]() {
clipboard.type = CLIPBOARD_TYPE_CUSTOM_FUNCTION;
clipboard.data.cfn = *cfn;
}
if (functions[MAX_SPECIAL_FUNCTIONS - 1].isEmpty()) {
menu->addLine(STR_INSERT, [=]() {
memmove(
cfn + 1, cfn,
(MAX_SPECIAL_FUNCTIONS - i - 1) * sizeof(CustomFunctionData));
memset(cfn, 0, sizeof(CustomFunctionData));
SET_DIRTY();
rebuild(window, i);
});
if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION) {
menu->addLine(STR_PASTE, [=]() {
*cfn = clipboard.data.cfn;
SET_DIRTY();
rebuild(window, i);
});
}
if (functions[MAX_SPECIAL_FUNCTIONS - 1].isEmpty()) {
menu->addLine(STR_INSERT, [=]() {
memmove(cfn + 1, cfn, (MAX_SPECIAL_FUNCTIONS - i - 1) * sizeof(CustomFunctionData));
memset(cfn, 0, sizeof(CustomFunctionData));
SET_DIRTY();
rebuild(window, i);
});
}
menu->addLine(STR_CLEAR, [=]() {
memset(cfn, 0, sizeof(CustomFunctionData));
}
menu->addLine(STR_CLEAR, [=]() {
memset(cfn, 0, sizeof(CustomFunctionData));
SET_DIRTY();
});
for (int j = i; j < MAX_SPECIAL_FUNCTIONS; j++) {
if (!functions[j].isEmpty()) {
menu->addLine(STR_DELETE, [=]() {
memmove(
cfn, cfn + 1,
(MAX_SPECIAL_FUNCTIONS - i - 1) * sizeof(CustomFunctionData));
memset(&functions[MAX_SPECIAL_FUNCTIONS - 1], 0,
sizeof(CustomFunctionData));
SET_DIRTY();
});
for (int j = i; j < MAX_SPECIAL_FUNCTIONS; j++) {
if (!functions[j].isEmpty()) {
menu->addLine(STR_DELETE, [=]() {
memmove(cfn, cfn + 1, (MAX_SPECIAL_FUNCTIONS - i - 1) * sizeof(CustomFunctionData));
memset(&functions[MAX_SPECIAL_FUNCTIONS - 1], 0, sizeof(CustomFunctionData));
SET_DIRTY();
rebuild(window, i);
});
break;
}
rebuild(window, i);
});
break;
}
return 0;
}
return 0;
});
button->setFocusHandler([=](bool focus) {
if (focus) {
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
} else {
txt->setBackgroundColor(FIELD_FRAME_COLOR);
txt->setTextFlags(CENTERED);
}
txt->invalidate();
});
if (focusIndex == i) {
button->setFocus(SET_FOCUS_DEFAULT);
txt->setBackgroundColor(FOCUS_BGCOLOR);
txt->setTextFlags(FOCUS_COLOR | CENTERED);
txt->invalidate();
}
txt->setHeight(button->height());
grid.spacer(button->height() + 5);
}
}
grid.nextLine();
// window->setLastField();
// window->setLastField();
window->setInnerHeight(grid.getWindowHeight());
}
@@ -31,11 +31,7 @@ class SpecialFunctionsPage: public PageTab {
void build(FormWindow * window) override
{
#if defined(HARDWARE_TOUCH)
build(window, -1);
#else
build(window, 0);
#endif
}
protected:
+7 -4
View File
@@ -48,12 +48,15 @@ void SwitchChoice::paint(BitmapBuffer * dc)
if (editMode)
textColor = FOCUS_COLOR;
else if (hasFocus())
textColor = FOCUS_BGCOLOR;
else if (value == 0)
textColor = DISABLE_COLOR;
textColor = FOCUS_COLOR;
// else if (value == 0)
// textColor = DISABLE_COLOR;
else
textColor = 0;
textColor = DEFAULT_COLOR;
drawSwitch(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, textColor);
dc->drawBitmapPattern(rect.w - 20, (rect.h - 11) / 2, LBM_DROPDOWN,
textColor);
}
void SwitchChoice::fillMenu(Menu * menu, std::function<bool(int16_t)> filter)
+10 -7
View File
@@ -32,12 +32,12 @@
TabsGroupHeader::TabsGroupHeader(TabsGroup * parent, uint8_t icon):
FormGroup(parent, { 0, 0, LCD_W, MENU_BODY_TOP }, OPAQUE),
#if defined(HARDWARE_TOUCH)
back(this, { 0, 0, MENU_HEADER_BUTTON_WIDTH, MENU_HEADER_BUTTON_WIDTH }, ICON_BACK,
back(this, { 0, 0, MENU_HEADER_BUTTON_WIDTH, MENU_HEADER_BUTTON_WIDTH },
[=]() -> uint8_t {
parent->deleteLater();
ViewMain::instance()->setFocus((SET_FOCUS_DEFAULT));
return 1;
}, NO_FOCUS),
}, NO_FOCUS | FORM_NO_BORDER),
#endif
icon(icon),
carousel(this, parent)
@@ -46,12 +46,15 @@ TabsGroupHeader::TabsGroupHeader(TabsGroup * parent, uint8_t icon):
void TabsGroupHeader::paint(BitmapBuffer * dc)
{
OpenTxTheme::instance()->drawMenuBackground(dc, icon, title);
OpenTxTheme::instance()->drawPageHeaderBackground(dc, icon, title);
}
TabsCarousel::TabsCarousel(Window * parent, TabsGroup * menu):
Window(parent, { MENU_HEADER_BUTTONS_LEFT, 0, LCD_W - MENU_HEADER_BUTTONS_LEFT, MENU_HEADER_HEIGHT + 10 }, TRANSPARENT),
menu(menu)
TabsCarousel::TabsCarousel(Window* parent, TabsGroup* menu) :
Window(parent,
{MENU_HEADER_BUTTONS_LEFT, 0, LCD_W - MENU_HEADER_BUTTONS_LEFT,
MENU_HEADER_HEIGHT + 10},
TRANSPARENT),
menu(menu)
{
}
@@ -62,7 +65,7 @@ void TabsCarousel::updateInnerWidth()
void TabsCarousel::paint(BitmapBuffer * dc)
{
OpenTxTheme::instance()->drawMenuHeader(dc, menu->tabs, currentIndex);
OpenTxTheme::instance()->drawPageHeader(dc, menu->tabs, currentIndex);
}
#if defined(HARDWARE_TOUCH)
+1 -1
View File
@@ -155,7 +155,7 @@ class TabsGroupHeader: public FormGroup {
protected:
#if defined(HARDWARE_TOUCH)
IconButton back;
Button back;
#endif
uint8_t icon;
TabsCarousel carousel;
+34 -33
View File
@@ -166,23 +166,18 @@ void OpenTxTheme::drawBackground(BitmapBuffer * dc) const
// }
//}
void OpenTxTheme::drawCheckBox(BitmapBuffer * dc, bool checked, coord_t x, coord_t y, bool focus) const
void OpenTxTheme::drawCheckBox(BitmapBuffer *dc, bool checked, coord_t x,
coord_t y, bool focus) const
{
dc->drawSolidFilledRect(x, y, 16, 16, FIELD_BGCOLOR);
if (focus) {
dc->drawSolidFilledRect(x + 0, y + 2, 16, 16, FOCUS_BGCOLOR);
if (checked) {
dc->drawSolidFilledRect(x + 2, y + 4, 12, 12, DEFAULT_BGCOLOR);
dc->drawSolidFilledRect(x + 3, y + 5, 10, 10, CHECKBOX_COLOR);
}
else {
dc->drawSolidFilledRect(x + 2, y + 4, 12, 12, DEFAULT_BGCOLOR);
}
dc->drawSolidRect(x, y, 16, 16, 2, FOCUS_BGCOLOR);
}
else {
dc->drawSolidRect(x + 0, y + 2, 16, 16, 1, DISABLE_COLOR);
if (checked) {
dc->drawSolidFilledRect(x + 2, y + 4, 12, 12, CHECKBOX_COLOR);
}
dc->drawSolidRect(x, y, 16, 16, 1, FIELD_FRAME_COLOR);
}
if (checked) {
dc->drawSolidFilledRect(x + 3, y + 3, 10, 10, CHECKBOX_COLOR);
}
}
@@ -192,37 +187,43 @@ void OpenTxTheme::drawChoice(BitmapBuffer * dc, ChoiceBase * choice, const char
if (choice->isEditMode())
textColor = FOCUS_COLOR;
else if (choice->hasFocus())
textColor = FOCUS_BGCOLOR;
else if (!str || str[0] == '\0')
textColor = DISABLE_COLOR;
textColor = FOCUS_COLOR;
// else if (!str || str[0] == '\0')
// textColor = FOCUS_COLOR;
else
textColor = DEFAULT_COLOR;
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, str[0] == '\0' ? "---" : str, textColor);
dc->drawBitmapPattern(choice->getRect().w - 20, (choice->getRect().h - 11) / 2, choice->getType() == CHOICE_TYPE_FOLDER ? LBM_FOLDER : LBM_DROPDOWN, textColor);
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP,
str[0] == '\0' ? "---" : str, textColor);
dc->drawBitmapPattern(
choice->getRect().w - 20, (choice->getRect().h - 11) / 2,
choice->getType() == CHOICE_TYPE_FOLDER ? LBM_FOLDER : LBM_DROPDOWN,
textColor);
}
void OpenTxTheme::drawSlider(BitmapBuffer * dc, int vmin, int vmax, int value, const rect_t & rect, bool edit, bool focus) const
void OpenTxTheme::drawSlider(BitmapBuffer *dc, int vmin, int vmax, int value,
const rect_t &rect, bool edit, bool focus) const
{
int val = limit(vmin, value, vmax);
int w = divRoundClosest((rect.w - 16) * (val - vmin), vmax - vmin);
if (edit) {
dc->drawBitmapPattern(0, 11, LBM_SLIDER_BAR_LEFT, FOCUS_BGCOLOR);
dc->drawSolidFilledRect(4, 11, rect.w - 8, 4, FOCUS_BGCOLOR);
dc->drawBitmapPattern(rect.w - 4, 11, LBM_SLIDER_BAR_RIGHT, FOCUS_BGCOLOR);
}
else {
dc->drawBitmapPattern(0, 11, LBM_SLIDER_BAR_LEFT, LINE_COLOR);
dc->drawSolidFilledRect(4, 11, rect.w - 8, 4, LINE_COLOR);
dc->drawBitmapPattern(rect.w - 4, 11, LBM_SLIDER_BAR_RIGHT, LINE_COLOR);
LcdFlags color = DEFAULT_COLOR;
if (focus) {
color = FOCUS_BGCOLOR;
}
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_OUT, DEFAULT_COLOR);
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_MID, DEFAULT_BGCOLOR);
// if ((options & INVERS) && (!(options & BLINK) || !BLINK_ON_PHASE))
if (focus) {
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_IN, FOCUS_BGCOLOR);
dc->drawBitmapPattern(0, 11, LBM_SLIDER_BAR_LEFT, color);
dc->drawSolidFilledRect(4, 11, rect.w - 8, 4, color);
dc->drawBitmapPattern(rect.w - 4, 11, LBM_SLIDER_BAR_RIGHT, color);
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_OUT, color);
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_MID, FIELD_BGCOLOR);
if (edit) {
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_IN, EDIT_MARKER_COLOR);
} else {
dc->drawBitmapPattern(w, 5, LBM_SLIDER_POINT_IN, FIELD_BGCOLOR);
}
}
+6 -2
View File
@@ -85,9 +85,11 @@ class OpenTxTheme: public Theme
virtual void drawBackground(BitmapBuffer * dc) const;
virtual void drawMenuBackground(BitmapBuffer * dc, uint8_t icon, const char *title) const = 0;
virtual void drawPageHeaderBackground(BitmapBuffer *dc, uint8_t icon,
const char *title) const = 0;
virtual void drawMenuHeader(BitmapBuffer * dc, std::vector<PageTab *> & tabs, uint8_t currentIndex) const = 0;
virtual void drawPageHeader(BitmapBuffer *dc, std::vector<PageTab *> &tabs,
uint8_t currentIndex) const = 0;
// virtual void drawMessageBox(const char * title, const char * text, const
// char * action, uint32_t flags) const override;
@@ -122,4 +124,6 @@ void loadTheme();
std::list<OpenTxTheme *> & getRegisteredThemes();
extern const uint8_t LBM_DROPDOWN[];
#endif // _COLORLCD_THEME_H_
+68 -47
View File
@@ -28,6 +28,16 @@ const ZoneOption OPTIONS_THEME_DEFAULT[] = {
{ nullptr, ZoneOption::Bool }
};
constexpr uint16_t __TEXT_COLOR = RGB(0x0C, 0x3F, 0x66);
constexpr uint16_t __BACKGROUND_COLOR = RGB(0x12, 0x5E, 0x99);
constexpr uint16_t __FOCUS_COLOR = RGB(0x14, 0xA1, 0xE5);
constexpr uint16_t __DATAFIELD_FRAME_COLOR = RGB(0xB6, 0xE0, 0xF2);
constexpr uint16_t __TAB_BACKGROUND_COLOR = RGB(0xE4, 0xEE, 0xF2);
constexpr uint16_t __PARAM_BACKGROUND_COLOR = WHITE;
constexpr uint16_t __EDIT_MARKER_COLOR = RGB(0x00, 0x99, 0x09);
constexpr uint16_t __ACTIVE_MARKER_COLOR = RGB(0xFF, 0xDE, 0x00);
class Theme480: public OpenTxTheme
{
public:
@@ -45,43 +55,45 @@ class Theme480: public OpenTxTheme
lcdColorTable[BARGRAPH2_COLOR_INDEX] = RGB(167, 167, 167);
lcdColorTable[BARGRAPH_BGCOLOR_INDEX] = RGB(222, 222, 222);
lcdColorTable[BATTERY_CHARGE_COLOR_INDEX] = GREEN;
lcdColorTable[CHECKBOX_COLOR_INDEX] = RED;
lcdColorTable[CHECKBOX_COLOR_INDEX] = __FOCUS_COLOR;
lcdColorTable[CURVE_COLOR_INDEX] = RED;
lcdColorTable[CURVE_CURSOR_COLOR_INDEX] = RED;
lcdColorTable[DEFAULT_BGCOLOR_INDEX] = WHITE;
lcdColorTable[DEFAULT_COLOR_INDEX] = BLACK;
lcdColorTable[DEFAULT_BGCOLOR_INDEX] = __TAB_BACKGROUND_COLOR;
lcdColorTable[DEFAULT_COLOR_INDEX] = __TEXT_COLOR;
lcdColorTable[DISABLE_COLOR_INDEX] = LIGHTGREY;
lcdColorTable[FOCUS_BGCOLOR_INDEX] = RED;
lcdColorTable[EDIT_MARKER_COLOR_INDEX] = __EDIT_MARKER_COLOR;
lcdColorTable[FIELD_BGCOLOR_INDEX] = WHITE;
lcdColorTable[FIELD_FRAME_COLOR_INDEX] = __DATAFIELD_FRAME_COLOR;
lcdColorTable[FOCUS_BGCOLOR_INDEX] = __FOCUS_COLOR;
lcdColorTable[FOCUS_COLOR_INDEX] = WHITE;
lcdColorTable[HEADER_COLOR_INDEX] = DARKRED;
lcdColorTable[HEADER_CURRENT_BGCOLOR_INDEX] = RED;
lcdColorTable[HEADER_ICON_BGCOLOR_INDEX] = RED;
lcdColorTable[HIGHLIGHT_COLOR_INDEX] = YELLOW;
lcdColorTable[HEADER_COLOR_INDEX] = __BACKGROUND_COLOR;
lcdColorTable[HEADER_CURRENT_BGCOLOR_INDEX] = __FOCUS_COLOR;
lcdColorTable[HEADER_ICON_BGCOLOR_INDEX] = __BACKGROUND_COLOR;
lcdColorTable[HIGHLIGHT_COLOR_INDEX] = __ACTIVE_MARKER_COLOR;
lcdColorTable[LINE_COLOR_INDEX] = GREY;
lcdColorTable[MAINVIEW_GRAPHICS_COLOR_INDEX] = RED;
lcdColorTable[MAINVIEW_PANES_COLOR_INDEX] = WHITE;
// this is what the status bar uses...
//lcdColorTable[MENU_BGCOLOR_INDEX] = DARKRED;
lcdColorTable[MENU_BGCOLOR_INDEX] = WHITE;
lcdColorTable[MENU_COLOR_INDEX] = __BACKGROUND_COLOR; // Menu font color
// Menu font color
lcdColorTable[MENU_BGCOLOR_INDEX] = DARKRED;//DARKGREY;
lcdColorTable[MENU_COLOR_INDEX] = WHITE;
// Selected item in menu
lcdColorTable[MENU_HIGHLIGHT_BGCOLOR_INDEX] = BLACK;
lcdColorTable[MENU_HIGHLIGHT_BGCOLOR_INDEX] = __FOCUS_COLOR;
lcdColorTable[MENU_HIGHLIGHT_COLOR_INDEX] = WHITE;
lcdColorTable[MENU_LINE_COLOR_INDEX] = __DATAFIELD_FRAME_COLOR;
lcdColorTable[MENU_TITLE_DISABLE_COLOR_INDEX] = RGB(GET_RED(RED)>>1, GET_GREEN(RED)>>1, GET_BLUE(RED)>>1);
lcdColorTable[MENU_TITLE_DISABLE_COLOR_INDEX] = __TEXT_COLOR;
lcdColorTable[OVERLAY_COLOR_INDEX] = BLACK;
lcdColorTable[SCROLLBAR_COLOR_INDEX] = RED;
lcdColorTable[SCROLLBAR_COLOR_INDEX] = __TEXT_COLOR;
lcdColorTable[TEXT_DISABLE_COLOR_INDEX] = GREY;
lcdColorTable[TEXT_STATUSBAR_COLOR_INDEX] = WHITE;
lcdColorTable[TITLE_BGCOLOR_INDEX] = RED;
lcdColorTable[TRIM_BGCOLOR_INDEX] = RED;
lcdColorTable[TITLE_BGCOLOR_INDEX] = __BACKGROUND_COLOR;
lcdColorTable[TRIM_BGCOLOR_INDEX] = __FOCUS_COLOR;
lcdColorTable[TRIM_SHADOW_COLOR_INDEX] = BLACK;
}
void loadMenuIcon(uint8_t index, const uint8_t * lbm, uint32_t color=MENU_COLOR) const
void loadMenuIcon(uint8_t index, const uint8_t * lbm) const
{
BitmapBuffer * mask = BitmapBuffer::load8bitMask(lbm);
if (mask) {
@@ -91,15 +103,15 @@ class Theme480: public OpenTxTheme
delete menuIconNormal[index];
menuIconNormal[index] = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height());
if (menuIconNormal[index]) {
menuIconNormal[index]->clear(MENU_BGCOLOR);
menuIconNormal[index]->drawMask(0, 0, mask, color);
menuIconNormal[index]->clear(HEADER_ICON_BGCOLOR);
menuIconNormal[index]->drawMask(0, 0, mask, FOCUS_COLOR);
}
delete menuIconSelected[index];
menuIconSelected[index] = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height());
if (menuIconSelected[index]) {
menuIconSelected[index]->clear(HEADER_CURRENT_BGCOLOR);
menuIconSelected[index]->drawMask(0, 0, mask, color);
menuIconSelected[index]->drawMask(0, 0, mask, FOCUS_COLOR);
}
}
}
@@ -107,7 +119,7 @@ class Theme480: public OpenTxTheme
void loadIcons() const
{
#if defined(LOG_TELEMETRY) || !defined(WATCHDOG)
loadMenuIcon(ICON_OPENTX, mask_opentx_testmode, DEFAULT_COLOR);
loadMenuIcon(ICON_OPENTX, mask_opentx_testmode);
#else
loadMenuIcon(ICON_OPENTX, mask_edgetx);
#endif
@@ -170,7 +182,7 @@ class Theme480: public OpenTxTheme
currentMenuBackground->drawSolidFilledRect(
0, 0, currentMenuBackground->width(), MENU_HEADER_HEIGHT,
MENU_BGCOLOR);
HEADER_COLOR);
currentMenuBackground->drawSolidFilledRect(
0, MENU_HEADER_HEIGHT, currentMenuBackground->width(),
@@ -185,12 +197,12 @@ class Theme480: public OpenTxTheme
currentMenuBackground->drawMask(0, 0, shadow, TRIM_SHADOW_COLOR);
currentMenuBackground->drawMask(10, 39, dot, MENU_COLOR);
currentMenuBackground->drawMask(10, 39, dot, FOCUS_COLOR);
}
delete topleftBitmap;
topleftBitmap = BitmapBuffer::load8bitMaskOnBackground(
mask_topleft, TITLE_BGCOLOR, HEADER_COLOR);
mask_topleft, HEADER_CURRENT_BGCOLOR, HEADER_COLOR);
delete background;
delete shadow;
@@ -245,41 +257,41 @@ class Theme480: public OpenTxTheme
// Channels monitor screen
delete chanMonLockedBitmap;
chanMonLockedBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_monitor_lockch.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
chanMonLockedBitmap = BitmapBuffer::load8bitMask(mask_monitor_lockch);
delete chanMonInvertedBitmap;
chanMonInvertedBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_monitor_inver.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
chanMonInvertedBitmap = BitmapBuffer::load8bitMask(mask_monitor_inver);
// Mixer setup screen
delete mixerSetupMixerBitmap;
mixerSetupMixerBitmap = BitmapBuffer::loadMaskOnBackground("mask_sbar_mixer.png", MENU_COLOR, MENU_BGCOLOR);
mixerSetupMixerBitmap = BitmapBuffer::load8bitMask(mask_sbar_mixer);
delete mixerSetupToBitmap;
mixerSetupToBitmap = BitmapBuffer::loadMaskOnBackground("mask_sbar_to.png", MENU_COLOR, MENU_BGCOLOR);
mixerSetupToBitmap = BitmapBuffer::load8bitMask(mask_sbar_to);
delete mixerSetupOutputBitmap;
mixerSetupOutputBitmap = BitmapBuffer::loadMaskOnBackground("mask_sbar_output.png", MENU_COLOR, MENU_BGCOLOR);
mixerSetupOutputBitmap = BitmapBuffer::load8bitMask(mask_sbar_output);
delete mixerSetupAddBitmap;
mixerSetupAddBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_mplex_add.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
mixerSetupAddBitmap = BitmapBuffer::load8bitMask(mask_mplex_add);
delete mixerSetupMultiBitmap;
mixerSetupMultiBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_mplex_multi.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
mixerSetupMultiBitmap = BitmapBuffer::load8bitMask(mask_mplex_multi);
delete mixerSetupReplaceBitmap;
mixerSetupReplaceBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_mplex_replace.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
mixerSetupReplaceBitmap = BitmapBuffer::load8bitMask(mask_mplex_replace);
delete mixerSetupLabelIcon;
mixerSetupLabelIcon = BitmapBuffer::loadMask(getFilePath("mask_textline_label.png"));
mixerSetupLabelIcon = BitmapBuffer::load8bitMask(mask_textline_label);
delete mixerSetupCurveIcon;
mixerSetupCurveIcon = BitmapBuffer::loadMask(getFilePath("mask_textline_curve.png"));
mixerSetupCurveIcon = BitmapBuffer::load8bitMask(mask_textline_curve);
delete mixerSetupSwitchIcon;
mixerSetupSwitchIcon = BitmapBuffer::loadMask(getFilePath("mask_textline_switch.png"));
mixerSetupSwitchIcon = BitmapBuffer::load8bitMask(mask_textline_switch);
delete mixerSetupFlightmodeIcon;
mixerSetupFlightmodeIcon = BitmapBuffer::loadMask(getFilePath("mask_textline_fm.png"));
mixerSetupFlightmodeIcon = BitmapBuffer::load8bitMask(mask_textline_fm);
// delete mixerSetupSlowIcon;
// mixerSetupSlowIcon = BitmapBuffer::loadMask(getFilePath("mask_textline_slow.png"));
@@ -347,7 +359,8 @@ class Theme480: public OpenTxTheme
}
}
void drawMenuBackground(BitmapBuffer * dc, uint8_t icon, const char * title) const override
void drawPageHeaderBackground(BitmapBuffer *dc, uint8_t icon,
const char *title) const override
{
if (topleftBitmap) {
dc->drawBitmap(0, 0, topleftBitmap);
@@ -363,10 +376,14 @@ class Theme480: public OpenTxTheme
else
dc->drawBitmap(5, 7, menuIconSelected[icon]);
dc->drawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, MENU_TITLE_TOP - MENU_HEADER_HEIGHT, DEFAULT_BGCOLOR); // the white separation line
dc->drawSolidFilledRect(0, MENU_TITLE_TOP, LCD_W, MENU_TITLE_HEIGHT, TITLE_BGCOLOR); // the title line background
dc->drawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W,
MENU_TITLE_TOP - MENU_HEADER_HEIGHT,
DEFAULT_BGCOLOR); // the white separation line
dc->drawSolidFilledRect(0, MENU_TITLE_TOP, LCD_W, MENU_TITLE_HEIGHT,
TITLE_BGCOLOR); // the title line background
if (title) {
dc->drawText(MENUS_MARGIN_LEFT, MENU_TITLE_TOP + 3, title, MENU_COLOR);
dc->drawText(MENUS_MARGIN_LEFT, MENU_TITLE_TOP + 3, title, FOCUS_COLOR);
}
drawMenuDatetime(dc);
@@ -382,20 +399,24 @@ class Theme480: public OpenTxTheme
return state == STATE_DEFAULT ? menuIconNormal[index] : menuIconSelected[index];
}
void drawMenuHeader(BitmapBuffer * dc, std::vector<PageTab *> & tabs, uint8_t currentIndex) const override
void drawPageHeader(BitmapBuffer *dc, std::vector<PageTab *> &tabs,
uint8_t currentIndex) const override
{
for (unsigned index = 0; index < tabs.size(); index++) {
if (index != currentIndex) {
dc->drawBitmap(index*MENU_HEADER_BUTTON_WIDTH + 2, 7, menuIconNormal[tabs[index]->getIcon()]);
dc->drawBitmap(index * MENU_HEADER_BUTTON_WIDTH + 2, 7,
menuIconNormal[tabs[index]->getIcon()]);
}
}
dc->drawBitmap(currentIndex*MENU_HEADER_BUTTON_WIDTH, 0, currentMenuBackground);
dc->drawBitmap(currentIndex*MENU_HEADER_BUTTON_WIDTH + 2, 7, menuIconSelected[tabs[currentIndex]->getIcon()]);
dc->drawBitmap(currentIndex * MENU_HEADER_BUTTON_WIDTH, 0,
currentMenuBackground);
dc->drawBitmap(currentIndex * MENU_HEADER_BUTTON_WIDTH + 2, 7,
menuIconSelected[tabs[currentIndex]->getIcon()]);
}
void drawMenuDatetime(BitmapBuffer * dc) const
{
dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, FOCUS_COLOR);
//dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, FOCUS_COLOR);
struct gtm t;
gettime(&t);
+37 -26
View File
@@ -348,25 +348,30 @@ class FlyskyTheme: public OpenTxTheme
}
}
void drawMenuBackground(BitmapBuffer * dc, uint8_t icon, const char * title) const override
void drawPageHeaderBackground(BitmapBuffer *dc, uint8_t icon,
const char *title) const override
{
// if (topleftBitmap) {
// dc->drawBitmap(0, 0, topleftBitmap);
// uint16_t width = topleftBitmap->width();
// dc->drawSolidFilledRect(width, 0, LCD_W-width, MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
// }
// else {
dc->drawSolidFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
// }
//
// if (icon == ICON_OPENTX)
// dc->drawBitmap(4, 10, menuIconSelected[ICON_OPENTX]);
// else
// dc->drawBitmap(5, 7, menuIconSelected[icon]);
//
dc->drawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W, MENU_TITLE_TOP - MENU_HEADER_HEIGHT, DEFAULT_BGCOLOR); // the white separation line
dc->drawSolidFilledRect(0, MENU_TITLE_TOP, LCD_W, MENU_TITLE_HEIGHT, TITLE_BGCOLOR); // the title line background
//
// if (topleftBitmap) {
// dc->drawBitmap(0, 0, topleftBitmap);
// uint16_t width = topleftBitmap->width();
// dc->drawSolidFilledRect(width, 0, LCD_W-width,
// MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
// }
// else {
dc->drawSolidFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, HEADER_BGCOLOR);
// }
//
// if (icon == ICON_OPENTX)
// dc->drawBitmap(4, 10, menuIconSelected[ICON_OPENTX]);
// else
// dc->drawBitmap(5, 7, menuIconSelected[icon]);
//
dc->drawSolidFilledRect(0, MENU_HEADER_HEIGHT, LCD_W,
MENU_TITLE_TOP - MENU_HEADER_HEIGHT,
DEFAULT_BGCOLOR); // the white separation line
dc->drawSolidFilledRect(0, MENU_TITLE_TOP, LCD_W, MENU_TITLE_HEIGHT,
TITLE_BGCOLOR); // the title line background
//
if (title) {
dc->drawText(MENUS_MARGIN_LEFT, MENU_TITLE_TOP + 2, title, MENU_COLOR);
}
@@ -382,19 +387,25 @@ class FlyskyTheme: public OpenTxTheme
return state == STATE_DEFAULT ? menuIconNormal[index] : menuIconSelected[index];
}
void drawMenuHeader(BitmapBuffer * dc, std::vector<PageTab *> & tabs, uint8_t currentIndex) const override
void drawPageHeader(BitmapBuffer *dc, std::vector<PageTab *> &tabs,
uint8_t currentIndex) const override
{
uint8_t padding_left = 4;
dc->drawSolidFilledRect(0, 0, 4, MENU_HEADER_BUTTON_WIDTH, HEADER_BGCOLOR);
dc->drawSolidFilledRect(0, 0, 4, MENU_HEADER_BUTTON_WIDTH,
HEADER_BGCOLOR);
for (unsigned i = 0; i < tabs.size(); i++) {
dc->drawBitmap(padding_left + i*MENU_HEADER_BUTTON_WIDTH, 0, theme->getIcon(tabs[i]->getIcon(), currentIndex == i ? STATE_PRESSED : STATE_DEFAULT));
dc->drawBitmap(
padding_left + i * MENU_HEADER_BUTTON_WIDTH, 0,
theme->getIcon(tabs[i]->getIcon(),
currentIndex == i ? STATE_PRESSED : STATE_DEFAULT));
}
// coord_t x = padding_left + MENU_HEADER_BUTTON_WIDTH * tabs.size();
// coord_t w = width() - x;
// if (w > 0) {
// dc->drawSolidFilledRect(x, 0, w, MENU_HEADER_BUTTON_WIDTH, HEADER_BGCOLOR);
// }
// coord_t x = padding_left + MENU_HEADER_BUTTON_WIDTH * tabs.size();
// coord_t w = width() - x;
// if (w > 0) {
// dc->drawSolidFilledRect(x, 0, w, MENU_HEADER_BUTTON_WIDTH,
// HEADER_BGCOLOR);
// }
}
void drawMenuDatetime(BitmapBuffer * dc) const
+4 -2
View File
@@ -36,11 +36,13 @@ void TimeEdit::paint(BitmapBuffer * dc)
if (editMode)
textColor = FOCUS_COLOR;
else if (hasFocus())
textColor = FOCUS_BGCOLOR;
textColor = FOCUS_COLOR;
else
textColor = DEFAULT_COLOR;
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, getTimerString(getValue(), (textFlags & TIMEHOUR) != 0), textColor);
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP,
getTimerString(getValue(), (textFlags & TIMEHOUR) != 0),
textColor);
}
#if defined(HARDWARE_KEYS)
+5 -5
View File
@@ -46,9 +46,9 @@ class ChannelsViewFooter: public Window {
// Draw single legend
coord_t drawChannelsMonitorLegend(BitmapBuffer * dc, coord_t x, const char * s, int color)
{
dc->drawSolidFilledRect(x, 2, LEG_COLORBOX + 2, LEG_COLORBOX + 2, BARGRAPH_BGCOLOR);
dc->drawSolidFilledRect(x + 1, 3, LEG_COLORBOX, LEG_COLORBOX, color);
dc->drawText(x + 20, 2, s, TEXT_STATUSBAR_COLOR);
dc->drawSolidFilledRect(x, 4, LEG_COLORBOX + 2, LEG_COLORBOX + 2, BARGRAPH_BGCOLOR);
dc->drawSolidFilledRect(x + 1, 5, LEG_COLORBOX, LEG_COLORBOX, color);
dc->drawText(x + 20, 4, s, TEXT_STATUSBAR_COLOR);
return x + 25 + getTextWidth(s);
}
@@ -57,8 +57,8 @@ class ChannelsViewFooter: public Window {
// Draw legend bar
coord_t x = 10;
dc->drawSolidFilledRect(0, 0, width(), height(), TITLE_BGCOLOR);
x = drawChannelsMonitorLegend(dc, MENUS_MARGIN_LEFT, STR_MONITOR_OUTPUT_DESC, BARGRAPH1_COLOR);
drawChannelsMonitorLegend(dc, x, STR_MONITOR_MIXER_DESC, BARGRAPH2_COLOR);
x = drawChannelsMonitorLegend(dc, MENUS_MARGIN_LEFT, STR_MONITOR_OUTPUT_DESC, HIGHLIGHT_COLOR);
drawChannelsMonitorLegend(dc, x, STR_MONITOR_MIXER_DESC, FOCUS_BGCOLOR);
}
};
@@ -27,27 +27,30 @@
class LogicalSwitchDisplayButton : public TextButton
{
public:
LogicalSwitchDisplayButton(FormGroup * parent, const rect_t & rect, std::string text, unsigned index):
TextButton(parent, rect, std::move(text)),
index(index)
{
}
LogicalSwitchDisplayButton(FormGroup* parent, const rect_t& rect,
std::string text, unsigned index) :
TextButton(parent, rect, std::move(text), nullptr, OPAQUE), index(index)
{
setBgColorHandler([=]() -> LcdFlags {
if (getSwitch(SWSRC_SW1 + index)) return HIGHLIGHT_COLOR;
return FIELD_BGCOLOR;
});
}
void checkEvents() override
{
bool newvalue = getSwitch(SWSRC_SW1 + index);
if (value != newvalue) {
if (newvalue) {
setTextFlags(FONT(BOLD) | HIGHLIGHT_COLOR);
}
else {
setTextFlags(FONT(STD) | DEFAULT_COLOR);
}
value = newvalue;
invalidate();
}
Button::checkEvents();
}
void checkEvents() override
{
bool newvalue = getSwitch(SWSRC_SW1 + index);
if (value != newvalue) {
if (newvalue) {
setTextFlags(FONT(BOLD) | DEFAULT_COLOR);
} else {
setTextFlags(FONT(STD) | DEFAULT_COLOR);
}
value = newvalue;
invalidate();
}
Button::checkEvents();
}
protected:
unsigned index = 0;
@@ -61,21 +64,28 @@ void LogicalSwitchesViewPage::build(FormWindow * window)
grid.spacer(PAGE_PADDING);
grid.setLabelWidth(8);
// Footer
footer = new LogicalSwitchDisplayFooter(
window, {0, window->height() - LSW_VIEW_FOOTER_HEIGHT, window->width(),
LSW_VIEW_FOOTER_HEIGHT});
// LSW table
std::string lsString ("LS64");
std::string lsString("LS64");
lcdColorTable[CUSTOM_COLOR_INDEX] = RGB(160, 160, 160);
for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) {
strAppendSigned(&lsString[1], i + 1, 2);
auto button = new LogicalSwitchDisplayButton(window, grid.getFieldSlot(8, i % 8), lsString, i);
button->setPressHandler([=]() {
footer->setIndex(i);
footer->invalidate();
auto button = new LogicalSwitchDisplayButton(
window, grid.getFieldSlot(8, i % 8), lsString, i);
button->setFocusHandler([=](bool focus) {
if (focus) {
footer->setIndex(i);
footer->invalidate();
}
return 0;
});
if ((i + 1) % 8 == 0)
grid.nextLine();
if ((i + 1) % 8 == 0) grid.nextLine();
}
// Footer
footer = new LogicalSwitchDisplayFooter(window, {0,window->height() - LSW_VIEW_FOOTER_HEIGHT, window->width(), LSW_VIEW_FOOTER_HEIGHT});
}
+63 -64
View File
@@ -30,77 +30,76 @@ constexpr coord_t CSW_4TH_COLUMN = 280;
constexpr coord_t CSW_5TH_COLUMN = 340;
constexpr coord_t CSW_6TH_COLUMN = 390;
void putsEdgeDelayParam(BitmapBuffer * dc, coord_t x, coord_t y, LogicalSwitchData * ls, LcdFlags flags);
void putsEdgeDelayParam(BitmapBuffer* dc, coord_t x, coord_t y,
LogicalSwitchData* ls, LcdFlags flags);
class LogicalSwitchDisplayFooter: public Window {
public:
explicit LogicalSwitchDisplayFooter(Window * parent, rect_t rect):
Window(parent, rect, OPAQUE),
rect(rect)
{
class LogicalSwitchDisplayFooter : public Window
{
public:
explicit LogicalSwitchDisplayFooter(Window* parent, rect_t rect) :
Window(parent, rect, OPAQUE), rect(rect)
{
}
void setIndex(unsigned value) { index = value; }
void paint(BitmapBuffer* dc) override
{
dc->clear(TITLE_BGCOLOR);
LogicalSwitchData* cs = lswAddress(index);
LcdFlags textColor = FOCUS_COLOR;
dc->drawTextAtIndex(10, 1, STR_VCSWFUNC, cs->func, textColor);
// CSW params
unsigned int cstate = lswFamily(cs->func);
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
drawSwitch(dc, CSW_3RD_COLUMN, 1, cs->v2, textColor);
} else if (cstate == LS_FAMILY_EDGE) {
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
putsEdgeDelayParam(dc, CSW_3RD_COLUMN, 1, cs, textColor);
} else if (cstate == LS_FAMILY_COMP) {
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
drawSource(dc, CSW_3RD_COLUMN, 1, cs->v2, textColor);
} else if (cstate == LS_FAMILY_TIMER) {
dc->drawNumber(CSW_2ND_COLUMN, 1, lswTimerValue(cs->v1),
LEFT | PREC1 | textColor);
dc->drawNumber(CSW_3RD_COLUMN, 1, lswTimerValue(cs->v2),
LEFT | PREC1 | textColor);
} else {
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
drawSourceCustomValue(
dc, CSW_3RD_COLUMN, 1, cs->v1,
cs->v1 <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2,
LEFT | textColor);
}
void setIndex(unsigned value)
{
index = value;
// CSW AND switch
drawSwitch(dc, CSW_4TH_COLUMN, 1, cs->andsw, textColor);
// CSW duration
if (cs->duration > 0)
dc->drawNumber(CSW_5TH_COLUMN, 1, cs->duration,
PREC1 | LEFT | textColor);
else
dc->drawTextAtIndex(CSW_5TH_COLUMN, 1, STR_MMMINV, 0, textColor);
// CSW delay
if (cstate == LS_FAMILY_EDGE) {
dc->drawText(CSW_6TH_COLUMN, 1, STR_NA, textColor);
} else if (cs->delay > 0) {
dc->drawNumber(CSW_6TH_COLUMN, 1, cs->delay, PREC1 | LEFT | textColor);
} else {
dc->drawTextAtIndex(CSW_6TH_COLUMN, 1, STR_MMMINV, 0, textColor);
}
}
void paint(BitmapBuffer * dc) override
{
dc->clear(TITLE_BGCOLOR);
LogicalSwitchData * cs = lswAddress(index);
dc->drawTextAtIndex(10, 1, STR_VCSWFUNC, cs->func, MENU_COLOR);
// CSW params
unsigned int cstate = lswFamily(cs->func);
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
drawSwitch(dc, CSW_3RD_COLUMN, 1, cs->v2, MENU_COLOR);
}
else if (cstate == LS_FAMILY_EDGE) {
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
putsEdgeDelayParam(dc, CSW_3RD_COLUMN, 1, cs, MENU_COLOR);
}
else if (cstate == LS_FAMILY_COMP) {
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
drawSource(dc, CSW_3RD_COLUMN, 1, cs->v2, MENU_COLOR);
}
else if (cstate == LS_FAMILY_TIMER) {
dc->drawNumber(CSW_2ND_COLUMN, 1, lswTimerValue(cs->v1), LEFT | PREC1 | MENU_COLOR);
dc->drawNumber(CSW_3RD_COLUMN, 1, lswTimerValue(cs->v2), LEFT | PREC1 | MENU_COLOR);
}
else {
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
drawSourceCustomValue(dc, CSW_3RD_COLUMN, 1, cs->v1, cs->v1 <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2, LEFT | MENU_COLOR);
}
// CSW AND switch
drawSwitch(dc, CSW_4TH_COLUMN, 1, cs->andsw, MENU_COLOR);
// CSW duration
if (cs->duration > 0)
dc->drawNumber(CSW_5TH_COLUMN, 1, cs->duration, PREC1 | LEFT | MENU_COLOR);
else
dc->drawTextAtIndex(CSW_5TH_COLUMN, 1, STR_MMMINV, 0, MENU_COLOR);
// CSW delay
if (cstate == LS_FAMILY_EDGE) {
dc->drawText(CSW_6TH_COLUMN, 1, STR_NA, MENU_COLOR);
}
else if (cs->delay > 0) {
dc->drawNumber(CSW_6TH_COLUMN, 1, cs->delay, PREC1 | LEFT | MENU_COLOR);
}
else {
dc->drawTextAtIndex(CSW_6TH_COLUMN, 1, STR_MMMINV, 0, MENU_COLOR);
}
}
protected:
rect_t rect;
unsigned index = 0;
protected:
rect_t rect;
unsigned index = 0;
};
class LogicalSwitchesViewPage : public PageTab
{
public:
+1 -1
View File
@@ -53,7 +53,7 @@ class TextWidget: public Widget
const ZoneOption TextWidget::options[] = {
{ STR_TEXT, ZoneOption::String, OPTION_VALUE_STRING(TEXT_WIDGET_DEFAULT_LABEL) },
{ STR_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(RED) },
{ STR_COLOR, ZoneOption::Color, OPTION_VALUE_UNSIGNED(DEFAULT_COLOR>>16) },
{ STR_SIZE, ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(0) },
{ STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false) },
{ nullptr, ZoneOption::Bool }
+2 -2
View File
@@ -29,8 +29,8 @@
#include "sdcard_raw.h"
#endif
#define MODELCELL_WIDTH 172
#define MODELCELL_HEIGHT 59
// #define MODELCELL_WIDTH 172
// #define MODELCELL_HEIGHT 59
// modelXXXXXXX.bin F,FF F,3F,FF\r\n
#define LEN_MODELS_IDX_LINE (LEN_MODEL_FILENAME + sizeof(" F,FF F,3F,FF\r\n")-1)
+3 -3
View File
@@ -106,9 +106,9 @@ constexpr uint32_t PAGE_TITLE_LEFT = 50;
constexpr uint32_t INPUT_EDIT_LABELS_WIDTH = 120;
constexpr coord_t INPUT_EDIT_CURVE_WIDTH = 158;
constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = LCD_H - MENU_HEADER_HEIGHT;
constexpr coord_t INPUT_EDIT_CURVE_LEFT = LCD_W - 158;
constexpr coord_t INPUT_EDIT_CURVE_TOP = MENU_HEADER_HEIGHT;
constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = INPUT_EDIT_CURVE_WIDTH;
constexpr coord_t INPUT_EDIT_CURVE_LEFT = PAGE_PADDING;
constexpr coord_t INPUT_EDIT_CURVE_TOP = MENU_HEADER_HEIGHT + PAGE_PADDING;
constexpr coord_t MENUS_LINE_HEIGHT = 30;
constexpr coord_t MENUS_WIDTH = 200;
constexpr coord_t MENUS_OFFSET_TOP = 20;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB