Zelda64Recomp/src/ui/elements/ElementConfigGroup.cpp

139 lines
5.1 KiB
C++

#include "ElementConfigGroup.h"
#include "ElementConfigOption.h"
#include "../config_options/ConfigOption.h"
#include "../config_options/ConfigRegistry.h"
#include "ElementOptionTypeCheckbox.h"
#include "librecomp/config_store.hpp"
#include <string>
#include "recomp_ui.h"
#include <RmlUi/Core/ElementDocument.h>
#include <RmlUi/Core/ElementText.h>
#include <cassert>
using json = nlohmann::json;
namespace recompui {
static const std::string config_group_base_class = "config-group";
static const std::string config_group_base_class_scrollable = config_group_base_class + "--scrollable";
static const std::string config_group_title_class = config_group_base_class + "__title";
static const std::string config_group_title_class_hidden = config_group_title_class + "--hidden";
static const std::string config_group_wrapper_class = config_group_base_class + "__wrapper";
ElementConfigGroup::ElementConfigGroup(const Rml::String& tag) : Rml::Element(tag)
{
SetAttribute("recomp-store-element", true);
SetClass(config_group_base_class, true);
Rml::ElementDocument *doc = GetOwnerDocument();
{
Rml::Element *title_el = AppendChild(doc->CreateElement("div"));
title_el->SetClass(config_group_title_class, true);
{
Rml::Element *text_el = title_el->AppendChild(doc->CreateTextNode("replace me"));
text_el->SetId("config-group-label");
} // title_el
Rml::Element *div_el = AppendChild(doc->CreateElement("div"));
div_el->SetClass(config_group_wrapper_class, true);
}
}
ElementConfigGroup::~ElementConfigGroup()
{
}
void ElementConfigGroup::SetTextLabel(const std::string& s) {
Rml::Element *title_container = GetChild(0);
Rml::ElementText *label = (Rml::ElementText *)title_container->GetElementById("config-group-label");
label->SetText(s);
DirtyLayout();
}
void ElementConfigGroup::ToggleTextLabelVisibility(bool show) {
Rml::Element *title_container = GetChild(0);
title_container->SetClass(config_group_title_class_hidden, !show);
}
void ElementConfigGroup::AddConfigOptionElement(const json& option_json) {
ConfigOptionType el_option_type = ConfigOptionType::Label;
from_json(option_json["type"], el_option_type);
const std::string key = get_string_in_json(option_json, ConfigOption::schema::key);
Rml::Element *option_container = GetChild(1);
Rml::Element *child_opt = nullptr;
if (config_option_is_group(el_option_type)) {
child_opt = (ElementConfigGroup *)option_container->AppendChild(
recompui::create_custom_element(GetOwnerDocument(), "recomp-config-group")
);
// TODO: Base class with option type + config_key
((ElementConfigGroup *)child_opt)->option_type = el_option_type;
} else {
child_opt = (ElementConfigOption *)option_container->AppendChild(
recompui::create_custom_element(GetOwnerDocument(), "recomp-config-option")
);
// TODO: Base class with option type + config_key
ElementConfigOption *opt_as_conf_opt = (ElementConfigOption *)child_opt;
opt_as_conf_opt->option_type = el_option_type;
opt_as_conf_opt->in_checkbox_group = option_type == ConfigOptionType::CheckboxGroup;
}
std::string full_key = config_key + "/" + key;
child_opt->SetAttribute("recomp-data", full_key);
}
static nlohmann::json get_options(std::string& config_key) {
if (config_key_is_base_group(config_key)) {
return get_group_json(config_key);
}
const json& group_json = get_json_from_key(config_key);
return group_json["options"];
}
void ElementConfigGroup::OnAttributeChange(const Rml::ElementAttributes& changed_attributes)
{
// Call through to the base element's OnAttributeChange().
Rml::Element::OnAttributeChange(changed_attributes);
auto config_store_key_attr = changed_attributes.find("recomp-data");
if (config_store_key_attr != changed_attributes.end() && config_store_key_attr->second.GetType() == Rml::Variant::STRING) {
config_key = config_store_key_attr->second.Get<Rml::String>();
bool is_base_group = config_key_is_base_group(config_key);
option_type = ConfigOptionType::Label;
if (is_base_group) {
SetClass(config_group_base_class_scrollable, true);
option_type = ConfigOptionType::Group;
ToggleTextLabelVisibility(false);
} else {
try {
auto value = recomp::get_config_store_value<std::string>("translations/" + config_key);
SetTextLabel(value);
} catch (const std::runtime_error& e) {
SetTextLabel(e.what());
}
const json& group_json = get_json_from_key(config_key);
from_json(group_json["type"], option_type);
assert(
option_type == ConfigOptionType::Group || option_type == ConfigOptionType::CheckboxGroup);
}
const nlohmann::json& options = get_options(config_key);
for (int i = 0; i < options.size(); i++) {
const auto &el = options[i];
AddConfigOptionElement(el);
}
DirtyLayout();
}
}
} // namespace Rml