The Battle for Wesnoth  1.19.7+dev
gamestate_inspector.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2024
3  by Yurii Chernyi <terraninfo@terraninfo.net>
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 
19 
21 #include "gui/widgets/button.hpp"
22 #include "gui/widgets/label.hpp"
25 #include "gui/widgets/window.hpp"
26 
27 #include "desktop/clipboard.hpp"
28 #include "serialization/markup.hpp"
29 #include "game_events/manager.hpp"
30 #include "serialization/parser.hpp" // for write()
31 #include "serialization/markup.hpp"
32 
33 #include "gettext.hpp"
34 #include "recall_list_manager.hpp"
35 #include "team.hpp"
36 #include "units/unit.hpp"
37 #include "units/map.hpp"
38 #include "ai/manager.hpp"
39 
40 #include "display_context.hpp"
41 #include "video.hpp"
42 
43 #include <vector>
44 #include <functional>
45 
46 namespace
47 {
48 
49 inline std::string config_to_string(const config& cfg)
50 {
51  std::ostringstream s;
52  write(s, cfg);
53  return s.str();
54 }
55 
56 inline std::string config_to_string(const config& cfg, const std::string& only_children)
57 {
58  config filtered;
59  for(const config& child : cfg.child_range(only_children)) {
60  filtered.add_child(only_children, child);
61  }
62  return config_to_string(filtered);
63 }
64 
65 }
66 
67 namespace gui2::dialogs
68 {
69 
71 {
72 public:
73  std::string name;
74 
75  std::string get_data_full() const
76  {
77  return data;
78  }
79 
80  std::string get_data_paged(int which_page)
81  {
82  if(std::size_t(which_page) >= pages.size()) {
83  return "";
84  }
85  return data.substr(pages[which_page].first, pages[which_page].second);
86  }
87 
88  void clear_data()
89  {
90  data.clear();
91  pages.clear();
92  }
93 
94  void set_data(const std::string& new_data)
95  {
96  data = new_data;
97  repaginate();
98  }
99 
101  {
102  return std::max<int>(pages.size(), 1);
103  }
104 
105 private:
106  void repaginate()
107  {
108  pages.clear();
109  std::size_t start = 0;
110  while(start + page_characters < data.size()) {
111  // This could search into data that's already on a previous page, which is why the result
112  // is then checked for end < start.
113  std::size_t end = data.find_last_of('\n', start + page_characters);
114  int len;
115  if(end == std::string::npos || end < start) {
116  len = page_characters;
117  } else {
118  len = end - start + 1;
119  }
120  pages.emplace_back(start, len);
121  start += len;
122  }
123  if(start < data.size()) {
124  pages.emplace_back(start, data.size() - start);
125  }
126  }
127  unsigned int page_characters = 10000 / video::get_pixel_scale();
128  std::string data;
129  std::vector<std::pair<std::size_t,int>> pages;
130 };
131 
133 {
134 public:
135  stuff_list_adder(tree_view_node& stuff_list, const std::string& defn)
136  : stuff_list_(stuff_list)
137  , defn_(defn)
138  {
139  }
140 
141  std::vector<int> add()
142  {
144  }
145 
146  stuff_list_adder& widget(const std::string& ref, const std::string& label, bool markup = false)
147  {
148  widget_item& item = data_[ref];
149  item["label"] = label;
150  item["use_markup"] = utils::bool_string(markup);
151  return *this;
152  }
153 
154 private:
156  const std::string defn_;
158 };
159 
161 {
162 public:
164  : stuff_list_(window.find_widget<tree_view>("stuff_list", false, true))
165  , inspect_(window.find_widget<styled_widget>("inspect", false, true))
166  , pages_(window.find_widget<styled_widget>("page_count", false, true))
167  , left_(window.find_widget<styled_widget>("page_left", false, true))
168  , right_(window.find_widget<styled_widget>("page_right", false, true))
169  {
170  }
171 
173  {
175  }
176 
177  void update(model& m)
178  {
179  int n_pages = m.count_pages();
180  current_page_ = std::min(n_pages - 1, std::max(0, current_page_));
182  if(n_pages > 1) {
183  std::ostringstream out;
184  out << current_page_ + 1 << '/' << n_pages;
185  pages_->set_label(out.str());
189  right_->set_active(current_page_ < n_pages - 1);
190  } else {
191  pages_->set_label("");
194  }
195  }
196 
198  {
199  stuff_list_->clear();
200  pages_->set_label("");
203  }
204 
205  void page(int where)
206  {
207  current_page_ += where;
208  }
209 
210 private:
211  int current_page_ = 0;
217 };
218 
220 {
221 public:
223  {
224  }
225 
227  {
228  }
229 
230 protected:
234  const config& vars() const;
235  const game_events::manager& events() const;
236  const display_context& dc() const;
237 };
238 
240 {
241 public:
244  {
245  }
246 
247  void show_list(tree_view_node& node);
248  void show_var(tree_view_node& node);
249  void show_array(tree_view_node& node);
250 };
251 
253 {
254 public:
256  void show_list(tree_view_node& node, bool is_wmi);
257  void show_event(tree_view_node& node, bool is_wmi);
258 
259 private:
261 };
262 
264 {
265 public:
268  {
269  }
270 
271  void show_list(tree_view_node& node);
272  void show_unit(tree_view_node& node);
273  void show_var(tree_view_node& node);
274  void show_array(tree_view_node& node);
275 };
276 
278 {
279 public:
282  {
283  }
284 
285  void show_list(tree_view_node& node, int side);
286  void show_ai(tree_view_node& node, int side);
287  void show_ai_components(tree_view_node& node, int side);
288  void show_ai_tree(tree_view_node& node, int side);
289  void show_recall(tree_view_node& node, int side);
290  void show_recall_unit(tree_view_node& node, int side);
291  void show_units(tree_view_node& node, int side);
292  void show_unit(tree_view_node& node, int side);
293  void show_vars(tree_view_node& node, int side);
294  void show_var(tree_view_node& node, int side);
295  void show_array(tree_view_node& node, int side);
296 };
297 
299 {
301 public:
302  controller(model& m, view& v, const config& vars, const game_events::manager& events, const display_context& dc)
303  : model_(m), view_(v)
304  , vars_(vars), events_(events), dc_(dc)
305  {
306  }
307 
309  {
310  tree_view_node* selected = dynamic_cast<tree_view&>(tree).selected_item();
311  callbacks[selected->describe_path()](*selected);
312 
313  // We recursively fold, but non-recursively unfold.
314  // This is because only one node on a level should be open at any given time.
315  // Furthermore, there's no need to remember that a subnode was open once the parent is closed.
316  if(!selected->is_root_node()) {
317  for(auto& node : selected->parent_node().children()) {
318  if(node.get() != selected) {
319  node->fold(true);
320  }
321  }
322 
323  selected->unfold();
324  }
325 
327  }
328 
330  {
332  }
333 
335  {
337  // The game state could've changed, so reset the dialog
338  callbacks.clear();
339  controllers.clear();
342  model_.clear_data();
344  }
345 
347  {
348  view_.page(next ? 1 : -1);
350  }
351 
352  template<typename T>
353  std::shared_ptr<T> get_controller()
354  {
355  for(auto& c : controllers) {
356  if(std::shared_ptr<T> p = std::dynamic_pointer_cast<T>(c)) {
357  return p;
358  }
359  }
360  std::shared_ptr<T> p = std::make_shared<T>(*this);
361  controllers.push_back(p);
362  return p;
363  }
364 
365  template<typename C>
366  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&))
367  {
368  C& sub_controller = *get_controller<C>();
369  callbacks.emplace(node_path, std::bind(fcn, sub_controller, std::placeholders::_1));
370  }
371 
372  template<typename C, typename T>
373  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&, T), T param)
374  {
375  C& sub_controller = *get_controller<C>();
376  callbacks.emplace(node_path, std::bind(fcn, sub_controller, std::placeholders::_1, param));
377  }
378 
380  {
381  auto stuff_list = window.find_widget<tree_view>("stuff_list", false, true);
382  auto copy_button = window.find_widget<button>("copy", false, true);
383  auto lua_button = window.find_widget<button>("lua", false, true);
384  auto left_button = window.find_widget<button>("page_left", false, true);
385  auto right_button = window.find_widget<button>("page_right", false, true);
386 
387  connect_signal_notify_modified(*stuff_list,
388  std::bind(&gamestate_inspector::controller::handle_stuff_list_item_clicked, this, std::placeholders::_1));
389 
391  *copy_button,
393  this));
394 
396  *lua_button,
398  this, std::ref(window)));
399 
401  *left_button,
403  this, false));
404 
406  *right_button,
408  this, true));
409 
413  }
414 
416  {
418  view_.stuff_list_entry(nullptr, "basic")
419  .widget("name", "variables")
420  .add(),
423  view_.stuff_list_entry(nullptr, "basic")
424  .widget("name", "events")
425  .add(),
427  false);
429  view_.stuff_list_entry(nullptr, "basic")
430  .widget("name", "menu items")
431  .add(),
433  true);
435  view_.stuff_list_entry(nullptr, "basic")
436  .widget("name", "units")
437  .add(),
439  int sides = dc_.teams().size();
440  for(int side = 1; side <= sides; side++) {
441  std::ostringstream label;
442  label << "team " << side;
443  const std::string& name = dc_.get_team(side).user_team_name();
444  if(!name.empty()) {
445  label << " (" << name << ")";
446  }
448  view_.stuff_list_entry(nullptr, "basic")
449  .widget("name", label.str())
450  .add(),
452  side);
453  }
454  // Expand initially selected node
455  callbacks[{0}](window.find_widget<tree_view>("stuff_list").get_root_node().get_child_at(0));
456  }
457 
458 private:
461  using node_callback = std::function<void(tree_view_node&)>;
462  using node_callback_map = std::map<std::vector<int>, node_callback>;
463  std::vector<std::shared_ptr<single_mode_controller>> controllers;
465  const config& vars_;
468 };
469 
471  return c.model_;
472 }
473 
475  return c.view_;
476 }
477 
479  return c.vars_;
480 }
481 
483  return c.events_;
484 }
485 
487  return c.dc_;
488 }
489 
492 {
494 }
495 
497 {
498  model().clear_data();
499 
500  if(node.count_children() > 0) {
501  return;
502  }
503 
504  for(const auto& attr : vars().attribute_range())
505  {
507  view().stuff_list_entry(&node, "basic")
508  .widget("name", attr.first)
509  .add(),
511  }
512 
513  std::map<std::string, std::size_t> wml_array_sizes;
514 
515  for(const auto [key, cfg] : vars().all_children_view())
516  {
517  std::ostringstream cur_str;
518  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
519 
520  this->c.set_node_callback(
521  view().stuff_list_entry(&node, "basic")
522  .widget("name", cur_str.str())
523  .add(),
525  wml_array_sizes[key]++;
526  }
527 }
528 
530 {
531  widget* w = node.find("name", false);
532  if(label* lbl = dynamic_cast<label*>(w)) {
533  model().set_data(vars()[lbl->get_label().str()]);
534  }
535 }
536 
538 {
539  widget* w = node.find("name", false);
540  if(label* lbl = dynamic_cast<label*>(w)) {
541  const std::string& var = lbl->get_label();
542  std::size_t n_start = var.find_last_of('[') + 1;
543  std::size_t n_len = var.size() - n_start - 1;
544  int n = std::stoi(var.substr(n_start, n_len));
545  model().set_data(config_to_string(vars().mandatory_child(var.substr(1, n_start - 3), n)));
546  }
547 }
548 
550 {
551  model().clear_data();
552 
553  if(node.count_children() > 0) {
554  return;
555  }
556 
557  for(const auto & cfg : events.child_range(is_wmi ? "menu_item" : "event"))
558  {
559  std::string name = is_wmi ? cfg["id"] : cfg["name"];
560  bool named_event = !is_wmi && !cfg["id"].empty();
561 
562  auto progress = view()
563  .stuff_list_entry(&node, named_event ? "named_event" : "basic")
564  .widget("name", name);
565 
566  if(named_event) {
567  std::ostringstream out;
568  out << "id=\"" << cfg["id"] << '"';
569  progress.widget("id", out.str());
570  }
571 
572  c.set_node_callback(progress.add(), &event_mode_controller::show_event, is_wmi);
573  }
574 
575 }
576 
578 {
579  int n = node.describe_path().back();
580  model().set_data(config_to_string(events.mandatory_child(is_wmi ? "menu_item" : "event", n)));
581 }
582 
584 {
585 
586  color_t team_color = game_config::tc_info(dc.get_team(u.side()).color())[0];
587  std::stringstream s;
588 
589  s << '(' << u.get_location() << ')';
590  progress.widget("loc", s.str());
591 
592  s.str("");
593  s << markup::span_color(team_color, "side=", u.side());
594  progress.widget("side", s.str(), true);
595 
596  if(u.can_recruit()) {
597  progress.widget("leader", markup::span_color("yellow", "LEADER "), true);
598  }
599 
600  s.str("");
601  s << "id=\"" << u.id() << '"';
602  progress.widget("id", s.str());
603 
604  progress.widget("type", u.type_id());
605 
606  s.str("");
607  s << "L" << u.level();
608  progress.widget("level", s.str());
609 
610  s.str("");
611  s << u.experience() << '/' << u.max_experience() << " xp";
612  progress.widget("xp", s.str());
613 
614  s.str("");
615  s << u.hitpoints() << '/' << u.max_hitpoints() << " hp";
616  progress.widget("hp", s.str());
617 
618  progress.widget("traits", utils::join(u.get_traits_list(), ", "));
619 
620  return progress;
621 }
622 
624 {
625  model().clear_data();
626 
627  if(node.count_children() > 0) {
628  return;
629  }
630 
631  for(unit_map::const_iterator i = dc().units().begin(); i != dc().units().end(); ++i) {
632  auto progress = view().stuff_list_entry(&node, "unit");
633  add_unit_entry(progress, *i, dc());
635  }
636 }
637 
639 {
640  int i = node.describe_path().back();
642  std::advance(u, i);
643  config c_unit;
644  u->write(c_unit);
645  model().set_data(config_to_string(c_unit));
646 
647  if(node.count_children() > 0) {
648  return;
649  }
650 
651  for(const auto& attr : u->variables().attribute_range())
652  {
654  view().stuff_list_entry(&node, "basic")
655  .widget("name", attr.first)
656  .add(),
658  }
659 
660  std::map<std::string, std::size_t> wml_array_sizes;
661 
662  for(const auto [key, cfg] : u->variables().all_children_view())
663  {
664  std::ostringstream cur_str;
665  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
666 
667  this->c.set_node_callback(
668  view().stuff_list_entry(&node, "basic")
669  .widget("name", cur_str.str())
670  .add(),
672  wml_array_sizes[key]++;
673  }
674 }
675 
677 {
678  widget* w = node.find("name", false);
679  int i = node.describe_path().back();
681  std::advance(u, i);
682  if(label* lbl = dynamic_cast<label*>(w)) {
683  model().set_data(u->variables()[lbl->get_label().str()]);
684  }
685 }
686 
688 {
689  widget* w = node.find("name", false);
690  int i = node.describe_path().back();
692  std::advance(u, i);
693  if(label* lbl = dynamic_cast<label*>(w)) {
694  const std::string& var = lbl->get_label();
695  std::size_t n_start = var.find_last_of('[') + 1;
696  std::size_t n_len = var.size() - n_start - 1;
697  int n = std::stoi(var.substr(n_start, n_len));
698  model().set_data(config_to_string(u->variables().mandatory_child(var.substr(1, n_start - 3), n)));
699  }
700 }
701 
703 {
704  config&& cfg = dc().get_team(side).to_config();
705  cfg.clear_children("ai");
706  model().set_data(config_to_string(cfg));
707 
708  if(node.count_children() > 0) {
709  return;
710  }
711 
713  view().stuff_list_entry(&node, "basic")
714  .widget("name", "ai")
715  .add(),
717  side);
719  view().stuff_list_entry(&node, "basic")
720  .widget("name", "recall list")
721  .add(),
723  side);
725  view().stuff_list_entry(&node, "basic")
726  .widget("name", "units")
727  .add(),
729  side);
731  view().stuff_list_entry(&node, "basic")
732  .widget("name", "variables")
733  .add(),
735  side);
736 }
737 
739 {
740  model().set_data(ai::manager::get_singleton().get_active_ai_overview_for_side(side));
741 
742  if(node.count_children() > 0) {
743  return;
744  }
745 
747  view().stuff_list_entry(&node, "basic")
748  .widget("name", "engines")
749  .add(),
751  side);
753  view().stuff_list_entry(&node, "basic")
754  .widget("name", "stages")
755  .add(),
757  side);
759  view().stuff_list_entry(&node, "basic")
760  .widget("name", "aspects")
761  .add(),
763  side);
765  view().stuff_list_entry(&node, "basic")
766  .widget("name", "goals")
767  .add(),
769  side);
771  view().stuff_list_entry(&node, "basic")
772  .widget("name", "component structure")
773  .add(),
775  side);
776 }
777 
779 {
780  widget* w = node.find("name", false);
781  if(label* lbl = dynamic_cast<label*>(w)) {
782  std::string tag = lbl->get_label();
783  tag.pop_back();
784  model().set_data(config_to_string(ai::manager::get_singleton().to_config(side), tag));
785  }
786 }
787 
789 {
790  model().clear_data();
791 
792  if(node.count_children() > 0) {
793  return;
794  }
795 
796  for(const unit_ptr& u : dc().get_team(side).recall_list()) {
797  auto progress = view().stuff_list_entry(&node, "unit");
798  add_unit_entry(progress, *u, dc());
800  }
801 }
802 
804 {
805  int i = node.describe_path().back();
806  auto u = dc().get_team(side).recall_list().begin();
807  std::advance(u, i);
808  config c_unit;
809  (*u)->write(c_unit);
810  model().set_data(config_to_string(c_unit));
811 }
812 
814 {
815  model().set_data(ai::manager::get_singleton().get_active_ai_structure_for_side(side));
816 }
817 
819 {
820  std::ostringstream s;
821  for(unit_map::const_iterator i = dc().units().begin(); i != dc().units().end();
822  ++i) {
823  if(i->side() != side) {
824  continue;
825  }
826  s << '(' << i->get_location() << ") ";
827  if(i->can_recruit()) {
828  s << "LEADER ";
829  }
830 
831  s << "\nid=\"" << i->id() << "\" (" << i->type_id() << ")\n"
832  << "L" << i->level() << "; " << i->experience() << '/'
833  << i->max_experience() << " XP; " << i->hitpoints() << '/'
834  << i->max_hitpoints() << " HP\n";
835  for(const auto & str : i->get_traits_list())
836  {
837  s << "\t" << str << std::endl;
838  }
839  s << std::endl;
840  }
841  model().set_data(s.str());
842 }
843 
845 {
846  model().clear_data();
847 
848  if(node.count_children() > 0) {
849  return;
850  }
851 
852  const team& t = dc().get_team(side);
853 
854  for(const auto& attr : t.variables().attribute_range())
855  {
857  view().stuff_list_entry(&node, "basic")
858  .widget("name", attr.first)
859  .add(),
861  side);
862  }
863 
864  std::map<std::string, std::size_t> wml_array_sizes;
865 
866  for(const auto [key, cfg] : t.variables().all_children_view())
867  {
868  std::ostringstream cur_str;
869  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
870 
871  this->c.set_node_callback(
872  view().stuff_list_entry(&node, "basic")
873  .widget("name", cur_str.str())
874  .add(),
876  side);
877  wml_array_sizes[key]++;
878  }
879 }
880 
882 {
883  widget* w = node.find("name", false);
884  const team& t = dc().get_team(side);
885  if(label* lbl = dynamic_cast<label*>(w)) {
886  model().set_data(t.variables()[lbl->get_label().str()]);
887  }
888 }
889 
891 {
892  widget* w = node.find("name", false);
893  const team& t = dc().get_team(side);
894  if(label* lbl = dynamic_cast<label*>(w)) {
895  const std::string& var = lbl->get_label();
896  std::size_t n_start = var.find_last_of('[') + 1;
897  std::size_t n_len = var.size() - n_start - 1;
898  int n = std::stoi(var.substr(n_start, n_len));
899  model().set_data(config_to_string(t.variables().mandatory_child(var.substr(1, n_start - 3), n)));
900  }
901 }
902 
904 
905 gamestate_inspector::gamestate_inspector(const config& vars, const game_events::manager& events, const display_context& dc, const std::string& title)
906  : modal_dialog(window_id())
907  , title_(title)
908  , vars_(vars)
909  , events_(events)
910  , dc_(dc)
911 {
912  model_.reset(new model);
913 }
914 
916 {
917  view_.reset(new view(*this));
918  controller_.reset(new controller(*model_, *view_, vars_, events_, dc_));
919 
920  if(!title_.empty()) {
921  find_widget<styled_widget>("inspector_name").set_label(title_);
922  }
923  controller_->bind(*this);
924  view_->update(*model_);
925 }
926 
927 } // namespace dialogs
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
double t
Definition: astarsearch.cpp:63
static manager & get_singleton()
Definition: manager.hpp:140
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
void clear_children(T... keys)
Definition: config.hpp:616
child_itors child_range(config_key_type key)
Definition: config.cpp:272
config & add_child(config_key_type key)
Definition: config.cpp:440
Abstract class for exposing game data that doesn't depend on the GUI, however which for historical re...
const team & get_team(int side) const
This getter takes a 1-based side number, not a 0-based team number.
virtual const std::vector< team > & teams() const =0
virtual const unit_map & units() const =0
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:45
void write_events(config &cfg, bool include_nonserializable=false) const
Definition: manager.cpp:173
Simple push button.
Definition: button.hpp:36
grid::iterator end()
void show_list(tree_view_node &node, bool is_wmi)
void show_event(tree_view_node &node, bool is_wmi)
event_mode_controller(gamestate_inspector::controller &c)
std::map< std::vector< int >, node_callback > node_callback_map
void set_node_callback(const std::vector< int > &node_path, void(C::*fcn)(tree_view_node &, T), T param)
controller(model &m, view &v, const config &vars, const game_events::manager &events, const display_context &dc)
std::vector< std::shared_ptr< single_mode_controller > > controllers
std::function< void(tree_view_node &)> node_callback
void set_node_callback(const std::vector< int > &node_path, void(C::*fcn)(tree_view_node &))
void set_data(const std::string &new_data)
std::vector< std::pair< std::size_t, int > > pages
stuff_list_adder stuff_list_entry(tree_view_node *parent, const std::string &defn)
const game_events::manager & events_
virtual void pre_show() override
Actions to be taken before showing the window.
std::shared_ptr< controller > controller_
static void display(lua_kernel_base *lk)
Display a new console, using given video and lua kernel.
Abstract base class for all modal dialogs.
const game_events::manager & events() const
single_mode_controller(gamestate_inspector::controller &c)
gamestate_inspector::controller & c
const display_context & dc() const
gamestate_inspector::model & model()
stuff_list_adder(tree_view_node &stuff_list, const std::string &defn)
stuff_list_adder & widget(const std::string &ref, const std::string &label, bool markup=false)
void show_var(tree_view_node &node, int side)
void show_ai_tree(tree_view_node &node, int side)
void show_ai(tree_view_node &node, int side)
void show_vars(tree_view_node &node, int side)
void show_recall(tree_view_node &node, int side)
void show_unit(tree_view_node &node, int side)
void show_array(tree_view_node &node, int side)
void show_ai_components(tree_view_node &node, int side)
void show_units(tree_view_node &node, int side)
void show_list(tree_view_node &node, int side)
team_mode_controller(gamestate_inspector::controller &c)
void show_recall_unit(tree_view_node &node, int side)
unit_mode_controller(gamestate_inspector::controller &c)
variable_mode_controller(gamestate_inspector::controller &c)
virtual void set_active(const bool active)=0
Sets the styled_widget's state.
virtual void set_label(const t_string &text)
std::vector< int > describe_path() const
Calculates the node indices needed to get from the root node to this node.
widget * find(const std::string_view id, const bool must_be_active) override
See widget::find.
std::size_t count_children() const
The number of children in this widget.
tree_view_node & add_child(const std::string &id, const widget_data &data, const int index=-1)
Constructs a new child node.
const tree_view_node & get_root_node() const
Definition: tree_view.hpp:53
Base class for all widgets.
Definition: widget.hpp:55
void set_visible(const visibility visible)
Definition: widget.cpp:479
@ visible
The user sets the widget visible, that means:
@ invisible
The user set the widget invisible, that means:
T * find_widget(const std::string_view id, const bool must_be_active, const bool must_exist)
Gets a widget with the wanted id.
Definition: widget.hpp:753
widget * parent()
Definition: widget.cpp:170
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:61
iterator begin()
begin iterator
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:75
const std::string & color() const
Definition: team.hpp:242
config to_config() const
Definition: team.cpp:1045
recall_list_manager & recall_list()
Definition: team.hpp:201
const t_string & user_team_name() const
Definition: team.hpp:283
unit_iterator end()
Definition: map.hpp:428
unit_iterator begin()
Definition: map.hpp:418
This class represents a single unit of a specific type.
Definition: unit.hpp:133
std::size_t i
Definition: function.cpp:1029
int w
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:505
int level() const
The current level of this unit.
Definition: unit.hpp:559
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:499
const std::string & type_id() const
The id of this unit's type.
Definition: unit.cpp:1933
int experience() const
The current number of experience points this unit has.
Definition: unit.hpp:523
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
Definition: unit.hpp:612
const std::string & id() const
Gets this unit's id.
Definition: unit.hpp:380
int side() const
The side this unit belongs to.
Definition: unit.hpp:343
int max_experience() const
The max number of experience points this unit can have.
Definition: unit.hpp:529
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1404
std::vector< std::string > get_traits_list() const
Gets a list of the traits this unit currently has, including hidden traits.
Definition: unit.hpp:1135
std::string label
What to show in the filter's drop-down list.
Definition: manager.cpp:200
This file contains the window object, this object is a top level container which has the event manage...
void copy_to_clipboard(const std::string &text)
Copies text to the clipboard.
Definition: clipboard.cpp:27
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Handling of system events.
std::string selected
const std::vector< color_t > & tc_info(std::string_view name)
Domain specific events.
static stuff_list_adder add_unit_entry(stuff_list_adder &progress, const unit &u, const display_context &dc)
REGISTER_DIALOG(editor_edit_unit)
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:203
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:177
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:36
std::map< std::string, t_string > widget_item
Definition: widget.hpp:33
std::string tag(const std::string &tag_name, Args &&... contents)
Definition: markup.hpp:45
std::string span_color(const color_t &color, Args &&... data)
Definition: markup.hpp:68
int stoi(std::string_view str)
Same interface as std::stoi and meant as a drop in replacement, except:
Definition: charconv.hpp:154
std::string bool_string(const bool value)
Converts a bool value to 'true' or 'false'.
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
int get_pixel_scale()
Get the current active pixel scale multiplier.
Definition: video.cpp:481
std::shared_ptr< unit > unit_ptr
Definition: ptr.hpp:26
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Definition: parser.cpp:766
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
mock_char c
mock_party p
static map_location::direction n
static map_location::direction s