From db321d2f2a982969e5f29d33dbee7f5c91878832 Mon Sep 17 00:00:00 2001 From: Martin Vladic Date: Mon, 26 Jul 2021 20:48:46 +0200 Subject: [PATCH] gauge widget --- CMakeLists.txt | 1 + src/eez/gui/data.h | 2 +- src/eez/gui/draw.cpp | 135 ++++++++++++++++++++++++++++++++++ src/eez/gui/draw.h | 2 + src/eez/gui/widget.h | 1 + src/eez/gui/widgets/gauge.cpp | 71 ++++++++++++++++++ 6 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/eez/gui/widgets/gauge.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d07269b41..a73317a31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,6 +328,7 @@ set(src_eez_gui_widgets src/eez/gui/widgets/canvas.cpp src/eez/gui/widgets/container.cpp src/eez/gui/widgets/display_data.cpp + src/eez/gui/widgets/gauge.cpp src/eez/gui/widgets/grid.cpp src/eez/gui/widgets/layout_view.cpp src/eez/gui/widgets/list.cpp diff --git a/src/eez/gui/data.h b/src/eez/gui/data.h index 3b6184e9a..18f6ac671 100644 --- a/src/eez/gui/data.h +++ b/src/eez/gui/data.h @@ -485,7 +485,7 @@ struct Value { bool isMega() const; public: - ValueType type_; + uint8_t type_; uint8_t unit_; uint16_t options_; uint32_t reserved_; diff --git a/src/eez/gui/draw.cpp b/src/eez/gui/draw.cpp index 54569cff9..948bb7c13 100644 --- a/src/eez/gui/draw.cpp +++ b/src/eez/gui/draw.cpp @@ -19,6 +19,7 @@ #if OPTION_DISPLAY #include +#define _USE_MATH_DEFINES #include #include @@ -704,6 +705,140 @@ void drawAntialiasedLine(int x0, int y0, int x1, int y1) { } } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int compareInt(const void *a, const void *b) { + return (*(const int *)a) - (*(const int *)b); +} + +int fillPolygon(const int16_t *vx, const int16_t *vy, int n, int *polyInts) { + int result; + int i; + int y, xa, xb; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + + /* + * Vertex array NULL check + */ + if (vx == NULL) { + return (-1); + } + if (vy == NULL) { + return (-1); + } + + /* + * Sanity check number of edges + */ + if (n < 3) { + return -1; + } + + /* + * Determine Y maxima + */ + miny = vy[0]; + maxy = vy[0]; + for (i = 1; (i < n); i++) { + if (vy[i] < miny) { + miny = vy[i]; + } else if (vy[i] > maxy) { + maxy = vy[i]; + } + } + + /* + * Draw, scanning y + */ + result = 0; + for (y = miny; (y <= maxy); y++) { + ints = 0; + for (i = 0; (i < n); i++) { + if (!i) { + ind1 = n - 1; + ind2 = 0; + } else { + ind1 = i - 1; + ind2 = i; + } + y1 = vy[ind1]; + y2 = vy[ind2]; + if (y1 < y2) { + x1 = vx[ind1]; + x2 = vx[ind2]; + } else if (y1 > y2) { + y2 = vy[ind1]; + y1 = vy[ind2]; + x2 = vx[ind1]; + x1 = vx[ind2]; + } else { + continue; + } + if (((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2))) { + polyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); + } + } + + qsort(polyInts, ints, sizeof(int), compareInt); + + /* + * Set color + */ + for (i = 0; (i < ints); i += 2) { + xa = polyInts[i] + 1; + xa = (xa >> 16) + ((xa & 32768) >> 15); + xb = polyInts[i + 1] - 1; + xb = (xb >> 16) + ((xb & 32768) >> 15); + mcu::display::drawHLine(xa, y, xb - xa + 1); + } + } + + return 0; +} + +void arcBarAsPolygon( + int xCenter, + int yCenter, + int radius, + float fromAngleDeg, + float toAngleDeg, + float width, + int16_t *vx, + int16_t *vy, + size_t n +) { + fromAngleDeg *= float(M_PI / 180); + toAngleDeg *= float(M_PI / 180); + + n -= 2; + + for (size_t i = 0; i <= n / 2; i++) { + auto angle = fromAngleDeg + (i / (n / 2.0f)) * (toAngleDeg - fromAngleDeg); + vx[i] = floor(xCenter + (radius + width / 2.0f) * cosf(angle)); + vy[i] = floor(yCenter - (radius + width / 2.0f) * sinf(angle)); + } + + for (size_t i = 0; i <= n / 2; i++) { + auto angle = toAngleDeg + (i / (n / 2.0f)) * (fromAngleDeg - toAngleDeg); + vx[n / 2 + 1 + i] = floor(xCenter + (radius - width / 2.0f) * cosf(angle)); + vy[n / 2 + 1 + i] = floor(yCenter - (radius - width / 2.0f) * sinf(angle)); + } +} + + +void fillArcBar(int xCenter, int yCenter, int radius, float fromAngleDeg, float toAngleDeg, int width) { + static const size_t N = 100; + int16_t vx[N]; + int16_t vy[N]; + int polyInts[N]; + arcBarAsPolygon(xCenter, yCenter, radius, fromAngleDeg, toAngleDeg, width, vx, vy, N); + fillPolygon(vx, vy, N, polyInts); +} + } // namespace gui } // namespace eez diff --git a/src/eez/gui/draw.h b/src/eez/gui/draw.h index df5f2b7bf..fd115accb 100644 --- a/src/eez/gui/draw.h +++ b/src/eez/gui/draw.h @@ -38,5 +38,7 @@ void expandRectWithShadow(int &x1, int &y1, int &x2, int &y2); void drawLine(int x1, int y1, int x2, int y2); void drawAntialiasedLine(int x1, int y1, int x2, int y2); +void fillArcBar(int xCenter, int yCenter, int radius, float fromAngleDeg, float toAngleDeg, int width); + } // namespace gui } // namespace eez diff --git a/src/eez/gui/widget.h b/src/eez/gui/widget.h index d08a28c5a..696d0bc01 100644 --- a/src/eez/gui/widget.h +++ b/src/eez/gui/widget.h @@ -48,6 +48,7 @@ namespace gui { WIDGET_TYPE(SCROLL_BAR, 20) \ WIDGET_TYPE(PROGRESS, 21) \ WIDGET_TYPE(CANVAS, 22) \ + WIDGET_TYPE(GAUGE, 23) \ #define WIDGET_TYPE(NAME, ID) WIDGET_TYPE_##NAME = ID, enum WidgetTypes { diff --git a/src/eez/gui/widgets/gauge.cpp b/src/eez/gui/widgets/gauge.cpp new file mode 100644 index 000000000..bb072e2c3 --- /dev/null +++ b/src/eez/gui/widgets/gauge.cpp @@ -0,0 +1,71 @@ +/* + * EEZ Modular Firmware + * Copyright (C) 2020-present, Envox d.o.o. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#if OPTION_DISPLAY + +#include + +#include + +#include +#include + +namespace eez { +namespace gui { + +EnumFunctionType GAUGE_enum = nullptr; + +DrawFunctionType GAUGE_draw = [](const WidgetCursor &widgetCursor) { + const Widget *widget = widgetCursor.widget; + + widgetCursor.currentState->size = sizeof(WidgetState); + + widgetCursor.currentState->data = get(widgetCursor, widget->data); + + bool refresh = !widgetCursor.previousState || widgetCursor.previousState->data != widgetCursor.currentState->data; + + if (refresh) { + const Style* style = getStyle(widget->style); + + mcu::display::setColor16(RGB_TO_COLOR(255, 0, 0)); + mcu::display::fillRect(widgetCursor.x, widgetCursor.y, widgetCursor.x + widget->w - 1, widgetCursor.y + widget->h - 1, 0); + + mcu::display::setColor16(RGB_TO_COLOR(0, 255, 0)); + + static const int BAR_WIDTH = 20; + float min = 0.0f; + float max = 40.0f; + fillArcBar( + widgetCursor.x + widget->w / 2, + widgetCursor.y + widget->h - 4, + (widget->w - 8) / 2 - BAR_WIDTH / 2, + remap(widgetCursor.currentState->data.getFloat(), min, 180.0f, max, 0.0f), + 180.0f, + BAR_WIDTH + ); + } +}; + +OnTouchFunctionType GAUGE_onTouch = nullptr; + +OnKeyboardFunctionType GAUGE_onKeyboard = nullptr; + +} // namespace gui +} // namespace eez + +#endif