diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 98cfb932c5b..ff7e763c262 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -32,93 +32,78 @@ namespace gui2 { namespace { -class theme_parser +config read_and_validate(const std::string& path) +try { + preproc_map defines; + schema_validation::schema_validator validator{filesystem::get_wml_location("schema/gui.cfg").value()}; + filesystem::scoped_istream stream = preprocess_file(path, &defines); + return ::read(*stream, &validator); + +} catch(const utils::bad_optional_access&) { + FAIL("GUI2: schema/gui.cfg not found."); + +} catch(const abstract_validator::error& e) { + FAIL("GUI2: could not read schema file: " + e.message); + +} catch(const config::error& e) { + ERR_GUI_P << "Could not read gui file: " << path; + ERR_GUI_P << e.what(); + return {}; +} + +/** + * Adds a theme definition object to the global registry. + * + * @param def A valid gui_definition config. + * + * @returns An optional iterator to the newly-constructed definition. + * If gui_definition throws wml_exception or a theme with the + * given ID already exists, returns nullopt. + */ +auto register_theme(const config& def) -> utils::optional +try { + auto [iter, is_unique] = guis.try_emplace(def["id"], def); + if(is_unique) return iter; + + ERR_GUI_P << "UI Theme '" << def["id"] << "' already exists."; + return utils::nullopt; + +} catch(const wml_exception& e) { + ERR_GUI_P << "Invalid UI theme: " << def["id"]; + ERR_GUI_P << e.user_message; + return utils::nullopt; +} + +/** + * Parses any GUI2 theme definitions at the file path specified. + * + * @param full_path Path to file containing one or more [gui] tags. + * @param is_core If true, look for the default theme here. + */ +void parse(const std::string& full_path, bool is_core) { -public: - theme_parser() - try - : validator_(filesystem::get_wml_location("schema/gui.cfg").value()) - , defines_(game_config::config_cache::instance().get_preproc_map()) - { - guis.clear(); // Reset in case we're re-initializing the UI subsystem - } catch(const utils::bad_optional_access&) { - FAIL("GUI2: schema/gui.cfg not found."); - } catch(const abstract_validator::error& e) { - FAIL("GUI2: could not read schema file: " + e.message); - } - - /** - * Parses any GUI2 theme definitions at the file path specified. - * - * @param full_path Path to file containing one or more [gui] tags. - * @param is_core If true, look for the default theme here. - */ - void parse(const std::string& full_path, bool is_core) - { #if __cpp_range_based_for >= 202211L // lifetime extension of temporaries - for(const config& def : read_and_validate(full_path).child_range("gui")) { + for(const config& def : read_and_validate(full_path).child_range("gui")) { #else - config cfg = read_and_validate(full_path); - for(const config& def : cfg.child_range("gui")) { + config cfg = read_and_validate(full_path); + for(const config& def : cfg.child_range("gui")) { #endif - const bool is_default = def["id"] == "default"; + const bool is_default = def["id"] == "default"; - if(is_default && !is_core) { - ERR_GUI_P << "UI theme id 'default' is reserved for core themes."; - continue; - } + if(is_default && !is_core) { + ERR_GUI_P << "UI theme id 'default' is reserved for core themes."; + continue; + } - const auto iter = register_theme(def); - if(!iter) continue; + const auto iter = register_theme(def); + if(!iter) continue; - if(is_default && is_core) { - default_gui = *iter; - current_gui = default_gui; - } + if(is_default && is_core) { + default_gui = *iter; + current_gui = default_gui; } } - -private: - auto read_and_validate(const std::string& path) -> config - try { - filesystem::scoped_istream stream = preprocess_file(path, &defines_); - return ::read(*stream, &validator_); - - } catch(const config::error& e) { - ERR_GUI_P << "Could not read gui file: " << path; - ERR_GUI_P << e.what(); - return {}; - }; - - /** - * Adds a theme definition object to the global registry. - * - * @param def A valid gui_definition config. - * - * @returns An optional iterator to the newly-constructed definition. - * If errors occurred while parsing the config or a theme with - * the given ID already exists, returns nullopt. - */ - auto register_theme(const config& def) const -> utils::optional - try { - auto [iter, is_unique] = guis.try_emplace(def["id"], def); - if(is_unique) return iter; - - ERR_GUI_P << "UI Theme '" << def["id"] << "' already exists."; - return utils::nullopt; - - } catch(const wml_exception& e) { - ERR_GUI_P << "Invalid UI theme: " << def["id"]; - ERR_GUI_P << e.user_message; - return utils::nullopt; - } - - /** GUI2 schema validator. */ - schema_validation::schema_validator validator_; - - /** Common macro context shared by all themes (@todo: document this fact). */ - preproc_map defines_; -}; +} } // namespace @@ -126,6 +111,9 @@ void init() { LOG_GUI_G << "Initializing UI subststem."; + // Reset the registry in case we're re-initializing + guis.clear(); + // Save current screen size. settings::update_screen_size_variables(); @@ -133,10 +121,8 @@ void init() // Parse GUI definitions from mainline // - theme_parser parser; - try { - parser.parse(filesystem::get_wml_location("gui/_main.cfg").value(), true); + parse(filesystem::get_wml_location("gui/_main.cfg").value(), true); } catch(const utils::bad_optional_access&) { FAIL("GUI2: gui/_main.cfg not found."); } @@ -157,7 +143,7 @@ void init() const std::string gui_file = umc + "/gui-theme.cfg"; if(filesystem::file_exists(gui_file)) { - parser.parse(gui_file, false); + parse(gui_file, false); } } }