The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
gui.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#define GETTEXT_DOMAIN "wesnoth-lib"
17
18#include "gui/gui.hpp"
19
20#include "config_cache.hpp"
21#include "filesystem.hpp"
22#include "gettext.hpp"
23#include "gui/core/log.hpp"
29#include "wml_exception.hpp"
30
31namespace gui2
32{
33namespace
34{
35config read_and_validate(const std::string& path)
36try {
37 preproc_map defines;
38#ifdef __ANDROID__
39 defines.try_emplace("ANDROID");
40#endif
42 return io::read(*preprocess_file(path, defines), &validator);
43
44} catch(const utils::bad_optional_access&) {
45 FAIL("GUI2: schema/gui.cfg not found.");
46
47} catch(const abstract_validator::error& e) {
48 FAIL("GUI2: could not read schema file: " + e.message);
49
50} catch(const config::error& e) {
51 ERR_GUI_P << "Could not read gui file: " << path;
52 ERR_GUI_P << e.what();
53 return {};
54}
55
56/**
57 * Adds a theme definition object to the global registry.
58 *
59 * @param def A valid gui_definition config.
60 *
61 * @returns An optional iterator to the newly-constructed definition.
62 * If gui_definition throws wml_exception or a theme with the
63 * given ID already exists, returns nullopt.
64 */
65auto register_theme(const config& def) -> utils::optional<gui_theme_map_t::iterator>
66try {
67 auto [iter, is_unique] = guis.try_emplace(def["id"], def);
68 if(is_unique) return iter;
69
70 ERR_GUI_P << "UI Theme '" << def["id"] << "' already exists.";
71 return utils::nullopt;
72
73} catch(const wml_exception& e) {
74 ERR_GUI_P << "Invalid UI theme: " << def["id"];
75 ERR_GUI_P << e.user_message;
76 return utils::nullopt;
77}
78
79/**
80 * Parses any GUI2 theme definitions at the file path specified.
81 *
82 * @param full_path Path to file containing one or more [gui] tags.
83 * @param is_core If true, look for the default theme here.
84 */
85void parse(const std::string& full_path, bool is_core)
86{
87 config cfg = read_and_validate(full_path);
88 for(const config& def : cfg.child_range("gui")) {
89 const bool is_default = def["id"] == "default";
90
91 if(is_default && !is_core) {
92 ERR_GUI_P << "UI theme id 'default' is reserved for core themes.";
93 continue;
94 }
95
96 const auto iter = register_theme(def);
97 if(!iter) continue;
98
99 if(is_default && is_core) {
100 default_gui = *iter;
102 }
103 }
104}
105
106} // namespace
107
108void init()
109{
110 LOG_GUI_G << "Initializing UI subststem.";
111
112 // Reset the registry in case we're re-initializing
113 guis.clear();
114
115 // Save current screen size.
117
118 //
119 // Parse GUI definitions from mainline
120 //
121
122 try {
123 parse(filesystem::get_wml_location("gui/_main.cfg").value(), true);
124 } catch(const utils::bad_optional_access&) {
125 FAIL("GUI2: gui/_main.cfg not found.");
126 }
127
128 // The default GUI must be in mainline
129 VALIDATE(default_gui != guis.end(), _("No default gui defined."));
130
131 //
132 // Parse GUI definitions from addons
133 //
134
135 std::vector<std::string> addon_dirs;
136 const std::string umc_dir = filesystem::get_addons_dir();
138
139 // Search for all $user_campaign_dir/*/gui-theme.cfg files
140 for(const std::string& umc : addon_dirs) {
141 const std::string gui_file = umc + "/gui-theme.cfg";
142
143 if(filesystem::file_exists(gui_file)) {
144 parse(gui_file, false);
145 }
146 }
147}
148
149void switch_theme(const std::string& theme_id)
150{
151 if(theme_id.empty() || theme_id == "default") {
153 } else {
155 [&](const auto& theme) { return theme.first; });
156
157 if(current_gui == guis.end()) {
158 ERR_GUI_P << "Missing [gui] definition for '" << theme_id << "'";
160 }
161 }
162
163 current_gui->second.activate();
164}
165
166} // namespace gui2
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
child_itors child_range(std::string_view key)
Definition config.cpp:268
Realization of serialization/validator.hpp abstract validator.
const config * cfg
Declarations for File-IO.
static std::string _(const char *str)
Definition gettext.hpp:100
Define the common log macros for the gui toolkit.
#define LOG_GUI_G
Definition log.hpp:42
#define ERR_GUI_P
Definition log.hpp:69
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs=nullptr, name_mode mode=name_mode::FILE_NAME_ONLY, filter_mode filter=filter_mode::NO_FILTER, reorder_mode reorder=reorder_mode::DONT_REORDER, file_tree_checksum *checksum=nullptr)
Get a list of all files and/or directories in a given directory.
utils::optional< std::string > get_wml_location(const std::string &path, const utils::optional< std::string > &current_dir=utils::nullopt)
Returns a translated path to the actual file or directory, if it exists.
std::string get_addons_dir()
void update_screen_size_variables()
Update the size of the screen variables in settings.
Definition settings.cpp:59
Generic file dialog.
void init()
Initializes the GUI subsystems.
Definition gui.cpp:108
gui_theme_map_t guis
Map of all known GUIs.
void switch_theme(const std::string &theme_id)
Set and activate the given gui2 theme.
Definition gui.cpp:149
gui_theme_map_t::iterator current_gui
Iterator pointing to the current GUI.
gui_theme_map_t::iterator default_gui
Iterator pointing to the default GUI.
config read(std::istream &in, abstract_validator *validator)
Definition parser.cpp:610
auto find(Container &container, const Value &value, const Projection &projection={})
Definition general.hpp:213
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map &defines)
Function to use the WML preprocessor on a file.
std::map< std::string, struct preproc_define > preproc_map
One of the realizations of serialization/validator.hpp abstract validator.
This file contains the settings handling of the widget library.
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition sound.cpp:139
Used to manage with not initialized validators Supposed to be thrown from the constructor.
Definition validator.hpp:97
Helper class, don't construct this directly.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define FAIL(message)
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
#define e