folder settings & allow picking which dialog to use

This commit is contained in:
HJfod 2024-08-24 12:13:58 +03:00
parent 1a82d12b7b
commit 56f878ccb3
4 changed files with 71 additions and 56 deletions

View file

@ -328,16 +328,11 @@ namespace geode {
FileSettingV3(PrivateMarker);
static Result<std::shared_ptr<FileSettingV3>> parse(std::string const& key, std::string const& modID, matjson::Value const& json);
enum class FileType {
Any = 0,
File = 1,
Folder = 2,
};
std::filesystem::path getDefaultValue() const override;
Result<> isValid(std::filesystem::path const& value) const override;
FileType getFileType() const;
bool isFolder() const;
bool useSaveDialog() const;
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;

View file

@ -21,6 +21,7 @@ private:
{ "float", &FloatSettingV3::parse },
{ "string", &StringSettingV3::parse },
{ "file", &FileSettingV3::parse },
{ "folder", &FileSettingV3::parse },
{ "path", &FileSettingV3::parse },
{ "rgb", &Color3BSettingV3::parse },
{ "color", &Color3BSettingV3::parse },

View file

@ -347,17 +347,17 @@ bool FileSettingNodeV3::init(std::shared_ptr<FileSettingV3> setting, float width
labelBG->setScale(.25f);
labelBG->setColor({ 0, 0, 0 });
labelBG->setOpacity(90);
labelBG->setContentSize({ 400, 80 });
this->getButtonMenu()->addChildAtPosition(labelBG, Anchor::Center, ccp(-15, 0));
labelBG->setContentSize({ 420, 80 });
this->getButtonMenu()->addChildAtPosition(labelBG, Anchor::Center, ccp(-10, 0));
m_fileIcon = CCSprite::create();
this->getButtonMenu()->addChildAtPosition(m_fileIcon, Anchor::Left, ccp(3, 0));
this->getButtonMenu()->addChildAtPosition(m_fileIcon, Anchor::Left, ccp(5, 0));
m_nameLabel = CCLabelBMFont::create("", "bigFont.fnt");
this->getButtonMenu()->addChildAtPosition(m_nameLabel, Anchor::Left, ccp(11, 0), ccp(0, .5f));
this->getButtonMenu()->addChildAtPosition(m_nameLabel, Anchor::Left, ccp(13, 0), ccp(0, .5f));
auto selectSpr = CCSprite::createWithSpriteFrameName("GJ_plus2Btn_001.png");
selectSpr->setScale(.75f);
selectSpr->setScale(.7f);
auto selectBtn = CCMenuItemSpriteExtra::create(
selectSpr, this, menu_selector(FileSettingNodeV3::onPickFile)
);
@ -370,18 +370,21 @@ bool FileSettingNodeV3::init(std::shared_ptr<FileSettingV3> setting, float width
void FileSettingNodeV3::updateState() {
SettingNodeV3::updateState();
auto ty = this->getSetting()->getFileType();
if (ty == FileSettingV3::FileType::Any) {
ty = std::filesystem::is_directory(m_path) ?
FileSettingV3::FileType::Folder :
FileSettingV3::FileType::File;
}
m_fileIcon->setDisplayFrame(CCSpriteFrameCache::get()->spriteFrameByName(
ty == FileSettingV3::FileType::File ? "file.png"_spr : "folderIcon_001.png"
this->getSetting()->isFolder() ? "folderIcon_001.png" : "file.png"_spr
));
limitNodeSize(m_fileIcon, ccp(10, 10), 1.f, .1f);
if (m_path.empty()) {
m_nameLabel->setString(this->getSetting()->isFolder() ? "No Folder Selected" : "No File Selected");
m_nameLabel->setColor(ccGRAY);
m_nameLabel->setOpacity(155);
}
else {
m_nameLabel->setString(m_path.filename().string().c_str());
m_nameLabel->limitLabelWidth(75, .4f, .1f);
m_nameLabel->setColor(ccWHITE);
m_nameLabel->setOpacity(255);
}
m_nameLabel->limitLabelWidth(75, .35f, .1f);
}
void FileSettingNodeV3::onCommit() {
@ -407,9 +410,9 @@ void FileSettingNodeV3::onPickFile(CCObject*) {
}
});
m_pickListener.setFilter(file::pick(
this->getSetting()->getFileType() == FileSettingV3::FileType::Folder ?
this->getSetting()->isFolder() ?
file::PickMode::OpenFolder :
file::PickMode::OpenFile,
(this->getSetting()->useSaveDialog() ? file::PickMode::SaveFile : file::PickMode::OpenFile),
{
dirs::getGameDir(),
this->getSetting()->getFilters().value_or(std::vector<file::FilePickOptions::Filter>())

View file

@ -609,7 +609,8 @@ class FileSettingV3::Impl final {
public:
std::filesystem::path value;
std::filesystem::path defaultValue;
FileType fileType;
bool folder = false;
bool useSaveDialog = false; // this option makes no sense if folder = true
std::optional<std::vector<utils::file::FilePickOptions::Filter>> filters;
};
@ -639,19 +640,30 @@ Result<std::shared_ptr<FileSettingV3>> FileSettingV3::parse(std::string const& k
}
ret->m_impl->value = ret->m_impl->defaultValue;
if (auto ty = root.has("filetype")) {
ty.assertIsString();
switch (hash(ty.template get<std::string>())) {
case hash("any"): ret->m_impl->fileType = FileType::Any; break;
case hash("file"): ret->m_impl->fileType = FileType::File; break;
case hash("folder"): ret->m_impl->fileType = FileType::Folder; break;
default: return Err(
"Setting '{}' in mod {}: Invalid filetype \"{}\"",
key, modID, ty.template get<std::string>()
std::string type;
root.needs("type").into(type);
if (type == "folder") {
ret->m_impl->folder = true;
// folder-specific stuff if they ever exist
}
else if (type == "file" || type == "path") {
if (type == "path") {
log::warn(
"Setting '{}' in mod {}: the \"path\" type has been "
"deprecated, use \"type\": \"file\" or \"type\": \"folder\" instead",
key, modID
);
}
std::string dialogType;
root.has("dialog").into(dialogType);
switch (hash(dialogType)) {
case hash("save"): ret->m_impl->useSaveDialog = true; break;
case hash("open"): ret->m_impl->useSaveDialog = false; break;
case hash(""): break;
default: return Err("Setting '{}' in mod {}: unknown \"dialog\" type \"{}\"", key, modID, dialogType);
}
// Filter controls only make sense for files but not for folders
if (auto controls = root.has("control")) {
auto filters = std::vector<file::FilePickOptions::Filter>();
for (auto& item : controls.has("filters").items()) {
@ -664,6 +676,7 @@ Result<std::shared_ptr<FileSettingV3>> FileSettingV3::parse(std::string const& k
ret->m_impl->filters.emplace(filters);
}
}
}
root.checkUnknownKeys();
return root.ok(ret);
@ -676,22 +689,25 @@ std::filesystem::path FileSettingV3::getDefaultValue() const {
return m_impl->defaultValue;
}
Result<> FileSettingV3::isValid(std::filesystem::path const& value) const {
if (m_impl->fileType != FileType::Any) {
if (!std::filesystem::exists(value)) {
return Err("{} must exist", m_impl->fileType == FileType::File ? "File" : "Folder");
}
if (m_impl->fileType == FileType::File && !std::filesystem::is_regular_file(value)) {
return Err("Value must be a file");
}
if (m_impl->fileType == FileType::Folder && !std::filesystem::is_directory(value)) {
std::error_code ec;
if (m_impl->folder) {
if (!std::filesystem::is_directory(value, ec)) {
return Err("Value must be a folder");
}
}
else {
if (!std::filesystem::is_regular_file(value, ec)) {
return Err("Value must be a file");
}
}
return Ok();
}
FileSettingV3::FileType FileSettingV3::getFileType() const {
return m_impl->fileType;
bool FileSettingV3::isFolder() const {
return m_impl->folder;
}
bool FileSettingV3::useSaveDialog() const {
return m_impl->useSaveDialog;
}
std::optional<std::vector<utils::file::FilePickOptions::Filter>> FileSettingV3::getFilters() const {