The Battle for Wesnoth  1.19.13+dev
gamestate_inspector.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
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 "game_config.hpp"
29 #include "serialization/markup.hpp"
30 #include "game_events/manager.hpp"
31 #include "serialization/parser.hpp" // for write()
32 #include "serialization/markup.hpp"
33 
34 #include "gettext.hpp"
35 #include "recall_list_manager.hpp"
36 #include "team.hpp"
37 #include "units/unit.hpp"
38 #include "units/map.hpp"
39 #include "ai/manager.hpp"
40 
41 #include "display_context.hpp"
42 #include "video.hpp"
43 
44 #include <vector>
45 #include <functional>
46 
47 namespace
48 {
49 
50 inline std::string config_to_string(const config& cfg)
51 {
52  std::ostringstream s;
53  io::write(s, cfg);
54  return s.str();
55 }
56 
57 inline std::string config_to_string(const config& cfg, const std::string& only_children)
58 {
59  config filtered;
60  for(const config& child : cfg.child_range(only_children)) {
61  filtered.add_child(only_children, child);
62  }
63  return config_to_string(filtered);
64 }
65 
66 }
67 
68 namespace gui2::dialogs
69 {
70 
72 {
73 public:
74  std::string name;
75 
76  std::string get_data_full() const
77  {
78  return data;
79  }
80 
81  std::string get_data_paged(int which_page)
82  {
83  if(std::size_t(which_page) >= pages.size()) {
84  return "";
85  }
86  return data.substr(pages[which_page].first, pages[which_page].second);
87  }
88 
89  void clear_data()
90  {
91  data.clear();
92  pages.clear();
93  }
94 
95  void set_data(const std::string& new_data)
96  {
97  data = new_data;
98  repaginate();
99  }
100 
102  {
103  return std::max<int>(pages.size(), 1);
104  }
105 
106 private:
107  void repaginate()
108  {
109  pages.clear();
110  std::size_t start = 0;
111  while(start + page_characters < data.size()) {
112  // This could search into data that's already on a previous page, which is why the result
113  // is then checked for end < start.
114  std::size_t end = data.find_last_of('\n', start + page_characters);
115  int len;
116  if(end == std::string::npos || end < start) {
117  len = page_characters;
118  } else {
119  len = end - start + 1;
120  }
121  pages.emplace_back(start, len);
122  start += len;
123  }
124  if(start < data.size()) {
125  pages.emplace_back(start, data.size() - start);
126  }
127  }
128  unsigned int page_characters = 10000 / video::get_pixel_scale();
129  std::string data;
130  std::vector<std::pair<std::size_t,int>> pages;
131 };
132 
134 {
135 public:
136  stuff_list_adder(tree_view_node& stuff_list, const std::string& defn)
137  : stuff_list_(stuff_list)
138  , defn_(defn)
139  {
140  }
141 
142  std::vector<int> add()
143  {
145  }
146 
147  stuff_list_adder& widget(const std::string& ref, const std::string& label, bool markup = false)
148  {
149  widget_item& item = data_[ref];
150  item["label"] = label;
151  item["use_markup"] = utils::bool_string(markup);
152  return *this;
153  }
154 
155 private:
157  const std::string defn_;
159 };
160 
162 {
163 public:
165  : stuff_list_(window.find_widget<tree_view>("stuff_list", false, true))
166  , inspect_(window.find_widget<styled_widget>("inspect", false, true))
167  , pages_(window.find_widget<styled_widget>("page_count", false, true))
168  , left_(window.find_widget<styled_widget>("page_left", false, true))
169  , right_(window.find_widget<styled_widget>("page_right", false, true))
170  {
171  }
172 
174  {
176  }
177 
178  void update(model& m)
179  {
180  int n_pages = m.count_pages();
181  current_page_ = std::min(n_pages - 1, std::max(0, current_page_));
183  if(n_pages > 1) {
184  std::ostringstream out;
185  out << current_page_ + 1 << '/' << n_pages;
186  pages_->set_label(out.str());
190  right_->set_active(current_page_ < n_pages - 1);
191  } else {
192  pages_->set_label("");
195  }
196  }
197 
199  {
200  stuff_list_->clear();
201  pages_->set_label("");
204  }
205 
206  void page(int where)
207  {
208  current_page_ += where;
209  }
210 
211 private:
212  int current_page_ = 0;
218 };
219 
221 {
222 public:
224  {
225  }
226 
228  {
229  }
230 
231 protected:
235  const config& vars() const;
236  const game_events::manager& events() const;
237  const display_context& dc() const;
238 };
239 
241 {
242 public:
245  {
246  }
247 
248  void show_list(tree_view_node& node);
249  void show_var(tree_view_node& node);
250  void show_array(tree_view_node& node);
251 };
252 
254 {
255 public:
257  void show_list(tree_view_node& node, bool is_wmi);
258  void show_event(tree_view_node& node, bool is_wmi);
259 
260 private:
262 };
263 
265 {
266 public:
269  {
270  }
271 
272  void show_list(tree_view_node& node);
273  void show_unit(tree_view_node& node);
274  void show_var(tree_view_node& node);
275  void show_array(tree_view_node& node);
276 };
277 
279 {
280 public:
283  {
284  }
285 
286  void show_list(tree_view_node& node, int side);
287  void show_ai(tree_view_node& node, int side);
288  void show_ai_components(tree_view_node& node, int side);
289  void show_ai_tree(tree_view_node& node, int side);
290  void show_recall(tree_view_node& node, int side);
291  void show_recall_unit(tree_view_node& node, int side);
292  void show_units(tree_view_node& node, int side);
293  void show_unit(tree_view_node& node, int side);
294  void show_vars(tree_view_node& node, int side);
295  void show_var(tree_view_node& node, int side);
296  void show_array(tree_view_node& node, int side);
297 };
298 
300 {
302 public:
303  controller(model& m, view& v, const config& vars, const game_events::manager& events, const display_context& dc)
304  : model_(m), view_(v)
305  , vars_(vars), events_(events), dc_(dc)
306  {
307  }
308 
310  {
311  tree_view_node* selected = dynamic_cast<tree_view&>(tree).selected_item();
312  callbacks[selected->describe_path()](*selected);
313 
314  // We recursively fold, but non-recursively unfold.
315  // This is because only one node on a level should be open at any given time.
316  // Furthermore, there's no need to remember that a subnode was open once the parent is closed.
317  if(!selected->is_root_node()) {
318  for(auto& node : selected->parent_node().children()) {
319  if(node.get() != selected) {
320  node->fold(true);
321  }
322  }
323 
324  selected->unfold();
325  }
326 
328  }
329 
331  {
333  }
334 
336  {
338  // The game state could've changed, so reset the dialog
339  callbacks.clear();
340  controllers.clear();
343  model_.clear_data();
345  }
346 
348  {
349  view_.page(next ? 1 : -1);
351  }
352 
353  template<typename T>
354  std::shared_ptr<T> get_controller()
355  {
356  for(auto& c : controllers) {
357  if(std::shared_ptr<T> p = std::dynamic_pointer_cast<T>(c)) {
358  return p;
359  }
360  }
361  std::shared_ptr<T> p = std::make_shared<T>(*this);
362  controllers.push_back(p);
363  return p;
364  }
365 
366  template<typename C>
367  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&))
368  {
369  callbacks.emplace(node_path, [=, sub_controller = get_controller<C>()](auto& node) {
370  std::invoke(fcn, *sub_controller, node);
371  });
372  }
373 
374  template<typename C, typename T>
375  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&, T), T param)
376  {
377  callbacks.emplace(node_path, [=, sub_controller = get_controller<C>()](auto& node) {
378  std::invoke(fcn, *sub_controller, node, param);
379  });
380  }
381 
383  {
384  auto stuff_list = window.find_widget<tree_view>("stuff_list", false, true);
385  auto copy_button = window.find_widget<button>("copy", false, true);
386  auto lua_button = window.find_widget<button>("lua", false, true);
387  auto left_button = window.find_widget<button>("page_left", false, true);
388  auto right_button = window.find_widget<button>("page_right", false, true);
389 
390  connect_signal_notify_modified(*stuff_list,
391  [this](widget& w, auto&&...) { handle_stuff_list_item_clicked(w); });
392 
393  connect_signal_mouse_left_click(*copy_button,
394  [this](auto&&...) { handle_copy_button_clicked(); });
395 
397  [this, &window](auto&&...) { handle_lua_button_clicked(window); }); // TODO: no window ref
398 
399  connect_signal_mouse_left_click(*left_button,
400  [this](auto&&...) { handle_page_button_clicked(false); });
401 
402  connect_signal_mouse_left_click(*right_button,
403  [this](auto&&...) { handle_page_button_clicked(true); });
404 
408  }
409 
411  {
413  view_.stuff_list_entry(nullptr, "basic")
414  .widget("name", "variables")
415  .add(),
418  view_.stuff_list_entry(nullptr, "basic")
419  .widget("name", "events")
420  .add(),
422  false);
424  view_.stuff_list_entry(nullptr, "basic")
425  .widget("name", "menu items")
426  .add(),
428  true);
430  view_.stuff_list_entry(nullptr, "basic")
431  .widget("name", "units")
432  .add(),
434  int sides = dc_.teams().size();
435  for(int side = 1; side <= sides; side++) {
436  std::ostringstream label;
437  label << "team " << side;
438  const std::string& name = dc_.get_team(side).user_team_name();
439  if(!name.empty()) {
440  label << " (" << name << ")";
441  }
443  view_.stuff_list_entry(nullptr, "basic")
444  .widget("name", label.str())
445  .add(),
447  side);
448  }
449  // Expand initially selected node
450  callbacks[{0}](window.find_widget<tree_view>("stuff_list").get_root_node().get_child_at(0));
451  }
452 
453 private:
456  using node_callback = std::function<void(tree_view_node&)>;
457  using node_callback_map = std::map<std::vector<int>, node_callback>;
458  std::vector<std::shared_ptr<single_mode_controller>> controllers;
460  const config& vars_;
463 };
464 
466  return c.model_;
467 }
468 
470  return c.view_;
471 }
472 
474  return c.vars_;
475 }
476 
478  return c.events_;
479 }
480 
482  return c.dc_;
483 }
484 
487 {
489 }
490 
492 {
493  model().clear_data();
494 
495  if(node.count_children() > 0) {
496  return;
497  }
498 
499  for(const auto& attr : vars().attribute_range())
500  {
502  view().stuff_list_entry(&node, "basic")
503  .widget("name", attr.first)
504  .add(),
506  }
507 
508  std::map<std::string, std::size_t> wml_array_sizes;
509 
510  for(const auto [key, cfg] : vars().all_children_view())
511  {
512  std::ostringstream cur_str;
513  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
514 
515  this->c.set_node_callback(
516  view().stuff_list_entry(&node, "basic")
517  .widget("name", cur_str.str())
518  .add(),
520  wml_array_sizes[key]++;
521  }
522 }
523 
525 {
526  widget* w = node.find("name", false);
527  if(label* lbl = dynamic_cast<label*>(w)) {
528  model().set_data(vars()[lbl->get_label().str()]);
529  }
530 }
531 
533 {
534  widget* w = node.find("name", false);
535  if(label* lbl = dynamic_cast<label*>(w)) {
536  const std::string& var = lbl->get_label();
537  std::size_t n_start = var.find_last_of('[') + 1;
538  std::size_t n_len = var.size() - n_start - 1;
539  int n = std::stoi(var.substr(n_start, n_len));
540  model().set_data(config_to_string(vars().mandatory_child(var.substr(1, n_start - 3), n)));
541  }
542 }
543 
545 {
546  model().clear_data();
547 
548  if(node.count_children() > 0) {
549  return;
550  }
551 
552  for(const auto & cfg : events.child_range(is_wmi ? "menu_item" : "event"))
553  {
554  std::string name = is_wmi ? cfg["id"] : cfg["name"];
555  bool named_event = !is_wmi && !cfg["id"].empty();
556 
557  auto progress = view()
558  .stuff_list_entry(&node, named_event ? "named_event" : "basic")
559  .widget("name", name);
560 
561  if(named_event) {
562  std::ostringstream out;
563  out << "id=\"" << cfg["id"] << '"';
564  progress.widget("id", out.str());
565  }
566 
567  c.set_node_callback(progress.add(), &event_mode_controller::show_event, is_wmi);
568  }
569 
570 }
571 
573 {
574  int n = node.describe_path().back();
575  model().set_data(config_to_string(events.mandatory_child(is_wmi ? "menu_item" : "event", n)));
576 }
577 
579 {
580 
581  color_t team_color = game_config::tc_info(dc.get_team(u.side()).color())[0];
582  std::stringstream s;
583 
584  s << '(' << u.get_location() << ')';
585  progress.widget("loc", s.str());
586 
587  s.str("");
588  s << markup::span_color(team_color, "side=", u.side());
589  progress.widget("side", s.str(), true);
590 
591  if(u.can_recruit()) {
592  progress.widget("leader", markup::span_color("yellow", "LEADER "), true);
593  }
594 
595  s.str("");
596  s << "id=\"" << u.id() << '"';
597  progress.widget("id", s.str());
598 
599  progress.widget("type", u.type_id());
600 
601  s.str("");
602  s << "L" << u.level();
603  progress.widget("level", s.str());
604 
605  s.str("");
606  s << u.experience() << '/' << u.max_experience() << " xp";
607  progress.widget("xp", s.str());
608 
609  s.str("");
610  s << u.hitpoints() << '/' << u.max_hitpoints() << " hp";
611  progress.widget("hp", s.str());
612 
613  progress.widget("traits", utils::join(u.get_traits_list(), ", "));
614 
615  return progress;
616 }
617 
619 {
620  model().clear_data();
621 
622  if(node.count_children() > 0) {
623  return;
624  }
625 
626  for(unit_map::const_iterator i = dc().units().begin(); i != dc().units().end(); ++i) {
627  auto progress = view().stuff_list_entry(&node, "unit");
628  add_unit_entry(progress, *i, dc());
630  }
631 }
632 
634 {
635  int i = node.describe_path().back();
637  std::advance(u, i);
638  config c_unit;
639  u->write(c_unit);
640  model().set_data(config_to_string(c_unit));
641 
642  if(node.count_children() > 0) {
643  return;
644  }
645 
646  for(const auto& attr : u->variables().attribute_range())
647  {
649  view().stuff_list_entry(&node, "basic")
650  .widget("name", attr.first)
651  .add(),
653  }
654 
655  std::map<std::string, std::size_t> wml_array_sizes;
656 
657  for(const auto [key, cfg] : u->variables().all_children_view())
658  {
659  std::ostringstream cur_str;
660  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
661 
662  this->c.set_node_callback(
663  view().stuff_list_entry(&node, "basic")
664  .widget("name", cur_str.str())
665  .add(),
667  wml_array_sizes[key]++;
668  }
669 }
670 
672 {
673  widget* w = node.find("name", false);
674  int i = node.describe_path().back();
676  std::advance(u, i);
677  if(label* lbl = dynamic_cast<label*>(w)) {
678  model().set_data(u->variables()[lbl->get_label().str()]);
679  }
680 }
681 
683 {
684  widget* w = node.find("name", false);
685  int i = node.describe_path().back();
687  std::advance(u, i);
688  if(label* lbl = dynamic_cast<label*>(w)) {
689  const std::string& var = lbl->get_label();
690  std::size_t n_start = var.find_last_of('[') + 1;
691  std::size_t n_len = var.size() - n_start - 1;
692  int n = std::stoi(var.substr(n_start, n_len));
693  model().set_data(config_to_string(u->variables().mandatory_child(var.substr(1, n_start - 3), n)));
694  }
695 }
696 
698 {
699  config&& cfg = dc().get_team(side).to_config();
700  cfg.clear_children("ai");
701  model().set_data(config_to_string(cfg));
702 
703  if(node.count_children() > 0) {
704  return;
705  }
706 
708  view().stuff_list_entry(&node, "basic")
709  .widget("name", "ai")
710  .add(),
712  side);
714  view().stuff_list_entry(&node, "basic")
715  .widget("name", "recall list")
716  .add(),
718  side);
720  view().stuff_list_entry(&node, "basic")
721  .widget("name", "units")
722  .add(),
724  side);
726  view().stuff_list_entry(&node, "basic")
727  .widget("name", "variables")
728  .add(),
730  side);
731 }
732 
734 {
735  model().set_data(ai::manager::get_singleton().get_active_ai_overview_for_side(side));
736 
737  if(node.count_children() > 0) {
738  return;
739  }
740 
742  view().stuff_list_entry(&node, "basic")
743  .widget("name", "engines")
744  .add(),
746  side);
748  view().stuff_list_entry(&node, "basic")
749  .widget("name", "stages")
750  .add(),
752  side);
754  view().stuff_list_entry(&node, "basic")
755  .widget("name", "aspects")
756  .add(),
758  side);
760  view().stuff_list_entry(&node, "basic")
761  .widget("name", "goals")
762  .add(),
764  side);
766  view().stuff_list_entry(&node, "basic")
767  .widget("name", "component structure")
768  .add(),
770  side);
771 }
772 
774 {
775  widget* w = node.find("name", false);
776  if(label* lbl = dynamic_cast<label*>(w)) {
777  std::string tag = lbl->get_label();
778  tag.pop_back();
779  model().set_data(config_to_string(ai::manager::get_singleton().to_config(side), tag));
780  }
781 }
782 
784 {
785  model().clear_data();
786 
787  if(node.count_children() > 0) {
788  return;
789  }
790 
791  for(const unit_ptr& u : dc().get_team(side).recall_list()) {
792  auto progress = view().stuff_list_entry(&node, "unit");
793  add_unit_entry(progress, *u, dc());
795  }
796 }
797 
799 {
800  int i = node.describe_path().back();
801  auto u = dc().get_team(side).recall_list().begin();
802  std::advance(u, i);
803  config c_unit;
804  (*u)->write(c_unit);
805  model().set_data(config_to_string(c_unit));
806 }
807 
809 {
810  model().set_data(ai::manager::get_singleton().get_active_ai_structure_for_side(side));
811 }
812 
814 {
815  std::ostringstream s;
816  for(unit_map::const_iterator i = dc().units().begin(); i != dc().units().end();
817  ++i) {
818  if(i->side() != side) {
819  continue;
820  }
821  s << '(' << i->get_location() << ") ";
822  if(i->can_recruit()) {
823  s << "LEADER ";
824  }
825 
826  s << "\nid=\"" << i->id() << "\" (" << i->type_id() << ")\n"
827  << "L" << i->level() << "; " << i->experience() << '/'
828  << i->max_experience() << " XP; " << i->hitpoints() << '/'
829  << i->max_hitpoints() << " HP\n";
830  for(const auto & str : i->get_traits_list())
831  {
832  s << "\t" << str << std::endl;
833  }
834  s << std::endl;
835  }
836  model().set_data(s.str());
837 }
838 
840 {
841  model().clear_data();
842 
843  if(node.count_children() > 0) {
844  return;
845  }
846 
847  const team& t = dc().get_team(side);
848 
849  for(const auto& attr : t.variables().attribute_range())
850  {
852  view().stuff_list_entry(&node, "basic")
853  .widget("name", attr.first)
854  .add(),
856  side);
857  }
858 
859  std::map<std::string, std::size_t> wml_array_sizes;
860 
861  for(const auto [key, cfg] : t.variables().all_children_view())
862  {
863  std::ostringstream cur_str;
864  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
865 
866  this->c.set_node_callback(
867  view().stuff_list_entry(&node, "basic")
868  .widget("name", cur_str.str())
869  .add(),
871  side);
872  wml_array_sizes[key]++;
873  }
874 }
875 
877 {
878  widget* w = node.find("name", false);
879  const team& t = dc().get_team(side);
880  if(label* lbl = dynamic_cast<label*>(w)) {
881  model().set_data(t.variables()[lbl->get_label().str()]);
882  }
883 }
884 
886 {
887  widget* w = node.find("name", false);
888  const team& t = dc().get_team(side);
889  if(label* lbl = dynamic_cast<label*>(w)) {
890  const std::string& var = lbl->get_label();
891  std::size_t n_start = var.find_last_of('[') + 1;
892  std::size_t n_len = var.size() - n_start - 1;
893  int n = std::stoi(var.substr(n_start, n_len));
894  model().set_data(config_to_string(t.variables().mandatory_child(var.substr(1, n_start - 3), n)));
895  }
896 }
897 
899 
900 gamestate_inspector::gamestate_inspector(const config& vars, const game_events::manager& events, const display_context& dc, const std::string& title)
901  : modal_dialog(window_id())
902  , title_(title)
903  , vars_(vars)
904  , events_(events)
905  , dc_(dc)
906 {
907  model_.reset(new model);
908 }
909 
911 {
912  view_.reset(new view(*this));
913  controller_.reset(new controller(*model_, *view_, vars_, events_, dc_));
914 
915  if(!title_.empty()) {
916  find_widget<styled_widget>("inspector_name").set_label(title_);
917  }
918  controller_->bind(*this);
919  view_->update(*model_);
920 }
921 
922 } // 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:158
void clear_children(T... keys)
Definition: config.hpp:602
child_itors child_range(config_key_type key)
Definition: config.cpp:268
config & add_child(config_key_type key)
Definition: config.cpp:436
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:174
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:747
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:74
const std::string & color() const
Definition: team.hpp:279
config to_config() const
Definition: team.cpp:1030
recall_list_manager & recall_list()
Definition: team.hpp:238
const t_string & user_team_name() const
Definition: team.hpp:320
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:1032
int w
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:521
int level() const
The current level of this unit.
Definition: unit.hpp:575
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:515
const std::string & type_id() const
The id of this unit's type.
Definition: unit.cpp:1964
int experience() const
The current number of experience points this unit has.
Definition: unit.hpp:539
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
Definition: unit.hpp:628
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:545
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1432
std::vector< std::string > get_traits_list() const
Gets a list of the traits this unit currently has, including hidden traits.
Definition: unit.hpp:1144
std::string label
What to show in the filter's drop-down list.
Definition: manager.cpp:201
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:189
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:163
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:36
std::map< std::string, t_string > widget_item
Definition: widget.hpp:33
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Definition: parser.cpp:737
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition: markup.hpp:110
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
Definition: markup.hpp:45
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:495
std::shared_ptr< unit > unit_ptr
Definition: ptr.hpp:26
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:61
mock_char c
mock_party p
static map_location::direction n
static map_location::direction s