diff --git a/radio/src/bitmaps/320x240/default_theme/mask_trim.png b/radio/src/bitmaps/320x240/default_theme/mask_trim.png new file mode 100644 index 000000000..f4cef34aa Binary files /dev/null and b/radio/src/bitmaps/320x240/default_theme/mask_trim.png differ diff --git a/radio/src/bitmaps/320x240/default_theme/mask_trim_shadow.png b/radio/src/bitmaps/320x240/default_theme/mask_trim_shadow.png new file mode 100644 index 000000000..d8ccaa0c8 Binary files /dev/null and b/radio/src/bitmaps/320x240/default_theme/mask_trim_shadow.png differ diff --git a/radio/src/bitmaps/480x272/default_theme/mask_trim.png b/radio/src/bitmaps/480x272/default_theme/mask_trim.png new file mode 100644 index 000000000..a12a15c55 Binary files /dev/null and b/radio/src/bitmaps/480x272/default_theme/mask_trim.png differ diff --git a/radio/src/bitmaps/480x272/default_theme/mask_trim_shadow.png b/radio/src/bitmaps/480x272/default_theme/mask_trim_shadow.png new file mode 100644 index 000000000..e6310dfc4 Binary files /dev/null and b/radio/src/bitmaps/480x272/default_theme/mask_trim_shadow.png differ diff --git a/radio/src/bitmaps/800x480/default_theme/mask_trim.png b/radio/src/bitmaps/800x480/default_theme/mask_trim.png new file mode 100644 index 000000000..c64b9bbd5 Binary files /dev/null and b/radio/src/bitmaps/800x480/default_theme/mask_trim.png differ diff --git a/radio/src/bitmaps/800x480/default_theme/mask_trim_shadow.png b/radio/src/bitmaps/800x480/default_theme/mask_trim_shadow.png new file mode 100644 index 000000000..9193c3dae Binary files /dev/null and b/radio/src/bitmaps/800x480/default_theme/mask_trim_shadow.png differ diff --git a/radio/src/gui/colorlcd/bitmaps.cpp b/radio/src/gui/colorlcd/bitmaps.cpp index a2a0bb3da..effdfd3c7 100644 --- a/radio/src/gui/colorlcd/bitmaps.cpp +++ b/radio/src/gui/colorlcd/bitmaps.cpp @@ -360,6 +360,13 @@ static const uint8_t mask_model_list_two[] = { #include "mask_model_list_two.lbm" }; +static const uint8_t mask_trim[] = { +#include "mask_trim.lbm" +}; +static const uint8_t mask_trim_shadow[] = { +#include "mask_trim_shadow.lbm" +}; + struct _BuiltinIcon { const uint8_t* lz4_compressed_bitmap; }; @@ -478,6 +485,9 @@ static const _BuiltinIcon _builtinIcons[EDGETX_ICONS_COUNT] = { BI(ICON_MODEL_GRID_SMALL, mask_model_grid_small), BI(ICON_MODEL_LIST_TWO, mask_model_list_two), BI(ICON_MODEL_LIST_ONE, mask_model_list_one), + + BI(ICON_TRIM, mask_trim), + BI(ICON_TRIM_SHADOW, mask_trim_shadow), }; static MaskBitmap* _builtinIconsDecompressed[EDGETX_ICONS_COUNT] = {0}; diff --git a/radio/src/gui/colorlcd/bitmaps.h b/radio/src/gui/colorlcd/bitmaps.h index dc556bdd8..959596669 100644 --- a/radio/src/gui/colorlcd/bitmaps.h +++ b/radio/src/gui/colorlcd/bitmaps.h @@ -133,6 +133,9 @@ enum EdgeTxIcon { ICON_MODEL_LIST_TWO, ICON_MODEL_LIST_ONE, + ICON_TRIM, + ICON_TRIM_SHADOW, + EDGETX_ICONS_COUNT }; diff --git a/radio/src/gui/colorlcd/mainview/sliders.cpp b/radio/src/gui/colorlcd/mainview/sliders.cpp index 4359b333f..b8d36c24e 100644 --- a/radio/src/gui/colorlcd/mainview/sliders.cpp +++ b/radio/src/gui/colorlcd/mainview/sliders.cpp @@ -26,86 +26,41 @@ #include "edgetx.h" #include "switches.h" -static const lv_style_const_prop_t shadow1_props[] = { - // LV_STYLE_CONST_SHADOW_COLOR does not compile in GitHub ??? - {.prop = LV_STYLE_SHADOW_COLOR, .value = {.color = {.full = 0}}}, - LV_STYLE_CONST_SHADOW_OPA(LV_OPA_20), - LV_STYLE_CONST_SHADOW_OFS_X(1), - LV_STYLE_CONST_SHADOW_OFS_Y(1), - LV_STYLE_CONST_SHADOW_WIDTH(1), - LV_STYLE_PROP_INV, -}; -static LV_STYLE_CONST_MULTI_INIT(shadow1_style, shadow1_props); - -static const lv_style_const_prop_t shadow2_props[] = { - // LV_STYLE_CONST_SHADOW_COLOR does not compile in GitHub ??? - {.prop = LV_STYLE_SHADOW_COLOR, .value = {.color = {.full = 0}}}, - LV_STYLE_CONST_SHADOW_OPA(LV_OPA_40), - LV_STYLE_CONST_SHADOW_OFS_X(1), - LV_STYLE_CONST_SHADOW_OFS_Y(1), - LV_STYLE_CONST_SHADOW_WIDTH(1), - LV_STYLE_PROP_INV, -}; -static LV_STYLE_CONST_MULTI_INIT(shadow2_style, shadow2_props); - SliderIcon::SliderIcon(Window* parent) : - Window(parent, rect_t{0, 0, MainViewSlider::SLIDER_ICON_SIZE + 2, MainViewSlider::SLIDER_ICON_SIZE + 2}) + Window(parent, rect_t{0, 0, MainViewSlider::SLIDER_BAR_SIZE, MainViewSlider::SLIDER_BAR_SIZE}) { setWindowFlag(NO_FOCUS); - auto shad = lv_obj_create(lvobj); - etx_obj_add_style(shad, shadow1_style, LV_PART_MAIN); - lv_obj_set_pos(shad, 1, 1); - lv_obj_set_size(shad, MainViewSlider::SLIDER_ICON_SIZE, MainViewSlider::SLIDER_ICON_SIZE); + auto icon = getBuiltinIcon(ICON_TRIM_SHADOW); + shadow = lv_canvas_create(lvobj); + lv_canvas_set_buffer(shadow, (void*)icon->data, icon->width, icon->height, LV_IMG_CF_ALPHA_8BIT); + etx_img_color(shadow, COLOR_THEME_PRIMARY1_INDEX); - fill = lv_obj_create(lvobj); - etx_obj_add_style(fill, shadow2_style, LV_PART_MAIN); - lv_obj_set_pos(fill, 0, 0); - lv_obj_set_size(fill, MainViewSlider::SLIDER_ICON_SIZE, MainViewSlider::SLIDER_ICON_SIZE); - etx_solid_bg(fill, COLOR_THEME_FOCUS_INDEX); + icon = getBuiltinIcon(ICON_TRIM); + mask = lv_canvas_create(lvobj); + lv_canvas_set_buffer(mask, (void*)icon->data, icon->width, icon->height, LV_IMG_CF_ALPHA_8BIT); + etx_img_color(mask, COLOR_THEME_FOCUS_INDEX); } +std::vector MainViewSlider::tickMasks; + MainViewSlider::MainViewSlider(Window* parent, const rect_t& rect, uint8_t idx, bool isVertical) : Window(parent, rect), isVertical(isVertical) { potIdx = adcGetInputOffset(ADC_INPUT_FLEX) + idx; - if (isVertical) { - int sliderTicksCount = (height() - SLIDER_BAR_SIZE) / SLIDER_TICK_SPACING; - tickPoints = new lv_point_t[(sliderTicksCount + 1) * 2]; + auto mask = getTicksMask(); - lv_coord_t y = SLIDER_BAR_SIZE / 2; - for (uint8_t i = 0; i <= sliderTicksCount; i++) { - if (i == 0 || i == sliderTicksCount / 2 || i == sliderTicksCount) { - tickPoints[i * 2] = {PAD_TINY, y}; - tickPoints[i * 2 + 1] = {SLIDER_ICON_SIZE, y}; - } else { - tickPoints[i * 2] = {PAD_TINY + 2, y}; - tickPoints[i * 2 + 1] = {SLIDER_ICON_SIZE - 2, y}; - } - auto line = lv_line_create(lvobj); - etx_obj_add_style(line, styles->div_line, LV_PART_MAIN); - lv_line_set_points(line, &tickPoints[i * 2], 2); - y += SLIDER_TICK_SPACING; - } - } else { - int sliderTicksCount = (width() - SLIDER_BAR_SIZE) / SLIDER_TICK_SPACING; - tickPoints = new lv_point_t[(sliderTicksCount + 1) * 2]; + if (mask) { + maskCanvas = lv_canvas_create(lvobj); + etx_img_color(maskCanvas, COLOR_THEME_SECONDARY1_INDEX); + lv_canvas_set_buffer(maskCanvas, mask->data, mask->width, mask->height, LV_IMG_CF_ALPHA_8BIT); - lv_coord_t x = SLIDER_BAR_SIZE / 2; - for (uint8_t i = 0; i <= sliderTicksCount; i++) { - if (i == 0 || i == sliderTicksCount / 2 || i == sliderTicksCount) { - tickPoints[i * 2] = {x, PAD_TINY}; - tickPoints[i * 2 + 1] = {x, SLIDER_ICON_SIZE}; - } else { - tickPoints[i * 2] = {x, PAD_TINY + 2}; - tickPoints[i * 2 + 1] = {x, SLIDER_ICON_SIZE - 2}; - } - auto line = lv_line_create(lvobj); - etx_obj_add_style(line, styles->div_line, LV_PART_MAIN); - lv_line_set_points(line, &tickPoints[i * 2], 2); - x += SLIDER_TICK_SPACING; + if (isVertical) { + lv_obj_set_pos(maskCanvas, PAD_TINY, SLIDER_BAR_SIZE / 2); + } else { + lv_obj_set_pos(maskCanvas, SLIDER_BAR_SIZE / 2, PAD_TINY); } } @@ -114,12 +69,73 @@ MainViewSlider::MainViewSlider(Window* parent, const rect_t& rect, uint8_t idx, setPos(); } -void MainViewSlider::deleteLater(bool detach, bool trash) +MaskBitmap* MainViewSlider::getTicksMask() { - if (!deleted()) { - if (tickPoints) delete tickPoints; - Window::deleteLater(detach, trash); + coord_t l, x, y, w, h; + + // Mask size + if (isVertical) { + h = height() - SLIDER_BAR_SIZE + 1; + if ((h & 1) == 0) h += 1; + w = MASK_SHORT_DIM; + } else { + w = width() - SLIDER_BAR_SIZE + 1; + if ((w & 1) == 0) w += 1; + h = MASK_SHORT_DIM; } + + for (auto mask : tickMasks) { + // TRACE("Found Mask %d %d",w,h); + if (mask->width == w && mask->height == h) return mask; + } + + MaskBitmap* mask =(MaskBitmap*)malloc(w * h + sizeof(uint16_t) * 2); + if (!mask) { + TRACE("Could not create Slider mask"); + return nullptr; + } + + mask->width = w; + mask->height = h; + memset(mask->data, 0, w * h); + + if (isVertical) { + // Create vertical mask for tick lines + int sliderTicksCount = h / SLIDER_TICK_SPACING; + y = 0; + for (uint8_t i = 0; i <= sliderTicksCount; i++) { + if (i == 0 || i == sliderTicksCount / 2 || i == sliderTicksCount) { + x = 0; + l = w; + } else { + x = PAD_TINY; + l = w - PAD_TINY * 2; + } + memset(&mask->data[y * w + x], 0xFF, l); + y += SLIDER_TICK_SPACING; + } + } else { + // Create horizontal mask for tick lines + int sliderTicksCount = w / SLIDER_TICK_SPACING; + x = 0; + for (uint8_t i = 0; i <= sliderTicksCount; i++) { + if (i == 0 || i == sliderTicksCount / 2 || i == sliderTicksCount) { + y = 0; + l = h; + } else { + y = PAD_TINY; + l = h - PAD_TINY * 2; + } + for (uint8_t n = y; n < y + l; n += 1) + mask->data[n * w + x] = 0xFF; + x += SLIDER_TICK_SPACING; + } + } + + // TRACE("Created Mask %d %d",w,h); + tickMasks.emplace_back(mask); + + return mask; } void MainViewSlider::setPos() diff --git a/radio/src/gui/colorlcd/mainview/sliders.h b/radio/src/gui/colorlcd/mainview/sliders.h index c80b339ac..4274a8c81 100644 --- a/radio/src/gui/colorlcd/mainview/sliders.h +++ b/radio/src/gui/colorlcd/mainview/sliders.h @@ -23,6 +23,9 @@ #include "dataconstants.h" #include "window.h" +#include + +class MaskBitmap; class SliderIcon : public Window { @@ -30,7 +33,8 @@ class SliderIcon : public Window SliderIcon(Window* parent); protected: - lv_obj_t* fill = nullptr; + lv_obj_t* mask = nullptr; + lv_obj_t* shadow = nullptr; }; class MainViewSlider : public Window @@ -49,19 +53,22 @@ class MainViewSlider : public Window static LAYOUT_VAL_SCALED(SLIDER_TICK_SPACING, 4) static constexpr coord_t HORIZONTAL_SLIDERS_WIDTH = SLIDER_SIZE + SLIDER_BAR_SIZE; static constexpr coord_t VERTICAL_SLIDERS_HEIGHT = SLIDER_SIZE + SLIDER_BAR_SIZE; + static constexpr coord_t MASK_SHORT_DIM = SLIDER_ICON_SIZE - PAD_TINY; + static constexpr coord_t MASK_LONG_DIM = SLIDER_SIZE + 1; protected: uint8_t potIdx; int16_t value = 0; bool isVertical; + lv_obj_t* maskCanvas = nullptr; SliderIcon* sliderIcon = nullptr; - lv_point_t* tickPoints = nullptr; + static std::vector tickMasks; void setPos(); void checkEvents() override; - void deleteLater(bool detach = true, bool trash = true) override; + MaskBitmap* getTicksMask(); }; class MainViewHorizontalSlider : public MainViewSlider diff --git a/radio/src/gui/colorlcd/mainview/trims.cpp b/radio/src/gui/colorlcd/mainview/trims.cpp index b2edde6e2..19854b6f4 100644 --- a/radio/src/gui/colorlcd/mainview/trims.cpp +++ b/radio/src/gui/colorlcd/mainview/trims.cpp @@ -60,17 +60,17 @@ class TrimIcon : public SliderIcon lv_obj_set_style_line_width(bar2, lw, LV_PART_MAIN); lv_line_set_points(bar2, &barPoints[2], 2); - etx_bg_color(fill, COLOR_THEME_ACTIVE_INDEX, LV_STATE_USER_1); + etx_img_color(mask, COLOR_THEME_ACTIVE_INDEX, LV_STATE_USER_1); } void setState(int value) { if (value < TRIM_MIN || value > TRIM_MAX) { - lv_obj_add_state(fill, LV_STATE_USER_1); + lv_obj_add_state(mask, LV_STATE_USER_1); lv_obj_add_state(bar1, LV_STATE_USER_1); lv_obj_add_state(bar2, LV_STATE_USER_1); } else { - lv_obj_clear_state(fill, LV_STATE_USER_1); + lv_obj_clear_state(mask, LV_STATE_USER_1); lv_obj_clear_state(bar1, LV_STATE_USER_1); lv_obj_clear_state(bar2, LV_STATE_USER_1); }