The Battle for Wesnoth  1.19.5+dev
gui.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
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"
25 #include "gui/widgets/settings.hpp"
26 #include "serialization/parser.hpp"
29 #include "wml_exception.hpp"
30 
31 namespace gui2
32 {
33 
34 void init()
35 {
36  LOG_GUI_G << "Initializing UI subststem.";
37 
38  // Save current screen size.
40 
41  config guis_cfg, addons_cfg;
42  preproc_map preproc(game_config::config_cache::instance().get_preproc_map());
43 
44  //
45  // Read and validate theme WML files from mainline
46  //
47  std::string current_file;
48  const std::string schema_file = "schema/gui.cfg";
49  try {
51 
52  // Core theme files
53  current_file = "gui/_main.cfg";
54  filesystem::scoped_istream stream = preprocess_file(filesystem::get_wml_location(current_file).value(), &preproc);
55  read(guis_cfg, *stream, &validator);
56 
57  } catch(const config::error& e) {
58  ERR_GUI_P << e.what();
59  ERR_GUI_P << "Setting: could not read gui file: " << current_file;
60  } catch(const abstract_validator::error& e) {
61  ERR_GUI_P << "Setting: could not read schema file: " << schema_file;
62  ERR_GUI_P << e.message;
63  }
64 
65  //
66  // Read and validate theme WML files from addons
67  //
68 
69  // Add the $user_campaign_dir/*/gui.cfg files to the addon gui config.
70  std::vector<std::string> user_dirs;
71  {
72  const std::string user_campaign_dir = filesystem::get_addons_dir();
73  std::vector<std::string> user_files;
75  user_campaign_dir, &user_files, &user_dirs, filesystem::name_mode::ENTIRE_FILE_PATH);
76  }
77 
78  for(const std::string& umc : user_dirs) {
79  try {
80  const std::string gui_file = umc + "/gui-theme.cfg";
81  current_file = filesystem::get_short_wml_path(gui_file);
82  if(filesystem::file_exists(gui_file)) {
83  config addon_cfg;
85  read(addon_cfg, *preprocess_file(gui_file, &preproc), &validator);
86  addons_cfg.append(addon_cfg);
87  }
88  } catch(const config::error& e) {
89  ERR_GUI_P << e.what();
90  ERR_GUI_P << "Setting: could not read gui file: " << current_file;
91  } catch(const abstract_validator::error& e) {
92  ERR_GUI_P << "Setting: could not read schema file: " << schema_file;
93  ERR_GUI_P << e.message;
94  }
95  }
96 
97  //
98  // Parse GUI definitions from mainline
99  //
100  for(const config& g : guis_cfg.child_range("gui")) {
101  const std::string id = g["id"];
102 
103  auto [iter, is_unique] = guis.try_emplace(id, g);
104 
105  if (!is_unique) {
106  ERR_GUI_P << "GUI Theme ID '" << id << "' already exists.";
107  } else {
108  if(id == "default") {
109  default_gui = iter;
110  }
111  }
112  }
113 
114  //
115  // Parse GUI definitions from addons
116  //
117  for(const config& g : addons_cfg.child_range("gui")) {
118  const std::string id = g["id"];
119 
120  try {
121  auto [iter, is_unique] = guis.try_emplace(id, g);
122 
123  if (!is_unique) {
124  ERR_GUI_P << "GUI Theme ID '" << id << "' already exists.";
125  }
126  } catch (const wml_exception& e) {
127  ERR_GUI_P << "Non-functional theme: " << id;
128  ERR_GUI_P << e.user_message;
129  }
130  }
131 
132  VALIDATE(default_gui != guis.end(), _("No default gui defined."));
133 }
134 
135 void switch_theme(const std::string& current_theme)
136 {
137  if (current_theme.empty() || current_theme == "default") {
139  } else {
140  gui_theme_map_t::iterator gui_itor = guis.begin();
141  for (const auto& gui : guis) {
142  if (gui.first == current_theme) {
143  current_gui = gui_itor;
144  }
145 
146  if (gui_itor != guis.end()) {
147  gui_itor++;
148  }
149  }
150 
151  if(current_gui == guis.end()) {
152  ERR_GUI_P << "Missing [gui] definition for '" << current_theme << "'";
154  }
155  }
156 
157  current_gui->second.activate();
158 }
159 
160 } // namespace gui2
double g
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:203
child_itors child_range(config_key_type key)
Definition: config.cpp:272
static config_cache & instance()
Get reference to the singleton object.
Realization of serialization/validator.hpp abstract validator.
Declarations for File-IO.
static std::string _(const char *str)
Definition: gettext.hpp:93
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
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:198
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
Definition: filesystem.cpp:444
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:325
utils::optional< std::string > get_wml_location(const std::string &path, const utils::optional< std::string > &current_dir)
Returns a translated path to the actual file or directory, if it exists.
std::unique_ptr< std::istream > scoped_istream
Definition: filesystem.hpp:53
std::string get_short_wml_path(const std::string &filename)
Returns a short path to filename, skipping the (user) data directory.
std::string get_addons_dir()
void update_screen_size_variables()
Update the size of the screen variables in settings.
Definition: settings.cpp:57
Generic file dialog.
void init()
Initializes the GUI subsystems.
Definition: gui.cpp:34
gui_theme_map_t guis
Map of all known GUIs.
void switch_theme(const std::string &current_theme)
Set and activate the given gui2 theme.
Definition: gui.cpp:135
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.
General purpose widgets.
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
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.
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:622
This file contains the settings handling of the widget library.
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 VALIDATE(cond, message)
The macro to use for the validation of WML.
#define e