diff --git a/radio/src/gui/colorlcd/file_preview.cpp b/radio/src/gui/colorlcd/file_preview.cpp index eae27f7c1..a907b9f24 100644 --- a/radio/src/gui/colorlcd/file_preview.cpp +++ b/radio/src/gui/colorlcd/file_preview.cpp @@ -22,7 +22,7 @@ #include "file_preview.h" FilePreview::FilePreview(Window *parent, const rect_t &rect) : - StaticBitmap(parent, rect, COLOR_THEME_SECONDARY3) + StaticBitmap(parent, rect) { hide(); } diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index a7714a118..5acf369ff 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -68,18 +68,12 @@ class ModelButton : public Button lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE); - check(modelCell == modelslist.getCurrentModel()); - lv_obj_add_event_cb(lvobj, ModelButton::on_draw, LV_EVENT_DRAW_MAIN_BEGIN, nullptr); } void addDetails() { - int bg_col_idx = modelCell == modelslist.getCurrentModel() - ? COLOR_THEME_ACTIVE_INDEX - : COLOR_THEME_PRIMARY2_INDEX; - coord_t w = width() - PAD_SMALL * 2; LcdFlags font = modelLayouts[layout].font; @@ -93,17 +87,18 @@ class ModelButton : public Button coord_t fh = getFontHeight(font) - ((font == FONT(STD)) ? 4 : (font == FONT(XS)) ? 3 : 1); coord_t fo = (font == FONT(STD)) ? -3 : (font == FONT(XS)) ? -3 : -1; - auto name = new StaticText(this, {PAD_TINY, PAD_TINY, w, fh}, modelCell->modelName, + modelName = new StaticText(this, {PAD_TINY, PAD_TINY, w, fh}, modelCell->modelName, CENTERED | COLOR_THEME_SECONDARY1 | font); - lv_label_set_long_mode(name->getLvObj(), LV_LABEL_LONG_DOT); - etx_bg_color(name->getLvObj(), (LcdColorIndex)bg_col_idx); - etx_obj_add_style(name->getLvObj(), styles->bg_opacity_75, LV_PART_MAIN); - name->padTop(fo); + etx_bg_color(modelName->getLvObj(), COLOR_THEME_ACTIVE_INDEX, LV_STATE_USER_1); + etx_obj_add_style(modelName->getLvObj(), styles->bg_opacity_75, LV_STATE_USER_1); + modelName->padTop(fo); } else { - auto name = new StaticText(this, {PAD_TINY, PAD_SMALL, w, EdgeTxStyles::PAGE_LINE_HEIGHT}, modelCell->modelName, + modelName = new StaticText(this, {PAD_TINY, PAD_SMALL, w, EdgeTxStyles::PAGE_LINE_HEIGHT}, modelCell->modelName, COLOR_THEME_SECONDARY1 | font); - lv_label_set_long_mode(name->getLvObj(), LV_LABEL_LONG_DOT); } + lv_label_set_long_mode(modelName->getLvObj(), LV_LABEL_LONG_DOT); + + checkEvents(); lv_obj_update_layout(lvobj); } @@ -142,7 +137,7 @@ class ModelButton : public Button if (modelLayouts[layout].hasImage) { if (modelCell->modelBitmap[0]) { GET_FILENAME(filename, BITMAPS_PATH, modelCell->modelBitmap, ""); - auto bitmap = new StaticImage(this, {PAD_TINY, PAD_TINY, w, h}, filename, false, true); + auto bitmap = new StaticBitmap(this, {PAD_TINY, PAD_TINY, w, h}, filename); lv_obj_move_background(bitmap->getLvObj()); bitmap->show(bitmap->hasImage()); if (bitmap->hasImage()) { @@ -158,11 +153,15 @@ class ModelButton : public Button return false; } + bool isModel(ModelCell* cell) { return cell == modelCell; } + protected: bool loaded = false; bool imgLoaded = false; uint8_t layout; ModelCell *modelCell; + StaticText* modelName = nullptr; + std::function m_setSelected = nullptr; void showNoImgMsg() @@ -177,6 +176,18 @@ class ModelButton : public Button CENTERED | COLOR_THEME_SECONDARY1 | font); } + void checkEvents() override + { + bool chk = (modelCell == modelslist.getCurrentModel()); + if (chk != checked()) { + check(chk); + if (chk) + lv_obj_add_state(modelName->getLvObj(), LV_STATE_USER_1); + else + lv_obj_clear_state(modelName->getLvObj(), LV_STATE_USER_1); + } + } + void onClicked() override { setFocused(); @@ -197,7 +208,8 @@ class ModelsPageBody : public Window void update() { - clear(); + for (auto b : modelButtons) + b->hide(); ModelsVector models; if (selectedLabels.size()) { @@ -224,9 +236,22 @@ class ModelsPageBody : public Window coord_t y = (n / cols) * (h + PAD_TINY); n += 1; - auto button = new ModelButton( - this, {x, y, w, h}, model, [=]() { focusedModel = model; }, - g_eeGeneral.modelSelectLayout); + ModelButton* button = nullptr; + for (auto b : modelButtons) + if (b->isModel(model)) { + button = b; + break; + } + if (button) { + button->setPos(x, y); + button->show(); + lv_obj_move_foreground(button->getLvObj()); + } else { + button = new ModelButton( + this, {x, y, w, h}, model, [=]() { focusedModel = model; }, + g_eeGeneral.modelSelectLayout); + modelButtons.push_back(button); + } if (!firstButton) firstButton = button; if (model == modelslist.getCurrentModel()) focusedButton = button; @@ -242,7 +267,7 @@ class ModelsPageBody : public Window } else { focusedModel = model; } - return 0; + return model == modelslist.getCurrentModel(); }); // Long Press Handler for Models @@ -262,6 +287,13 @@ class ModelsPageBody : public Window } } + void reload() + { + modelButtons.clear(); + clear(); + update(); + } + void setLabels(LabelsVector labels) { selectedLabels = labels; @@ -288,6 +320,7 @@ class ModelsPageBody : public Window std::string selectedLabel; LabelsVector selectedLabels; ModelCell *focusedModel = nullptr; + std::vector modelButtons; std::function refreshLabels = nullptr; void checkEvents() override @@ -670,7 +703,7 @@ void ModelLabelsWindow::buildHead(Window *hdr) mdlLayout->setLayout(l); g_eeGeneral.modelSelectLayout = l; storageDirty(EE_GENERAL); - mdlselector->update(); + mdlselector->reload(); return 0; }); } diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp b/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp index 49c9947ba..56e192a59 100644 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer.cpp @@ -498,13 +498,15 @@ coord_t BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char *s, // Resize and convert to LVGL image data format with alpha blending to // background color -void BitmapBuffer::resizeToLVGL(coord_t w, coord_t h, LcdFlags bgColor) +void BitmapBuffer::resizeToLVGL(coord_t w, coord_t h) { - // Scale values from ARGB4444 to RGB565 + // Scale values from ARGB4444 to RGB565 with alpha static uint8_t rbcnv[16] = {0, 2, 4, 6, 8, 10, 12, 14, 17, 19, 21, 23, 25, 27, 29, 31}; static uint8_t gcnv[16] = {0, 4, 8, 13, 17, 21, 25, 29, 34, 38, 42, 46, 50, 55, 59, 63}; + static uint8_t alpha[16] = {0, 17, 34, 51, 68, 85, 102, 119, + 136, 153, 170, 187, 204, 221, 238, 255}; float vscale = float(h) / (float)height(); float hscale = float(w) / (float)width(); @@ -520,33 +522,26 @@ void BitmapBuffer::resizeToLVGL(coord_t w, coord_t h, LcdFlags bgColor) scaledh = height() * scale; } - pixel_t *ndata = - (pixel_t *)malloc(align32(scaledw * scaledh * sizeof(pixel_t))); + uint8_t *ndata = + (uint8_t *)malloc(align32(scaledw * scaledh * 3)); if (ndata) { - RGB_SPLIT(COLOR_VAL(bgColor), bgRed, bgGreen, bgBlue); + uint8_t *dst = ndata; for (int i = 0; i < scaledh; i += 1) { - pixel_t *dst = &ndata[i * scaledw]; pixel_t *src = &data[(coord_t)(i / scale) * width()]; for (int j = 0; j < scaledw; j += 1) { ARGB_SPLIT(src[(coord_t)(j / scale)], a, r, g, b); - r = rbcnv[r]; - g = gcnv[g]; - b = rbcnv[b]; - if (a != OPACITY_MAX) { - uint8_t bgWeight = OPACITY_MAX - a; - r = (bgRed * bgWeight + r * a) / OPACITY_MAX; - g = (bgGreen * bgWeight + g * a) / OPACITY_MAX; - b = (bgBlue * bgWeight + b * a) / OPACITY_MAX; - } - *dst++ = RGB_JOIN(r, g, b); + auto c = RGB_JOIN(rbcnv[r], gcnv[g], rbcnv[b]); + *dst++ = c & 0xFF; + *dst++ = c >> 8; + *dst++ = alpha[a]; } } delete data; - data = ndata; + data = (pixel_t*)ndata; _width = scaledw; _height = scaledh; - data_end = data + (scaledw * scaledh); + data_end = data + ((scaledw * scaledh * 3 + 1) / 2); } } diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h index a53f988bf..02182e962 100644 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer.h +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer.h @@ -140,7 +140,7 @@ class BitmapBuffer static BitmapBuffer* loadBitmap(const char* filename, BitmapFormats fmt = BMP_INVALID); - void resizeToLVGL(coord_t w, coord_t h, LcdFlags bgColor); + void resizeToLVGL(coord_t w, coord_t h); uint8_t* to8bitMask(size_t* size) const; diff --git a/radio/src/thirdparty/libopenui/src/bitmapbuffer_fileio.cpp b/radio/src/thirdparty/libopenui/src/bitmapbuffer_fileio.cpp index 878f8d3f4..1122fe2ab 100644 --- a/radio/src/thirdparty/libopenui/src/bitmapbuffer_fileio.cpp +++ b/radio/src/thirdparty/libopenui/src/bitmapbuffer_fileio.cpp @@ -95,8 +95,6 @@ const stbi_io_callbacks stbCallbacks = {stbc_read, stbc_skip, stbc_eof}; BitmapBuffer *BitmapBuffer::loadBitmap(const char *filename, BitmapFormats fmt) { - // TRACE(" BitmapBuffer::load_stb(%s)", filename); - FRESULT result = f_open(&imgFile, filename, FA_OPEN_EXISTING | FA_READ); if (result != FR_OK) { return nullptr; @@ -104,14 +102,7 @@ BitmapBuffer *BitmapBuffer::loadBitmap(const char *filename, BitmapFormats fmt) int x, y, nn; stbi_info_from_callbacks(&stbCallbacks, &imgFile, &x, &y, &nn); - f_close(&imgFile); - // TRACE(" BitmapBuffer::load_stb()----Info File %s, %d, %d, %d", filename, - // x, y, nn); - - result = f_open(&imgFile, filename, FA_OPEN_EXISTING | FA_READ); - if (result != FR_OK) { - return nullptr; - } + f_lseek(&imgFile, 0); int w, h, n; unsigned char *img = diff --git a/radio/src/thirdparty/libopenui/src/static.cpp b/radio/src/thirdparty/libopenui/src/static.cpp index 10640d79d..c1330d0df 100644 --- a/radio/src/thirdparty/libopenui/src/static.cpp +++ b/radio/src/thirdparty/libopenui/src/static.cpp @@ -245,8 +245,8 @@ void StaticImage::setZoom() // Display image from file system with software scaling // - uglier but much faster than LVGL scaling StaticBitmap::StaticBitmap(Window* parent, const rect_t& rect, - LcdFlags bgColor, const char* filename) : - Window(parent, rect), bgColor(bgColor) + const char* filename) : + Window(parent, rect) { setWindowFlag(NO_FOCUS); lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICKABLE); @@ -260,12 +260,12 @@ void StaticBitmap::setSource(const char *filename) if (img) delete img; img = BitmapBuffer::loadBitmap(filename, BMP_ARGB4444); if (img) { - img->resizeToLVGL(width(), height(), bgColor); + img->resizeToLVGL(width(), height()); if (canvas) lv_obj_del(canvas); canvas = lv_canvas_create(lvobj); lv_obj_center(canvas); lv_canvas_set_buffer(canvas, img->getData(), img->width(), img->height(), - LV_IMG_CF_TRUE_COLOR); + LV_IMG_CF_TRUE_COLOR_ALPHA); } } } diff --git a/radio/src/thirdparty/libopenui/src/static.h b/radio/src/thirdparty/libopenui/src/static.h index 4a59ec3e8..3f764aa83 100644 --- a/radio/src/thirdparty/libopenui/src/static.h +++ b/radio/src/thirdparty/libopenui/src/static.h @@ -163,7 +163,7 @@ class StaticBitmap : public Window { public: StaticBitmap(Window *parent, const rect_t &rect, - LcdFlags bgColor, const char *filename = nullptr); + const char *filename = nullptr); ~StaticBitmap(); #if defined(DEBUG_WINDOWS) @@ -174,7 +174,6 @@ class StaticBitmap : public Window bool hasImage() const; protected: - LcdFlags bgColor; lv_obj_t *canvas = nullptr; BitmapBuffer *img = nullptr; };