feat(color): add filters to file chooser popup menu (#4946)
This commit is contained in:
@@ -111,7 +111,7 @@ class ScriptEditWindow : public Page
|
||||
LUA_LOAD_MODEL_SCRIPT(idx); // async reload ...
|
||||
update = true;
|
||||
},
|
||||
true);
|
||||
true, STR_SCRIPT);
|
||||
|
||||
// Custom name
|
||||
line = window->newLine(grid);
|
||||
|
||||
@@ -92,7 +92,7 @@ static void setModelBitmap(std::string newValue)
|
||||
struct ModelBitmapEdit : public FileChoice {
|
||||
ModelBitmapEdit(Window *parent, const rect_t &rect) :
|
||||
FileChoice(parent, rect, BITMAPS_PATH, BITMAPS_EXT, LEN_BITMAP_NAME,
|
||||
getModelBitmap, setModelBitmap)
|
||||
getModelBitmap, setModelBitmap, false, STR_BITMAP)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -482,7 +482,7 @@ void FunctionEditPage::updateSpecialFunctionOneWindow()
|
||||
if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
},
|
||||
true); // strip extension
|
||||
true, funcGetLabel(func));
|
||||
break;
|
||||
|
||||
case FUNC_SET_TIMER: {
|
||||
|
||||
+4
@@ -45,6 +45,8 @@ class ChoiceBase : public FormField
|
||||
ChoiceBase(Window *parent, const rect_t &rect,
|
||||
ChoiceType type = CHOICE_TYPE_DROPOWN);
|
||||
|
||||
void setChoiceType(ChoiceType t) { type = t; }
|
||||
|
||||
protected:
|
||||
ChoiceType type;
|
||||
lv_obj_t *label;
|
||||
@@ -149,6 +151,8 @@ class Choice : public ChoiceBase
|
||||
int getMin() const { return vmin; }
|
||||
int getMax() const { return vmax; }
|
||||
|
||||
std::string getString(int val) { return values[val]; }
|
||||
|
||||
void set_lv_LongPressHandler(lvHandler_t longPressHandler, void *data);
|
||||
|
||||
int selectedIx0 = 0;
|
||||
|
||||
+113
-36
@@ -22,14 +22,82 @@
|
||||
|
||||
#include "libopenui_file.h"
|
||||
#include "menu.h"
|
||||
#include "menutoolbar.h"
|
||||
#include "theme.h"
|
||||
|
||||
class FileChoiceMenuToolbar : public MenuToolbar
|
||||
{
|
||||
public:
|
||||
FileChoiceMenuToolbar(FileChoice *choice, Menu *menu) :
|
||||
MenuToolbar(choice, menu, 3)
|
||||
{
|
||||
filterButton(choice, 'a', 'd', "aA-dD");
|
||||
filterButton(choice, 'e', 'h', "eE-hH");
|
||||
filterButton(choice, 'i', 'l', "iI-lL");
|
||||
filterButton(choice, 'm', 'p', "mM-pP");
|
||||
filterButton(choice, 'q', 't', "qQ-tT");
|
||||
filterButton(choice, 'u', 'z', "uU-zZ");
|
||||
filterButton(choice, '0', '9', "0-9");
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < choice->getMax(); i += 1) {
|
||||
char c = choice->getString(i)[0];
|
||||
if (c && !isdigit(c) && !isalpha(c)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
addButton(
|
||||
"._-", 0, choice->getMax(),
|
||||
[=](int16_t index) {
|
||||
char c = choice->getString(index)[0];
|
||||
return c && !isdigit(c) && !isalpha(c);
|
||||
},
|
||||
STR_MENU_OTHER);
|
||||
}
|
||||
|
||||
addButton(STR_SELECT_MENU_CLR, 0, 0, nullptr, nullptr, true);
|
||||
}
|
||||
|
||||
void filterButton(FileChoice *choice, char from, char to, const char* title)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < choice->getMax(); i += 1) {
|
||||
char c = choice->getString(i)[0];
|
||||
if (isupper(c)) c += 0x20;
|
||||
if (c >= from && c <= to) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
char s[4];
|
||||
s[0] = from; s[1] = '-'; s[2] = to; s[3] = 0;
|
||||
addButton(
|
||||
s, 0, choice->getMax(),
|
||||
[=](int16_t index) {
|
||||
char c = choice->getString(index)[0];
|
||||
if (isupper(c)) c += 0x20;
|
||||
return (c >= from && c <= to);
|
||||
},
|
||||
title);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
FileChoice::FileChoice(Window *parent, const rect_t &rect, std::string folder,
|
||||
const char *extension, int maxlen,
|
||||
std::function<std::string()> getValue,
|
||||
std::function<void(std::string)> setValue,
|
||||
bool stripExtension) :
|
||||
ChoiceBase(parent, rect, CHOICE_TYPE_FOLDER),
|
||||
bool stripExtension, const char *title) :
|
||||
Choice(
|
||||
parent, rect, 0, 0, [=]() { return selectedIdx; },
|
||||
[=](int val) { setValue(getString(val)); }, title),
|
||||
folder(std::move(folder)),
|
||||
extension(extension),
|
||||
maxlen(maxlen),
|
||||
@@ -37,13 +105,18 @@ FileChoice::FileChoice(Window *parent, const rect_t &rect, std::string folder,
|
||||
setValue(std::move(setValue)),
|
||||
stripExtension(stripExtension)
|
||||
{
|
||||
setChoiceType(CHOICE_TYPE_FOLDER);
|
||||
lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
}
|
||||
|
||||
std::string FileChoice::getLabelText() { return getValue(); }
|
||||
|
||||
bool FileChoice::openMenu()
|
||||
void FileChoice::loadFiles()
|
||||
{
|
||||
if (loaded) return;
|
||||
|
||||
loaded = true;
|
||||
|
||||
FILINFO fno;
|
||||
DIR dir;
|
||||
std::list<std::string> files;
|
||||
@@ -79,41 +152,45 @@ bool FileChoice::openMenu()
|
||||
files.emplace_back(newFile);
|
||||
}
|
||||
|
||||
if (!files.empty()) {
|
||||
// sort files
|
||||
files.sort(compare_nocase);
|
||||
files.push_front("");
|
||||
|
||||
auto menu = new Menu(this);
|
||||
int count = 0;
|
||||
int current = -1;
|
||||
std::string value = getValue();
|
||||
for (const auto &file : files) {
|
||||
menu->addLineBuffered(file, [=]() {
|
||||
setValue(file);
|
||||
lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
});
|
||||
// TRACE("%s %d %s %d", value.c_str(), value.size(), file.c_str(),
|
||||
// file.size());
|
||||
if (value.compare(file) == 0) {
|
||||
// TRACE("OK");
|
||||
current = count;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
menu->updateLines();
|
||||
|
||||
if (current >= 0) {
|
||||
menu->select(current);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
f_closedir(&dir);
|
||||
}
|
||||
|
||||
new MessageDialog(this, STR_SDCARD, STR_NO_FILES_ON_SD);
|
||||
if (!files.empty()) {
|
||||
// sort files
|
||||
files.sort(compare_nocase);
|
||||
files.push_front("");
|
||||
|
||||
return false;
|
||||
std::string value = getValue();
|
||||
int idx = 0;
|
||||
for (const auto &file : files) {
|
||||
addValue(file.c_str());
|
||||
if (strcmp(value.c_str(), file.c_str()) == 0) selectedIdx = idx;
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
setMax(files.size() - 1);
|
||||
}
|
||||
|
||||
fileCount = files.size();
|
||||
}
|
||||
|
||||
void FileChoice::onClicked() { openMenu(); }
|
||||
void FileChoice::openMenu()
|
||||
{
|
||||
loadFiles();
|
||||
|
||||
if (fileCount > 0) {
|
||||
setEditMode(true); // this needs to be done first before menu is created.
|
||||
|
||||
auto menu = new Menu(this);
|
||||
if (menuTitle) menu->setTitle(menuTitle);
|
||||
|
||||
auto tb = new FileChoiceMenuToolbar(this, menu);
|
||||
menu->setToolbar(tb);
|
||||
|
||||
fillMenu(menu);
|
||||
|
||||
menu->setCloseHandler([=]() { setEditMode(false); });
|
||||
} else {
|
||||
new MessageDialog(this, STR_SDCARD, STR_NO_FILES_ON_SD);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-5
@@ -21,22 +21,25 @@
|
||||
#include "choice.h"
|
||||
#include <string>
|
||||
|
||||
class FileChoice : public ChoiceBase
|
||||
class FileChoice : public Choice
|
||||
{
|
||||
public:
|
||||
FileChoice(Window* parent, const rect_t& rect, std::string folder,
|
||||
const char* extension, int maxlen,
|
||||
std::function<std::string()> getValue,
|
||||
std::function<void(std::string)> setValue,
|
||||
bool stripExtension=false);
|
||||
bool stripExtension = false,
|
||||
const char* title = nullptr);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override { return "FileChoice"; }
|
||||
#endif
|
||||
|
||||
void onClicked() override;
|
||||
|
||||
protected:
|
||||
bool loaded = false;
|
||||
int fileCount = 0;
|
||||
int selectedIdx = -1;
|
||||
Menu* menu = nullptr;
|
||||
std::string getLabelText() override;
|
||||
std::string folder;
|
||||
const char* extension;
|
||||
@@ -45,5 +48,7 @@ protected:
|
||||
std::function<void(std::string)> setValue;
|
||||
bool stripExtension;
|
||||
|
||||
bool openMenu();
|
||||
void loadFiles();
|
||||
|
||||
void openMenu() override;
|
||||
};
|
||||
|
||||
+5
-2
@@ -22,6 +22,9 @@
|
||||
#include "themes/etx_lv_theme.h"
|
||||
#include "translations.h"
|
||||
|
||||
constexpr uint32_t MENUS_TOOLBAR_BUTTON_WIDTH = 36;
|
||||
constexpr uint32_t MENUS_TOOLBAR_BUTTON_HEIGHT = 32;
|
||||
|
||||
static const lv_obj_class_t menu_button_class = {
|
||||
.base_class = &button_class,
|
||||
.constructor_cb = nullptr,
|
||||
@@ -113,13 +116,13 @@ rect_t MenuToolbar::getButtonRect(bool wideButton)
|
||||
coord_t x =
|
||||
(nxtBtnPos % filterColumns) * (MENUS_TOOLBAR_BUTTON_WIDTH + PAD_SMALL);
|
||||
coord_t y =
|
||||
(nxtBtnPos / filterColumns) * (MENUS_TOOLBAR_BUTTON_WIDTH + PAD_SMALL);
|
||||
(nxtBtnPos / filterColumns) * (MENUS_TOOLBAR_BUTTON_HEIGHT + PAD_SMALL);
|
||||
coord_t w = wideButton ? (MENUS_TOOLBAR_BUTTON_WIDTH + PAD_SMALL) *
|
||||
(filterColumns - 1) +
|
||||
MENUS_TOOLBAR_BUTTON_WIDTH
|
||||
: MENUS_TOOLBAR_BUTTON_WIDTH;
|
||||
nxtBtnPos += wideButton ? filterColumns : 1;
|
||||
return {x, y, w, MENUS_TOOLBAR_BUTTON_WIDTH};
|
||||
return {x, y, w, MENUS_TOOLBAR_BUTTON_HEIGHT};
|
||||
}
|
||||
|
||||
bool MenuToolbar::filterMenu(MenuToolbarButton* btn, int16_t filtermin,
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "button.h"
|
||||
#include "choice.h"
|
||||
|
||||
constexpr uint32_t MENUS_TOOLBAR_BUTTON_WIDTH = 32;
|
||||
|
||||
class Menu;
|
||||
|
||||
class MenuToolbarButton : public ButtonBase
|
||||
|
||||
Reference in New Issue
Block a user