Skip to content

Commit

Permalink
Add filters to file chooser popup menu.
Browse files Browse the repository at this point in the history
  • Loading branch information
philmoz committed May 25, 2024
1 parent b8a0038 commit 9e94288
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 47 deletions.
2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/model_mixer_scripts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}
};
Expand Down
2 changes: 1 addition & 1 deletion radio/src/gui/colorlcd/special_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
4 changes: 4 additions & 0 deletions radio/src/thirdparty/libopenui/src/choice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
147 changes: 112 additions & 35 deletions radio/src/thirdparty/libopenui/src/filechoice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,101 @@

#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),
getValue(std::move(getValue)),
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;
Expand Down Expand Up @@ -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);
}
f_closedir(&dir);
}

return true;
if (!files.empty()) {
// sort files
files.sort(compare_nocase);
files.push_front("");

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;
}
}

new MessageDialog(this, STR_SDCARD, STR_NO_FILES_ON_SD);
setMax(files.size() - 1);
}

return false;
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);
}
}
15 changes: 10 additions & 5 deletions radio/src/thirdparty/libopenui/src/filechoice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -45,5 +48,7 @@ class FileChoice : public ChoiceBase
std::function<void(std::string)> setValue;
bool stripExtension;

bool openMenu();
void loadFiles();

void openMenu() override;
};
7 changes: 5 additions & 2 deletions radio/src/thirdparty/libopenui/src/menutoolbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -118,13 +121,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,
Expand Down
2 changes: 0 additions & 2 deletions radio/src/thirdparty/libopenui/src/menutoolbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
#include "button.h"
#include "choice.h"

constexpr uint32_t MENUS_TOOLBAR_BUTTON_WIDTH = 32;

class Menu;

class MenuToolbarButton : public ButtonBase
Expand Down

0 comments on commit 9e94288

Please sign in to comment.