From 63bb205e6b9788e2b84345b166ec7a37c71777cd Mon Sep 17 00:00:00 2001 From: philmoz Date: Fri, 26 Jan 2024 21:48:09 +1100 Subject: [PATCH] feat(color): Add alternate layouts for model list in Manage Models page (#4524) --- .../default_theme/mask_model_grid_large.png | Bin 0 -> 2117 bytes .../default_theme/mask_model_grid_small.png | Bin 0 -> 2070 bytes .../default_theme/mask_model_list_one.png | Bin 0 -> 1839 bytes .../default_theme/mask_model_list_two.png | Bin 0 -> 1986 bytes radio/src/datastructs_private.h | 23 +-- radio/src/gui/colorlcd/bitmaps.cpp | 16 ++ radio/src/gui/colorlcd/menus.h | 4 + radio/src/gui/colorlcd/model_select.cpp | 180 +++++++++++++----- radio/src/gui/colorlcd/model_select.h | 2 + radio/src/storage/modelslist.cpp | 2 +- .../storage/yaml/yaml_datastructs_nv14.cpp | 1 + .../storage/yaml/yaml_datastructs_pl18.cpp | 1 + .../src/storage/yaml/yaml_datastructs_x10.cpp | 1 + .../storage/yaml/yaml_datastructs_x12s.cpp | 1 + 14 files changed, 173 insertions(+), 58 deletions(-) create mode 100644 radio/src/bitmaps/480x272/default_theme/mask_model_grid_large.png create mode 100644 radio/src/bitmaps/480x272/default_theme/mask_model_grid_small.png create mode 100644 radio/src/bitmaps/480x272/default_theme/mask_model_list_one.png create mode 100644 radio/src/bitmaps/480x272/default_theme/mask_model_list_two.png diff --git a/radio/src/bitmaps/480x272/default_theme/mask_model_grid_large.png b/radio/src/bitmaps/480x272/default_theme/mask_model_grid_large.png new file mode 100644 index 0000000000000000000000000000000000000000..862f7676929fef11db9da66956ef6e3cb19ca31d GIT binary patch literal 2117 zcmb_deQXnD7(W!|HZl_x86TOu+@cQkdf#pDLV>bwu1M!LI^9&nw|8&bllJboyKdb` zR6Y&55F*Lcx#&V7vc)VC`2+dLoSR56Dh8EA11O3@GP1>Gm}mmN*R>6hfrQxf?%sRv z_xzsc_dL)0zT4{S9xo|gP>f+%Nw7B1h@K0atFQpw`&O*{8a;}P+7=7LX5Z&rGqCQS zc^Fo(Qw=xU&7qZ&tS4PS(Ie26P8tY}VT+fh4Irwvnp~70cgplYS^l-;SM8+ z=qcMrplGLLB#k_+W@S@_l18P0K`}1ck(B`|avo=-%tXeyB2zE{lTfoQgk|zrBd*)J z71wV-o&S7|1C-uSDDPw1Sdz)S3(Kxn5HAlpvt4v@3*w9Cyy745)qarDKI4>FHJ%SM76_Mv*&OV^a zDW|qMdj;7?-EPJc;XNcB5fF*M$)uN21Tre{&@0j`6XnF5{gbAO))z?JHjlIFoTiX! zRST7?J-a4W!FAbDLd7$EAOYFwZyzB$g@p={omQvGz^y5mqHT*qM0%5QPr)obYPSIs z`eP_tx6n}3jl#D;>&=5#1TPR2ULX}3C7oy7JP8!qOEQ3^IZ@#Rpzt~I*99*+y-Ew{ zpKHL|3qG4#IS#ZKM4Ki>+`gP!>&EG7G0l4VKjl!)PC3 z;RDqp$;eROj)5mmgjdg@j`uDsJ+g*vOl&>04`1!2>CUm2%ePOwRKD;?Ll*=sKMe6- zoqYC0YW3;VDYdzC-Pn2W-EUsl@o|5DY=m7lPaZzpS9$D{v43io9hrRiQss{a24=e( z*HjL@6?|iKX65!@%bH?8UD|Nrz~#F8H-r79_=kN5w(Z?;dFfHQ)6PaNyQ=QDn$cPNzdiFQ|GcrsIp~Acb%BB9FKql5SQy5B literal 0 HcmV?d00001 diff --git a/radio/src/bitmaps/480x272/default_theme/mask_model_grid_small.png b/radio/src/bitmaps/480x272/default_theme/mask_model_grid_small.png new file mode 100644 index 0000000000000000000000000000000000000000..b07da8fa8bf102597ccdd29cb4969255182a2e57 GIT binary patch literal 2070 zcmb_dTWB0r7@n%oq$R;tks3v(6EBfEJ7;b?GskRdvb%Pdx-q0nyILP|_RQJcAv+gm zCfQApqIs(Z5v^cDLw)I!#NvY}D)=B&`Xb_kC_=0FkOvX1A`Rk$XZA8SWgA0qU}nzD zeCPka@4w7{dTR2>z@DK!48siMbD3#+ABxVt+vxR?k?+saTfdikHei^&cSYweX64)g zhS@!A6-!~M@HE7(oj|5rCW)r)Q8dGh9&UOF&ytWWld9#UxL-f{jAJb`#hp+Kpx~uR z&B`tMSwv-bE=+Nh zZCi%z#b%wL6Dk@sp@}>}On^vM3uxjP=gs-`mU9yeq)u$&gaO5hG1jZOp&QiPTbPbN zZ*oAxTPVandUCPt*hLU#=c$ZNKzgEs;(|wnX%e_|J|@|DN^>|;vQT+^y7Y=(-U zNO3@flClX(3&%tu`cJTlVa4@rL?v4`suIC-svH{!5~kg{>r=;+o!nwkD8RfEgvh}p zpGk34b;7btsEK7w*EO9-x}oz5s%X5SmNgz@Op-DtvZ}}XGcKNsa@*Z+(*2cWQq;r|#Vb{tyRTR+V1)UC=K-JEw zZjD7Uw@Y(Wh}wZ}V%w{>Az^Eets;dvD`K$F@q3KC5Hny~bqNuU`YpxbsL+VXbzWON zGP1phw#_zbgc{wV{MxX z^S}Vfiik|TY^q)HH<34r5`Z8HC8^sGJ0sr-Ev_M_O6X5q;C3!&d)?717d`s>|CG}z z)pnf;H{Vv)x2pH*^30F>xxpU>xo`E?*6_$jOQq7=M}Iq4mG-Ild2Enpruse{~?d-Z=Niy(1UC`tHe@wbhreKd?G*$Jz%! ze|+lVnXjKa1n=v6{m(0S`O<;)=lgb@zdCe$-}1@bkN))LwaXjki_(?L8~vx=5x)HV S!_yB(lRKZC%)B=-v-A%d43zo+ literal 0 HcmV?d00001 diff --git a/radio/src/bitmaps/480x272/default_theme/mask_model_list_one.png b/radio/src/bitmaps/480x272/default_theme/mask_model_list_one.png new file mode 100644 index 0000000000000000000000000000000000000000..040b022705960df9e7b7a9d210313776d780ef5a GIT binary patch literal 1839 zcmb_dzmMER6gCtQ1g=U0M`Jl6Is&uy_~&{QC%WCeWEbJf>9UA}it%{7Yu(!8*uLAn zD?mYM=#Z#DNRWR3Au6Ouxt@XwL4l$ahz{jS3L2jGhm}K{a5`bh_IUig@4fH6H#47Z zZQfWpzj|Jhq?KN`vkmXn>VDyQcwSoj?F)Fln04PTBoWkP@;;U$$P$tW$z#8alc1jg00s>oAFx$7zGl|y;Q-;&!R=d#W3zo-O8H-e|7-=B(N>71kXEKtkrcH}^svv3V zgk~ykXqBufFl03@+sj8&=OI)1h$lQP3&7$Un+-)NilKN4b^ZH<14ys$*FKiUk|ec@ zqTJXA8S{iJMHl^pjH}zc5PLb}8~YIE#Y#;^+Bv7C$ooQ!7RB0Hge>b;!;sf}%Hp&V z@x~J-yhBUwDNr{PX&7nEzK)5m6U%%PW1?v@s4v1eIyec%S|7Va!vy0KP-vWxmh?Zt zAtRB<6AF^!gbuixr2|E-6G_@)Byw;J(HYYye4q5vqNFL~y^g1V>P8%gB+?wmvI7SN zCTk+ov|QB0Zh)L9WHvLRP}kjseMhjpsZ+z7-MD~q9n9CnEq;4G8pZOo4+v#de|rk63d=)fJ{>Q~ z!08msXvaeiq|Ye#3|5G!9Mhby4?W Zy1V+*ufKf%!NclE>uqdyzHNQ@$v?hVKnnl> literal 0 HcmV?d00001 diff --git a/radio/src/bitmaps/480x272/default_theme/mask_model_list_two.png b/radio/src/bitmaps/480x272/default_theme/mask_model_list_two.png new file mode 100644 index 0000000000000000000000000000000000000000..c483cd718707117d4fdcf53ebff3b39884f857d8 GIT binary patch literal 1986 zcmb_d&u`pB6m~0qG%YzGF0?1hkx&qs^^DhRuSapKBpbSma9E`)kxD&uJRa{_S$mA_ zWH-4~aH+V!6%Yq*+&J{WfgXSp5*#Wa<;33rTsbo1U7M!bhA8T4ZIA75-uu4y!|&7n z&h6!^H?As*vfS%-cE$CEJg!_8=eJh>_)=V!((c_{QLeoqk4wr|U%#m+udYOcy<*RM zA5$JTNWgv8n8v9T0E3EY|X|uBj!Y*mt!J=}_JC`sxyXFrYOqJ;=tT^MLAX%wm=lxxk_tn~r$F^AUfJ>H7642O_+lSNmAVC5~$s zd9i&cWXuDy5SQl{^+oF8PAZ66AnD^g90w=zZwo((u3SIO#ElvShEXsW9op;015 zy#3S`)*%IRHIX+HKm=fWU?6N5xMjYB5QcCD^>`44N2j3(4v>SP1f7D4!U;%0{udlj z9P%tCLUI(7A=A@jsHt@z@fIKROgI+onk5U*!@VRgNJ3e!<7z^6BZ>lSBFjd^@`3Lo z224f}XooEVLdyJrSuF?+r`q4)^g!me+8@aMO&?l;6$0B2EMQtr2proaz+tRyx1obf z(yI1nO+^U_?`WjlyX>TESLq@V4v zEK=N!B!i>5-#hH1nt@u@B_>q%o2yY-Xe`j?kE2ByIafqyW+x*ijGj?`Gg!{UVnQ;u zF%;Q5M}h0lqo0$*v&mCRO^RR}n9wrhiGnsECJ6mzNCFmw2BekvXUIDP17g_5O;k0+ z#mLV?OGhLbGVu}DwTsI+Uw16Z#e)8Rk#fpXozUK0ObAM_i)1>j_P_|J))vc2t{&Uc&lKlvBi CyKAQa literal 0 HcmV?d00001 diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 897896b7c..47c5f4657 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -957,19 +957,20 @@ PACK(struct RadioData { // Radio level tabs control (global settings) #if defined(COLORLCD) - uint8_t radioThemesDisabled:1; + NOBACKUP(uint8_t modelSelectLayout:2); + NOBACKUP(uint8_t radioThemesDisabled:1); #endif - uint8_t radioGFDisabled:1; - uint8_t radioTrainerDisabled:1; + NOBACKUP(uint8_t radioGFDisabled:1); + NOBACKUP(uint8_t radioTrainerDisabled:1); // Model level tabs control (global setting) - uint8_t modelHeliDisabled:1; - uint8_t modelFMDisabled:1; - uint8_t modelCurvesDisabled:1; - uint8_t modelGVDisabled:1; - uint8_t modelLSDisabled:1; - uint8_t modelSFDisabled:1; - uint8_t modelCustomScriptsDisabled:1; - uint8_t modelTelemetryDisabled:1; + NOBACKUP(uint8_t modelHeliDisabled:1); + NOBACKUP(uint8_t modelFMDisabled:1); + NOBACKUP(uint8_t modelCurvesDisabled:1); + NOBACKUP(uint8_t modelGVDisabled:1); + NOBACKUP(uint8_t modelLSDisabled:1); + NOBACKUP(uint8_t modelSFDisabled:1); + NOBACKUP(uint8_t modelCustomScriptsDisabled:1); + NOBACKUP(uint8_t modelTelemetryDisabled:1); NOBACKUP(uint8_t getBrightness() const { diff --git a/radio/src/gui/colorlcd/bitmaps.cpp b/radio/src/gui/colorlcd/bitmaps.cpp index 04d4e4904..1b065f5ac 100644 --- a/radio/src/gui/colorlcd/bitmaps.cpp +++ b/radio/src/gui/colorlcd/bitmaps.cpp @@ -191,6 +191,18 @@ static const uint8_t stick_pointer[] = { static const uint8_t stick_background[] = { #include "alpha_stick_background.lbm" }; +static const uint8_t mask_model_grid_large[] = { +#include "mask_model_grid_large.lbm" +}; +static const uint8_t mask_model_grid_small[] = { +#include "mask_model_grid_small.lbm" +}; +static const uint8_t mask_model_list_one[] = { +#include "mask_model_list_one.lbm" +}; +static const uint8_t mask_model_list_two[] = { +#include "mask_model_list_two.lbm" +}; BitmapBuffer * calibStick = nullptr; BitmapBuffer * calibStickBackground = nullptr; @@ -285,6 +297,10 @@ static const _BuiltinIcon _builtinIcons[] = { {ICON_MONITOR_CHANNELS3, mask_monitor_channels3}, {ICON_MONITOR_CHANNELS4, mask_monitor_channels4}, {ICON_MONITOR_LOGICAL_SWITCHES, mask_monitor_logsw}, + {ICON_MODEL_GRID_LARGE, mask_model_grid_large}, + {ICON_MODEL_GRID_SMALL, mask_model_grid_small}, + {ICON_MODEL_LIST_TWO, mask_model_list_two}, + {ICON_MODEL_LIST_ONE, mask_model_list_one}, }; const uint8_t* getBuiltinIcon(MenuIcons id) diff --git a/radio/src/gui/colorlcd/menus.h b/radio/src/gui/colorlcd/menus.h index 5feae9011..dbdf43d38 100644 --- a/radio/src/gui/colorlcd/menus.h +++ b/radio/src/gui/colorlcd/menus.h @@ -78,6 +78,10 @@ enum MenuIcons { ICON_MONITOR_CHANNELS3, ICON_MONITOR_CHANNELS4, ICON_MONITOR_LOGICAL_SWITCHES, + ICON_MODEL_GRID_LARGE, + ICON_MODEL_GRID_SMALL, + ICON_MODEL_LIST_TWO, + ICON_MODEL_LIST_ONE, MENUS_ICONS_COUNT }; diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index 38eb09126..792f277a1 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -32,17 +32,32 @@ inline tmr10ms_t getTicks() { return g_tmr10ms; } -constexpr coord_t MODEL_CELL_PADDING = 6; -constexpr coord_t MODEL_SELECT_CELL_HEIGHT = 92; constexpr int BUTTONS_HEIGHT = 32; -constexpr int MODEL_CELLS_PER_LINE = 2; + +struct ModelButtonLayout { + uint16_t width; + uint16_t height; + uint16_t padding; + bool hsaImage; + uint16_t font; +}; + +ModelButtonLayout modelLayouts[] = { +#if LCD_W > LCD_H // Landscape + {165, 92, 6, true, FONT(STD)}, + {108, 61, 6, true, FONT(XS)}, + {165, 32, 4, false, FONT(STD)}, + {336, 32, 4, false, FONT(STD)}, +#else // Portrait + {147, 92, 6, true, FONT(STD)}, + {96, 61, 6, true, FONT(XS)}, + {147, 32, 4, false, FONT(STD)}, + {300, 32, 4, false, FONT(STD)}, +#endif +}; #if LCD_W > LCD_H // Landscape -constexpr int LABELS_WIDTH = 132; constexpr int LAY_MARGIN = 5; -constexpr coord_t MODEL_SELECT_CELL_WIDTH = - (LCD_W - LABELS_WIDTH - (MODEL_CELLS_PER_LINE + 1) * MODEL_CELL_PADDING) / - MODEL_CELLS_PER_LINE; constexpr int LABELS_ROW = 0; constexpr int MODELS_COL = 1; constexpr int MODELS_ROW = 0; @@ -50,10 +65,6 @@ constexpr int MODELS_ROW_CNT = 2; constexpr int BUTTONS_ROW = 1; #else // Portrait constexpr int LAY_MARGIN = 8; -constexpr int LABELS_HEIGHT = 140; -constexpr coord_t MODEL_SELECT_CELL_WIDTH = - (LCD_W - LAY_MARGIN - (MODEL_CELLS_PER_LINE + 1) * MODEL_CELL_PADDING) / - MODEL_CELLS_PER_LINE; constexpr int LABELS_ROW = 1; constexpr int MODELS_COL = 0; constexpr int MODELS_ROW = 0; @@ -65,16 +76,17 @@ class ModelButton : public Button { public: ModelButton(FormWindow *parent, const rect_t &rect, ModelCell *modelCell, - std::function setSelected) : + std::function setSelected, uint8_t layout) : Button(parent, rect, nullptr, 0, 0, etx_button_create), + layout(layout), modelCell(modelCell), m_setSelected(std::move(setSelected)) { padAll(0); lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE); - setWidth(MODEL_SELECT_CELL_WIDTH); - setHeight(MODEL_SELECT_CELL_HEIGHT); + setWidth(modelLayouts[layout].width); + setHeight(modelLayouts[layout].height); check(modelCell == modelslist.getCurrentModel()); @@ -98,38 +110,53 @@ class ModelButton : public Button coord_t w = width() - 8; coord_t h = height() - 8; - GET_FILENAME(filename, BITMAPS_PATH, modelCell->modelBitmap, ""); - const BitmapBuffer *bitmap = BitmapBuffer::loadBitmap(filename); + LcdFlags font = modelLayouts[layout].font; + if ((getTextWidth(modelCell->modelName, 0, font) > w)) + font = (font == FONT(STD)) ? FONT(XS) : FONT(XXS); - if (bitmap) { - buffer = new BitmapBuffer(BMP_RGB565, w, h); - if (buffer) { - buffer->clear(bg_color); - buffer->drawScaledBitmap(bitmap, 0, 0, w, h); - delete bitmap; + if (modelLayouts[layout].hsaImage) { + GET_FILENAME(filename, BITMAPS_PATH, modelCell->modelBitmap, ""); + const BitmapBuffer *bitmap = BitmapBuffer::loadBitmap(filename); - lv_obj_t *bm = lv_canvas_create(lvobj); - lv_obj_center(bm); - lv_canvas_set_buffer(bm, buffer->getData(), buffer->width(), - buffer->height(), LV_IMG_CF_TRUE_COLOR); + if (bitmap) { + buffer = new BitmapBuffer(BMP_RGB565, w, h); + if (buffer) { + buffer->clear(bg_color); + buffer->drawScaledBitmap(bitmap, 0, 0, w, h); + delete bitmap; + + lv_obj_t *bm = lv_canvas_create(lvobj); + lv_obj_center(bm); + lv_canvas_set_buffer(bm, buffer->getData(), buffer->width(), + buffer->height(), LV_IMG_CF_TRUE_COLOR); + } } - } - if (!buffer) { - std::string errorMsg = "("; - errorMsg += STR_NO_PICTURE; - errorMsg += ")"; - new StaticText(this, {2, h / 2, w, 17}, errorMsg, 0, - CENTERED | COLOR_THEME_SECONDARY1 | FONT(XS)); - } + if (!buffer) { + std::string errorMsg = "("; + errorMsg += STR_NO_PICTURE; + errorMsg += ")"; + new StaticText(this, {2, h / 2, w, 17}, errorMsg, 0, + CENTERED | COLOR_THEME_SECONDARY1 | FONT(XS)); + } - auto name = - new StaticText(this, {2, 2, width() - 8, 17}, modelCell->modelName, 0, - CENTERED | COLOR_THEME_SECONDARY1); - name->setHeight(17); - name->setBackgroudOpacity(LV_OPA_80); - name->setBackgroundColor(bg_color); - name->padTop(-3); + coord_t fh = (font == FONT(STD)) ? 17 : (font == FONT(XS)) ? 14 : 11; + coord_t fo = (font == FONT(STD)) ? -3 : (font == FONT(XS)) ? -3 : -1; + + auto name = new StaticText(this, {2, 2, w, fh}, modelCell->modelName, 0, + CENTERED | COLOR_THEME_SECONDARY1 | font); + lv_label_set_long_mode(name->getLvObj(), LV_LABEL_LONG_DOT); + name->setWidth(w); + name->setHeight(fh); + name->setBackgroudOpacity(LV_OPA_80); + name->setBackgroundColor(bg_color); + name->padTop(fo); + } else { + auto name = new StaticText(this, {2, 4, w, 24}, modelCell->modelName, 0, + COLOR_THEME_SECONDARY1 | font); + lv_label_set_long_mode(name->getLvObj(), LV_LABEL_LONG_DOT); + name->setWidth(w); + } } static void on_draw(lv_event_t *e) @@ -157,6 +184,7 @@ class ModelButton : public Button protected: bool loaded = false; + uint8_t layout; ModelCell *modelCell; BitmapBuffer *buffer = nullptr; std::function m_setSelected = nullptr; @@ -182,14 +210,16 @@ class ModelsPageBody : public FormWindow #else padLeft(LAY_MARGIN); #endif - setFlexLayout(LV_FLEX_FLOW_ROW_WRAP, MODEL_CELL_PADDING); - padRow(MODEL_CELL_PADDING); } void update() { clear(); + setFlexLayout(LV_FLEX_FLOW_ROW_WRAP, + modelLayouts[g_eeGeneral.modelSelectLayout].padding); + padRow(modelLayouts[g_eeGeneral.modelSelectLayout].padding); + ModelsVector models; if (selectedLabels.size()) { models = modelslabels.getModelsInLabels(selectedLabels); @@ -206,8 +236,9 @@ class ModelsPageBody : public FormWindow ModelButton *focusedButton = nullptr; for (auto &model : models) { - auto button = new ModelButton(this, rect_t{}, model, - [=]() { focusedModel = model; }); + auto button = new ModelButton( + this, rect_t{}, model, [=]() { focusedModel = model; }, + g_eeGeneral.modelSelectLayout); if (!firstButton) firstButton = button; if (model == modelslist.getCurrentModel()) focusedButton = button; @@ -481,6 +512,46 @@ class LabelDialog : public Dialog //----------------------------------------------------------------------------- +class ModelLayoutButton : public TextButton +{ + public: + ModelLayoutButton(Window *parent, std::function pressHandler) : + TextButton(parent, {0, 0, 32, 32}, "", pressHandler) + { + } + + ~ModelLayoutButton() + { + if (bmBuffer) delete bmBuffer; + } + + uint8_t getLayout() const { return layout; } + + void setLayout(uint8_t newLayout) + { + layout = newLayout; + invalidate(); + } + + void paint(BitmapBuffer *dc) override + { + auto maskData = getBuiltinIcon((MenuIcons)(ICON_MODEL_GRID_LARGE + layout)); + auto mask = BitmapBuffer::load8bitMaskLZ4(maskData); + if (!bmBuffer) + bmBuffer = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height()); + bmBuffer->clear(COLOR_THEME_PRIMARY2); + bmBuffer->drawMask(0, 0, mask, COLOR_THEME_SECONDARY1); + delete mask; + dc->drawBitmap(3, 3, bmBuffer); + } + + protected: + uint8_t layout; + BitmapBuffer *bmBuffer = nullptr; +}; + +//----------------------------------------------------------------------------- + ModelLabelsWindow::ModelLabelsWindow() : Page(ICON_MODEL) { buildHead(&header); @@ -629,7 +700,7 @@ void ModelLabelsWindow::buildHead(PageHeader *hdr) setTitle(); // new model button - auto btn = new TextButton(hdr, rect_t{}, STR_NEW, [=]() { + auto btn = new TextButton(hdr, rect_t{0, 0, 60, 32}, STR_NEW, [=]() { auto menu = new Menu(this); menu->setTitle(STR_CREATE_NEW); menu->addLine(STR_NEW_MODEL, [=]() { newModel(); }); @@ -642,14 +713,28 @@ void ModelLabelsWindow::buildHead(PageHeader *hdr) // button placement hdr->padRight(lv_dpx(8)); lv_obj_align(btn->getLvObj(), LV_ALIGN_RIGHT_MID, 0, 0); + + mldLayout = new ModelLayoutButton(this, [=]() { + uint8_t l = mldLayout->getLayout(); + l = (l + 1) & 3; + mldLayout->setLayout(l); + g_eeGeneral.modelSelectLayout = l; + storageDirty(EE_GENERAL); + mdlselector->update(); + return 0; + }); + mldLayout->setLayout(g_eeGeneral.modelSelectLayout); + lv_obj_set_pos(mldLayout->getLvObj(), LCD_W - 105, 6); } #if LCD_W > LCD_H +constexpr int LABELS_WIDTH = 132; static const lv_coord_t col_dsc[] = {LABELS_WIDTH, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; static const lv_coord_t row_dsc[] = {LV_GRID_FR(1), BUTTONS_HEIGHT, LV_GRID_TEMPLATE_LAST}; #else +constexpr int LABELS_HEIGHT = 140; static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; static const lv_coord_t row_dsc[] = {LV_GRID_FR(1), LABELS_HEIGHT, BUTTONS_HEIGHT, LV_GRID_TEMPLATE_LAST}; @@ -672,6 +757,9 @@ void ModelLabelsWindow::buildBody(FormWindow *window) lv_obj_set_grid_cell(mdl_obj, LV_GRID_ALIGN_STRETCH, MODELS_COL, 1, LV_GRID_ALIGN_STRETCH, MODELS_ROW, MODELS_ROW_CNT); + if (mdlselector->getSortOrder() == NO_SORT) + mdlselector->setSortOrder(NAME_ASC); + // Labels auto box = new Window(window, rect_t{}); box->padAll(0); diff --git a/radio/src/gui/colorlcd/model_select.h b/radio/src/gui/colorlcd/model_select.h index 0ec1ffc01..2051e7772 100644 --- a/radio/src/gui/colorlcd/model_select.h +++ b/radio/src/gui/colorlcd/model_select.h @@ -27,6 +27,7 @@ #include "tabsgroup.h" class ModelsPageBody; +class ModelLayoutButton; class ModelLabelsWindow : public Page { @@ -38,6 +39,7 @@ class ModelLabelsWindow : public Page char tmpLabel[LABEL_LENGTH + 1] = "\0"; ListBox *lblselector; ModelsPageBody *mdlselector; + ModelLayoutButton *mldLayout; std::string currentLabel; LabelsVector getLabels() diff --git a/radio/src/storage/modelslist.cpp b/radio/src/storage/modelslist.cpp index 55721f411..ddd59798b 100644 --- a/radio/src/storage/modelslist.cpp +++ b/radio/src/storage/modelslist.cpp @@ -840,7 +840,7 @@ bool ModelMap::updateModelFile(ModelCell *cell) /** * @brief Sorts a ModelsVector by sortby * - * @param mv ModeslVector to sort + * @param mv ModelsVector to sort * @param sortby NO_SORT, NAME_ASC, NAME_DES, DATE_ASC, DATE_DES, */ diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index fc448baa0..996367537 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -367,6 +367,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_SIGNED( "uartSampleMode", 2 ), YAML_UNSIGNED( "stickDeadZone", 3 ), YAML_STRING("selectedTheme", 26), + YAML_UNSIGNED( "modelSelectLayout", 2 ), YAML_UNSIGNED( "radioThemesDisabled", 1 ), YAML_UNSIGNED( "radioGFDisabled", 1 ), YAML_UNSIGNED( "radioTrainerDisabled", 1 ), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp index 408b5db26..7b3aa9209 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -367,6 +367,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_SIGNED( "uartSampleMode", 2 ), YAML_UNSIGNED( "stickDeadZone", 3 ), YAML_STRING("selectedTheme", 26), + YAML_UNSIGNED( "modelSelectLayout", 2 ), YAML_UNSIGNED( "radioThemesDisabled", 1 ), YAML_UNSIGNED( "radioGFDisabled", 1 ), YAML_UNSIGNED( "radioTrainerDisabled", 1 ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index f2fdf8a1b..abbfb21f8 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -369,6 +369,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_SIGNED( "imuMax", 8 ), YAML_SIGNED( "imuOffset", 8 ), YAML_STRING("selectedTheme", 26), + YAML_UNSIGNED( "modelSelectLayout", 2 ), YAML_UNSIGNED( "radioThemesDisabled", 1 ), YAML_UNSIGNED( "radioGFDisabled", 1 ), YAML_UNSIGNED( "radioTrainerDisabled", 1 ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp index f2fdf8a1b..abbfb21f8 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp @@ -369,6 +369,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_SIGNED( "imuMax", 8 ), YAML_SIGNED( "imuOffset", 8 ), YAML_STRING("selectedTheme", 26), + YAML_UNSIGNED( "modelSelectLayout", 2 ), YAML_UNSIGNED( "radioThemesDisabled", 1 ), YAML_UNSIGNED( "radioGFDisabled", 1 ), YAML_UNSIGNED( "radioTrainerDisabled", 1 ),