The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
mp_options.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012 - 2016 by Boldizsár Lipka <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "mp_options.hpp"
16 #include "gettext.hpp"
20 #include "gui/widgets/button.hpp"
21 #include "gui/widgets/slider.hpp"
22 #include "gui/widgets/text_box.hpp"
24 #include "widgets/slider.hpp"
25 #include "widgets/textbox.hpp"
26 #include "utils/functional.hpp"
27 
28 static lg::log_domain log_mp_create_options("mp/create/options");
29 #define DBG_MP LOG_STREAM(debug, log_mp_create_options)
30 
31 namespace mp
32 {
33 
34 namespace options
35 {
36 
37 void manager::init_info(const config& cfg, const std::string& key)
38 {
39  for (const config& comp : cfg.child_range(key)) {
40  config entry;
41  entry["id"] = comp["id"];
42  entry["name"] = comp["name"];
43 
44  if (comp.has_child("options") && comp["allow_new_game"].to_bool(true)) {
45  const config& options = comp.child("options");
46 
47  for (const config::any_child& c : options.all_children_range()) {
48  entry.add_child(c.key, c.cfg);
49  }
50 
51  }
52 
53  // We need to store components even if they don't have any options in
54  // order to have set_xxx_by_index work properly
55  options_info_.add_child(key, entry);
56  }
57 }
58 
60 {
61  for (option_display* od : widgets_ordered_) {
62  delete od;
63  }
64 
65  widgets_.clear();
66  widgets_ordered_.clear();
67 
68  for (const config::any_child& comp : options_info_.all_children_range()) {
69  if (comp.cfg.all_children_count() == 0 || !is_active(comp.cfg["id"])) {
70  continue;
71  }
72 
73  widgets_ordered_.push_back(new title_display(video_, comp.cfg["name"]));
74  for (const config::any_child& c : comp.cfg.all_children_range()) {
75  const std::string id = c.cfg["id"];
76  if (c.key == "slider") {
77  widgets_ordered_.push_back(new slider_display(video_, c.cfg));
78  } else if (c.key == "entry") {
79  widgets_ordered_.push_back(new entry_display(video_, c.cfg));
80  } else if (c.key == "checkbox") {
81  widgets_ordered_.push_back(new checkbox_display(video_, c.cfg));
82  } else if (c.key == "combo") {
83  widgets_ordered_.push_back(new combo_display(video_, c.cfg));
84  }
85  widgets_ordered_.back()->set_value(get_stored_value(id));
86  widgets_[id] = widgets_ordered_.back();
87  }
88  widgets_ordered_.push_back(new reset_display(video_, comp.cfg["id"], *this));
89  }
90 }
91 
92 void manager::restore_defaults(const std::string &component)
93 {
94  for (const config::any_child& i : get_component_cfg(component).all_children_range()) {
95  if (!is_valid_option(i.key, i.cfg)) {
96  continue;
97  }
98 
99  const std::string id = i.cfg["id"].str();
100 
101  widgets_[id]->set_value(get_default_value(id));
102  }
103 }
104 
106 {
107  return !widgets_.empty();
108 }
109 
110 manager::manager(const config &gamecfg, CVideo &video, gui::scrollpane *pane, const config &values)
111  : options_info_()
112  , values_(values)
113  , video_(video)
114  , pane_(pane)
115  , era_()
116  , scenario_()
117  , is_campaign_()
118  , modifications_()
119  , widgets_()
120  , widgets_ordered_()
121 {
122  DBG_MP << "Initializing the options manager" << std::endl;
123  init_info(gamecfg, "modification");
124  init_info(gamecfg, "era");
125  init_info(gamecfg, "multiplayer");
126  init_info(gamecfg, "campaign");
127 
129  {
130  for (const config::any_child& j : i.cfg.all_children_range())
131  {
132  if (is_valid_option(j.key, j.cfg)) {
133  config& value = get_value_cfg(j.cfg["id"]);
134  value["value"] = get_stored_value(j.cfg["id"]);
135  }
136  }
137  }
138 
139  init_widgets();
140 }
141 
143 {
144  for (option_display* od : widgets_ordered_)
145  {
146  delete od;
147  }
148 }
149 
150 
152 {
153  values_ = c;
154 }
155 
157 {
158  era_ = era;
159 }
160 
161 void manager::set_scenario(const std::string& scenario)
162 {
163  is_campaign_ = false;
164  scenario_ = scenario;
165 }
166 
167 void manager::set_campaign(const std::string& campaign)
168 {
169  is_campaign_ = true;
170  scenario_ = campaign;
171 }
172 
173 void manager::set_modifications(const std::vector<std::string>& modifications)
174 {
176 }
177 
178 void manager::layout_widgets(int startx, int starty, int w)
179 {
180  int ypos = starty;
181  int border_size = 3;
182  for (option_display* od : widgets_ordered_)
183  {
184  od->layout(startx, ypos, w, border_size, pane_);
185  ypos += border_size;
186  }
187 }
188 
190 {
191  for (size_t i = 0; i<widgets_ordered_.size(); ++i)
192  {
193  widgets_ordered_[i]->process_event();
194  }
195 }
196 
197 void manager::hide_children(bool hide)
198 {
200  i != widgets_.end(); ++i)
201  {
202  i->second->hide_children(hide);
203  }
204 }
205 
206 
208 {
209  update_values();
210  return values_;
211 }
212 
214 {
215  {
216  const config& value_cfg = get_value_cfg_or_empty(id);
217  if (!value_cfg.empty()) {
218  return const_cast<config&>(value_cfg);
219  }
220  }
221 
223  config* parent_cfg;
224  if (!values_.find_child(info.key, "id", info.cfg["id"])) {
225  parent_cfg = &values_.add_child(info.key);
226  (*parent_cfg)["id"] = info.cfg["id"];
227  } else {
228  parent_cfg = &values_.find_child(info.key, "id", info.cfg["id"]);
229  }
230 
231  config& value_cfg = parent_cfg->add_child("option");
232  value_cfg["id"] = id;
233 
234  return value_cfg;
235 }
236 
238 {
239  static const config empty;
240 
241  for (const config::any_child& i : values_.all_children_range()) {
242  for (const config& j : i.cfg.child_range("option")) {
243  if (j["id"] == id) {
244  return j;
245  }
246  }
247  }
248 
249  return empty;
250 }
251 
253 {
254  static const config empty;
255  static const std::string empty_key = "";
256  static config::any_child not_found(&empty_key, &empty);
257 
259  for (const config::any_child& j : i.cfg.all_children_range()) {
260  if (j.cfg["id"] == id) {
261  return i;
262  }
263  }
264  }
265 
266  return not_found;
267 }
268 
270 {
271  static const config empty;
272 
274  for (const config::any_child& j : i.cfg.all_children_range()) {
275  if (j.cfg["id"] == id) {
276  return j.cfg;
277  }
278  }
279  }
280 
281  return empty;
282 }
283 
285 {
286  static const config empty;
287  const config &m = options_info_.find_child("modification", "id", id);
288  if (m) {
289  return m;
290  }
291  const config &s = options_info_.find_child("scenario", "id", id);
292  if (s) {
293  return s;
294  }
295  const config &e = options_info_.find_child("era", "id", id);
296  if (e) {
297  return e;
298  }
299  return empty;
300 }
301 
302 
304 {
305  const config& valcfg = get_value_cfg_or_empty(id);
306 
307  if (!valcfg["value"].empty()) {
308  // There's a saved value for this option
309  return valcfg["value"];
310  }
311 
312  // Fall back to the option's default
313  return get_default_value(id);
314 }
315 
317 {
318  const config& optinfo = get_option_info_cfg(id);
319 
320  return optinfo["default"];
321 }
322 
324 {
325  for (const config::any_child& c : options_info_.find_child(key, "id", id).all_children_range())
326  {
327  if (!is_valid_option(c.key, c.cfg)) {
328  continue;
329  }
330 
331  config& out = get_value_cfg(c.cfg["id"].str());
332  out["value"] = widgets_[c.cfg["id"]]->get_value();
333  }
334 }
335 
337 {
338  extract_values("era", era_);
339  if (is_campaign_) {
340  extract_values("campaign", scenario_);
341  }
342  else {
343  extract_values("multiplayer", scenario_);
344  }
345  for (const std::string& str : modifications_) {
346  extract_values("modification", str);
347  }
348 }
349 
351 {
352  return (key == "slider" || key == "entry" || key == "checkbox" || key == "combo") &&
353  (!option["id"].empty());
354 }
355 
356 bool manager::is_active(const std::string &id) const
357 {
358  return (era_ == id) || (scenario_ == id) ||
359  (std::find(modifications_.begin(), modifications_.end(), id) != modifications_.end());
360 }
361 
363  entry_(new gui::textbox(video, 150, cfg["default"])),
364  label_(new gui::label(video, cfg["name"]))
365 {
366  entry_->set_help_string(cfg["description"]);
367 }
368 
370 {
371  delete entry_;
372  delete label_;
373 }
374 
375 void entry_display::layout(int &xpos, int &ypos, int /*w*/, int border_size, gui::scrollpane *pane)
376 {
377  pane->add_widget(label_, xpos, ypos);
378  pane->add_widget(entry_, xpos + label_->width() + border_size, ypos);
379  ypos += std::max(label_->height(), entry_->height()) + border_size;
380 }
381 
383 {
384  entry_->set_text(val);
385 }
386 
388 {
390  res = entry_->text();
391  return res;
392 }
393 
395 {
396  label_->hide(hide);
397  entry_->hide(hide);
398 }
399 
401  slider_(new gui::slider(video)),
402  label_(new gui::label(video, cfg["name"], font::SIZE_SMALL)),
403  last_value_(cfg["default"].to_int()),
404  label_text_(cfg["name"])
405 {
406  slider_->set_min(cfg["min"].to_int());
407  slider_->set_max(cfg["max"].to_int());
408  slider_->set_increment(cfg["step"].to_int());
409  slider_->set_value(cfg["default"].to_int());
410 
411  slider_->set_help_string(cfg["description"]);
412 
413  update_label();
414 }
415 
417 {
418  delete slider_;
419  delete label_;
420 }
421 
422 void slider_display::layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
423 {
424  pane->add_widget(label_, xpos, ypos);
425  ypos += label_->height() + border_size;
426  pane->add_widget(slider_, xpos, ypos);
427  slider_->set_width(w - border_size);
428  ypos += slider_->height() + border_size;
429 }
430 
432 {
433  slider_->set_value(val.to_int());
434 }
435 
437 {
439  res = slider_->value();
440  return res;
441 }
442 
444 {
445  if (slider_->value() != last_value_) {
447  update_label();
448  }
449 }
450 
452 {
453  label_->hide(hide);
454  slider_->hide(hide);
455 }
456 
458 {
459  std::stringstream ss;
460  ss << label_text_ << ' ' << last_value_;
461  label_->set_text(ss.str());
462 }
463 
465  checkbox_(new gui::button(video, cfg["name"], gui::button::TYPE_CHECK))
466 {
467  checkbox_->set_check(cfg["default"].to_bool());
468  checkbox_->set_help_string(cfg["description"]);
469 }
470 
472 {
473  delete checkbox_;
474 }
475 
476 void checkbox_display::layout(int &xpos, int &ypos, int /*w*/, int border_size, gui::scrollpane *pane)
477 {
478  pane->add_widget(checkbox_, xpos, ypos);
479  ypos += checkbox_->height() + border_size;
480 }
481 
483 {
484  checkbox_->set_check(val.to_bool());
485 }
486 
488 {
490  res = checkbox_->checked();
491  return res;
492 }
493 
495 {
496  checkbox_->hide(hide);
497 }
498 
500  title_(new gui::label(video, "`~" + label, font::SIZE_PLUS, font::LOBBY_COLOR))
501 {}
502 
504 {
505  delete title_;
506 }
507 
508 void title_display::layout(int &xpos, int &ypos, int /*w*/, int border_size, gui::scrollpane *pane)
509 {
510  ypos += 4*border_size;
511  pane->add_widget(title_, xpos, ypos);
512  ypos += title_->height() + 2*border_size;
513 }
514 
516 {
517  title_->hide(hide);
518 }
519 
521  label_(new gui::label(video, cfg["name"])),
522  combo_(new gui::combo(video, std::vector<std::string>())),
523  values_()
524 {
525  std::vector<std::string> items;
526  for (const config& item : cfg.child_range("item")) {
527  items.push_back(item["name"]);
528  values_.push_back(item["value"]);
529  }
530 
531  combo_->set_items(items);
532  combo_->set_help_string(cfg["description"]);
533  set_value(cfg["default"]);
534 }
535 
537 {
538  delete label_;
539  delete combo_;
540 }
541 
542 void combo_display::layout(int &xpos, int &ypos, int /*w*/, int border_size, gui::scrollpane *pane)
543 {
544  pane->add_widget(label_, xpos, ypos);
545  pane->add_widget(combo_, xpos + label_->width() + border_size, ypos);
546  ypos += std::max(label_->height(), combo_->height()) + border_size;
547 }
548 
550 {
551  const std::string value = val;
552  for (size_t i = 0; i<values_.size(); i++) {
553  if (value == values_[i]) {
554  combo_->set_selected(i);
555  break;
556  }
557  }
558 }
559 
561 {
563  res = values_[combo_->selected()];
564  return res;
565 }
566 
568 {
569  label_->hide(hide);
570  combo_->hide(hide);
571 }
572 
574  : manager_(m)
575  , component_(comp)
576  , button_(new gui::button(video, _("Defaults")))
577 {}
578 
580 {
581  delete button_;
582 }
583 
584 void reset_display::layout(int &/*xpos*/, int &ypos, int w, int border_size, gui::scrollpane *pane)
585 {
586  pane->add_widget(button_, w-border_size-button_->width(), ypos);
587  ypos += button_->height() + border_size;
588 }
589 
591 {
592  button_->hide(hide);
593 }
594 
596 {
597  if (button_->pressed()) {
599  }
600 }
601 
602 } // namespace options
603 
604 } // namespace mp
605 
static lg::log_domain log_mp_create_options("mp/create/options")
child_itors child_range(const std::string &key)
Definition: config.cpp:613
void restore_defaults(const std::string &component)
Definition: mp_options.cpp:92
title_display(CVideo &video, const std::string &label)
Definition: mp_options.cpp:499
void set_check(bool check)
Definition: button.cpp:352
void set_value(const config::attribute_value &val)
Definition: mp_options.cpp:382
entry_display(CVideo &video, const config &cfg)
Definition: mp_options.cpp:362
CVideo & video_
The screen to display the dialog on.
Definition: mp_options.hpp:233
const std::string & set_text(const std::string &text)
Definition: label.cpp:35
std::string era()
gui::scrollpane * pane_
The scrollarea to put the widgets on.
Definition: mp_options.hpp:236
Graphical text output.
const GLfloat * c
Definition: glew.h:12741
virtual void hide_children(bool hide)
Definition: mp_options.cpp:515
void set_value(int value)
Definition: slider.cpp:87
std::string era_
The id of the selected era.
Definition: mp_options.hpp:239
bool to_bool(bool def=false) const
Definition: config.cpp:275
int value() const
Definition: slider.cpp:112
void hide_children(bool hide=true)
Definition: mp_options.cpp:197
void layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
Definition: mp_options.cpp:584
logger & info()
Definition: log.cpp:91
void set_max(int value)
Definition: slider.cpp:77
Definition: video.hpp:58
void set_scenario(const std::string &id)
Sets the selected scenario.
Definition: mp_options.cpp:161
std::vector< std::string > modifications_
The ids of the selected modifications.
Definition: mp_options.hpp:245
config options_info_
Stores needed info about each element and their configuration options.
Definition: mp_options.hpp:227
General purpose widgets.
void set_width(int w)
Definition: widget.cpp:119
void set_increment(int increment)
Definition: slider.cpp:107
void layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
Definition: mp_options.cpp:476
GLuint const GLfloat * val
Definition: glew.h:2614
config values_
Stores the selected values for each option.
Definition: mp_options.hpp:230
void set_text(const std::string &text, const SDL_Color &color=font::NORMAL_COLOR)
Definition: textbox.cpp:76
#define DBG_MP
Definition: mp_options.cpp:29
STL namespace.
Scrollpane.
Definition: scrollpane.hpp:30
void set_modifications(const std::vector< std::string > &ids)
Sets the activated modifications.
Definition: mp_options.cpp:173
const std::vector< std::string > items
const std::string text() const
Definition: textbox.cpp:69
const int SIZE_PLUS
Definition: font.hpp:65
reset_display(CVideo &video, const std::string &comp, manager &m)
Definition: mp_options.cpp:573
void init_info(const config &cfg, const std::string &key)
Adds the necessary information about the specified component to options_info_.
Definition: mp_options.cpp:37
std::string scenario_
The id of the selected [multiplayer] or [campaign].
Definition: mp_options.hpp:242
GLuint GLenum option
Definition: glew.h:2815
bool empty() const
Definition: config.cpp:1105
int selected() const
Definition: combo.cpp:38
const config & cfg
Definition: config.hpp:629
Variant for storing WML attributes.
Definition: config.hpp:223
config::attribute_value get_value() const
Definition: mp_options.cpp:560
GLboolean GLenum GLenum GLvoid * values
Definition: glew.h:3799
bool is_active(const std::string &id) const
Definition: mp_options.cpp:356
This module controls the multiplayer lobby.
config::attribute_value get_default_value(const std::string &id) const
Retrieves the default value for a certain option.
Definition: mp_options.cpp:316
const config & options()
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
void layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
Definition: mp_options.cpp:375
GLuint id
Definition: glew.h:1647
void hide_children(bool hide)
Definition: mp_options.cpp:590
const config & get_component_cfg(const std::string &id) const
Definition: mp_options.cpp:284
virtual void hide(bool value=true)
Definition: widget.cpp:162
virtual void hide_children(bool hide)
Definition: mp_options.cpp:494
std::map< std::string, option_display * > widgets_
Definition: mp_options.hpp:247
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
GLsizei const GLfloat * value
Definition: glew.h:1817
all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:1127
const child_map::key_type & key
Definition: config.hpp:628
config & get_value_cfg(const std::string &id)
Returns the node which holds the selected value of an option.
Definition: mp_options.cpp:213
void set_era(const std::string &id)
Sets the selected era.
Definition: mp_options.cpp:156
void extract_values(const std::string &key, const std::string &id)
Writes all the values for the options of a certain component from a specified window into values_...
Definition: mp_options.cpp:323
void layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
Definition: mp_options.cpp:422
slider_display(CVideo &video, const config &cfg)
Definition: mp_options.cpp:400
config & add_child(const std::string &key)
Definition: config.cpp:743
bool pressed()
Definition: button.cpp:770
checkbox_display(CVideo &video, const config &cfg)
Definition: mp_options.cpp:464
std::vector< std::string > values_
Definition: mp_options.hpp:112
virtual void hide_children(bool hide)
Definition: mp_options.cpp:451
void set_help_string(const std::string &str)
Definition: widget.cpp:314
const std::string label_text_
Definition: mp_options.hpp:80
std::vector< option_display * > widgets_ordered_
Definition: mp_options.hpp:248
GLuint res
Definition: glew.h:9258
void set_selected(int val)
Definition: combo.cpp:68
void layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
Definition: mp_options.cpp:542
manager(const config &gamecfg, CVideo &video, gui::scrollpane *pane, const config &initial_value)
Constructor.
Definition: mp_options.cpp:110
bool has_options() const
Definition: mp_options.cpp:105
config::any_child get_option_parent(const std::string &id) const
Finds the parent node of an options.
Definition: mp_options.cpp:252
void layout(int &xpos, int &ypos, int w, int border_size, gui::scrollpane *pane)
Definition: mp_options.cpp:508
combo_display(CVideo &video, const config &cfg)
Definition: mp_options.cpp:520
const SDL_Color LOBBY_COLOR
Definition: font.cpp:566
size_t i
Definition: function.cpp:1057
void set_items(const std::vector< std::string > &items)
Definition: combo.cpp:52
config::attribute_value get_value() const
Definition: mp_options.cpp:387
config::attribute_value get_stored_value(const std::string &id) const
Retrieves the saved value for a certain option, or the default, if there's no such.
Definition: mp_options.cpp:303
void set_value(const config::attribute_value &val)
Definition: mp_options.cpp:549
void set_value(const config::attribute_value &val)
Definition: mp_options.cpp:431
virtual void hide(bool value=true)
Definition: scrollarea.cpp:78
virtual void hide_children(bool hide)
Definition: mp_options.cpp:394
const config & get_option_info_cfg(const std::string &id) const
Returns the information about an option.
Definition: mp_options.cpp:269
const std::vector< std::string > & modifications(bool mp)
const GLdouble * m
Definition: glew.h:6968
bool find(E event, F functor)
Tests whether an event handler is available.
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
void set_campaign(const std::string &id)
Sets the selected campaign.
Definition: mp_options.cpp:167
bool checked() const
Definition: button.cpp:381
config & find_child(const std::string &key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition: config.cpp:1010
config::attribute_value get_value() const
Definition: mp_options.cpp:487
config::attribute_value get_value() const
Definition: mp_options.cpp:436
void set_min(int value)
Definition: slider.cpp:67
const config & get_value_cfg_or_empty(const std::string &id) const
Returns the node which holds the selected value of an option.
Definition: mp_options.cpp:237
#define c
Definition: glew.h:12743
int to_int(int def=0) const
Definition: config.cpp:308
#define e
int width() const
Definition: widget.cpp:134
const config & get_values()
Returns the the values for each option.
Definition: mp_options.cpp:207
void hide_children(bool hide)
Definition: mp_options.cpp:567
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLdouble s
Definition: glew.h:1358
static bool is_valid_option(const std::string &key, const config &option)
Decides whether a config is a sane option node or not.
Definition: mp_options.cpp:350
void add_widget(widget *w, int x, int y, int z_order=0)
Definition: scrollpane.cpp:71
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void layout_widgets(int startx, int starty, int w)
Definition: mp_options.cpp:178
const int SIZE_SMALL
Definition: font.hpp:62
void set_values(const config &values)
Set the current values the options.
Definition: mp_options.cpp:151
int height() const
Definition: widget.cpp:139
void set_value(const config::attribute_value &val)
Definition: mp_options.cpp:482