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 "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  io::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  callbacks.emplace(node_path, [=, sub_controller = get_controller<C>()](auto& node) {
369  std::invoke(fcn, *sub_controller, node);
370  });
371  }
372 
373  template<typename C, typename T>
374  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&, T), T param)
375  {
376  callbacks.emplace(node_path, [=, sub_controller = get_controller<C>()](auto& node) {
377  std::invoke(fcn, *sub_controller, node, param);
378  });
379  }
380 
382  {
383  auto stuff_list = window.find_widget<tree_view>("stuff_list", false, true);
384  auto copy_button = window.find_widget<button>("copy", false, true);
385  auto lua_button = window.find_widget<button>("lua", false, true);
386  auto left_button = window.find_widget<button>("page_left", false, true);
387  auto right_button = window.find_widget<button>("page_right", false, true);
388 
389  connect_signal_notify_modified(*stuff_list,
390  [this](widget& w, auto&&...) { handle_stuff_list_item_clicked(w); });
391 
392  connect_signal_mouse_left_click(*copy_button,
393  [this](auto&&...) { handle_copy_button_clicked(); });
394 
396  [this, &window](auto&&...) { handle_lua_button_clicked(window); }); // TODO: no window ref
397 
398  connect_signal_mouse_left_click(*left_button,
399  [this](auto&&...) { handle_page_button_clicked(false); });
400 
401  connect_signal_mouse_left_click(*right_button,
402  [this](auto&&...) { handle_page_button_clicked(true); });
403 
407  }
408 
410  {
412  view_.stuff_list_entry(nullptr, "basic")
413  .widget("name", "variables")
414  .add(),
417  view_.stuff_list_entry(nullptr, "basic")
418  .widget("name", "events")
419  .add(),
421  false);
423  view_.stuff_list_entry(nullptr, "basic")
424  .widget("name", "menu items")
425  .add(),
427  true);
429  view_.stuff_list_entry(nullptr, "basic")
430  .widget("name", "units")
431  .add(),
433  int sides = dc_.teams().size();
434  for(int side = 1; side <= sides; side++) {
435  std::ostringstream label;
436  label << "team " << side;
437  const std::string& name = dc_.get_team(side).user_team_name();
438  if(!name.empty()) {
439  label << " (" << name << ")";
440  }
442  view_.stuff_list_entry(nullptr, "basic")
443  .widget("name", label.str())
444  .add(),
446  side);
447  }
448  // Expand initially selected node
449  callbacks[{0}](window.find_widget<tree_view>("stuff_list").get_root_node().get_child_at(0));
450  }
451 
452 private:
455  using node_callback = std::function<void(tree_view_node&)>;
456  using node_callback_map = std::map<std::vector<int>, node_callback>;
457  std::vector<std::shared_ptr<single_mode_controller>> controllers;
459  const config& vars_;
462 };
463 
465  return c.model_;
466 }
467 
469  return c.view_;
470 }
471 
473  return c.vars_;
474 }
475 
477  return c.events_;
478 }
479 
481  return c.dc_;
482 }
483 
486 {
488 }
489 
491 {
492  model().clear_data();
493 
494  if(node.count_children() > 0) {
495  return;
496  }
497 
498  for(const auto& attr : vars().attribute_range())
499  {
501  view().stuff_list_entry(&node, "basic")
502  .widget("name", attr.first)
503  .add(),
505  }
506 
507  std::map<std::string, std::size_t> wml_array_sizes;
508 
509  for(const auto [key, cfg] : vars().all_children_view())
510  {
511  std::ostringstream cur_str;
512  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
513 
514  this->c.set_node_callback(
515  view().stuff_list_entry(&node, "basic")
516  .widget("name", cur_str.str())
517  .add(),
519  wml_array_sizes[key]++;
520  }
521 }
522 
524 {
525  widget* w = node.find("name", false);
526  if(label* lbl = dynamic_cast<label*>(w)) {
527  model().set_data(vars()[lbl->get_label().str()]);
528  }
529 }
530 
532 {
533  widget* w = node.find("name", false);
534  if(label* lbl = dynamic_cast<label*>(w)) {
535  const std::string& var = lbl->get_label();
536  std::size_t n_start = var.find_last_of('[') + 1;
537  std::size_t n_len = var.size() - n_start - 1;
538  int n = std::stoi(var.substr(n_start, n_len));
539  model().set_data(config_to_string(vars().mandatory_child(var.substr(1, n_start - 3), n)));
540  }
541 }
542 
544 {
545  model().clear_data();
546 
547  if(node.count_children() > 0) {
548  return;
549  }
550 
551  for(const auto & cfg : events.child_range(is_wmi ? "menu_item" : "event"))
552  {
553  std::string name = is_wmi ? cfg["id"] : cfg["name"];
554  bool named_event = !is_wmi && !cfg["id"].empty();
555 
556  auto progress = view()
557  .stuff_list_entry(&node, named_event ? "named_event" : "basic")
558  .widget("name", name);
559 
560  if(named_event) {
561  std::ostringstream out;
562  out << "id=\"" << cfg["id"] << '"';
563  progress.widget("id", out.str());
564  }
565 
566  c.set_node_callback(progress.add(), &event_mode_controller::show_event, is_wmi);
567  }
568 
569 }
570 
572 {
573  int n = node.describe_path().back();
574  model().set_data(config_to_string(events.mandatory_child(is_wmi ? "menu_item" : "event", n)));
575 }
576 
578 {
579 
580  color_t team_color = game_config::tc_info(dc.get_team(u.side()).color())[0];
581  std::stringstream s;
582 
583  s << '(' << u.get_location() << ')';
584  progress.widget("loc", s.str());
585 
586  s.str("");
587  s << markup::span_color(team_color, "side=", u.side());
588  progress.widget("side", s.str(), true);
589 
590  if(u.can_recruit()) {
591  progress.widget("leader", markup::span_color("yellow", "LEADER "), true);
592  }
593 
594  s.str("");
595  s << "id=\"" << u.id() << '"';
596  progress.widget("id", s.str());
597 
598  progress.widget("type", u.type_id());
599 
600  s.str("");
601  s << "L" << u.level();
602  progress.widget("level", s.str());
603 
604  s.str("");
605  s << u.experience() << '/' << u.max_experience() << " xp";
606  progress.widget("xp", s.str());
607 
608  s.str("");
609  s << u.hitpoints() << '/' << u.max_hitpoints() << " hp";
610  progress.widget("hp", s.str());
611 
612  progress.widget("traits", utils::join(u.get_traits_list(), ", "));
613 
614  return progress;
615 }
616 
618 {
619  model().clear_data();
620 
621  if(node.count_children() > 0) {
622  return;
623  }
624 
625  for(unit_map::const_iterator i = dc().units().begin(); i != dc().units().end(); ++i) {
626  auto progress = view().stuff_list_entry(&node, "unit");
627  add_unit_entry(progress, *i, dc());
629  }
630 }
631 
633 {
634  int i = node.describe_path().back();
636  std::advance(u, i);
637  config c_unit;
638  u->write(c_unit);
639  model().set_data(config_to_string(c_unit));
640 
641  if(node.count_children() > 0) {
642  return;
643  }
644 
645  for(const auto& attr : u->variables().attribute_range())
646  {
648  view().stuff_list_entry(&node, "basic")
649  .widget("name", attr.first)
650  .add(),
652  }
653 
654  std::map<std::string, std::size_t> wml_array_sizes;
655 
656  for(const auto [key, cfg] : u->variables().all_children_view())
657  {
658  std::ostringstream cur_str;
659  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
660 
661  this->c.set_node_callback(
662  view().stuff_list_entry(&node, "basic")
663  .widget("name", cur_str.str())
664  .add(),
666  wml_array_sizes[key]++;
667  }
668 }
669 
671 {
672  widget* w = node.find("name", false);
673  int i = node.describe_path().back();
675  std::advance(u, i);
676  if(label* lbl = dynamic_cast<label*>(w)) {
677  model().set_data(u->variables()[lbl->get_label().str()]);
678  }
679 }
680 
682 {
683  widget* w = node.find("name", false);
684  int i = node.describe_path().back();
686  std::advance(u, i);
687  if(label* lbl = dynamic_cast<label*>(w)) {
688  const std::string& var = lbl->get_label();
689  std::size_t n_start = var.find_last_of('[') + 1;
690  std::size_t n_len = var.size() - n_start - 1;
691  int n = std::stoi(var.substr(n_start, n_len));
692  model().set_data(config_to_string(u->variables().mandatory_child(var.substr(1, n_start - 3), n)));
693  }
694 }
695 
697 {
698  config&& cfg = dc().get_team(side).to_config();
699  cfg.clear_children("ai");
700  model().set_data(config_to_string(cfg));
701 
702  if(node.count_children() > 0) {
703  return;
704  }
705 
707  view().stuff_list_entry(&node, "basic")
708  .widget("name", "ai")
709  .add(),
711  side);
713  view().stuff_list_entry(&node, "basic")
714  .widget("name", "recall list")
715  .add(),
717  side);
719  view().stuff_list_entry(&node, "basic")
720  .widget("name", "units")
721  .add(),
723  side);
725  view().stuff_list_entry(&node, "basic")
726  .widget("name", "variables")
727  .add(),
729  side);
730 }
731 
733 {
734  model().set_data(ai::manager::get_singleton().get_active_ai_overview_for_side(side));
735 
736  if(node.count_children() > 0) {
737  return;
738  }
739 
741  view().stuff_list_entry(&node, "basic")
742  .widget("name", "engines")
743  .add(),
745  side);
747  view().stuff_list_entry(&node, "basic")
748  .widget("name", "stages")
749  .add(),
751  side);
753  view().stuff_list_entry(&node, "basic")
754  .widget("name", "aspects")
755  .add(),
757  side);
759  view().stuff_list_entry(&node, "basic")
760  .widget("name", "goals")
761  .add(),
763  side);
765  view().stuff_list_entry(&node, "basic")
766  .widget("name", "component structure")
767  .add(),
769  side);
770 }
771 
773 {
774  widget* w = node.find("name", false);
775  if(label* lbl = dynamic_cast<label*>(w)) {
776  std::string tag = lbl->get_label();
777  tag.pop_back();
778  model().set_data(config_to_string(ai::manager::get_singleton().to_config(side), tag));
779  }
780 }
781 
783 {
784  model().clear_data();
785 
786  if(node.count_children() > 0) {
787  return;
788  }
789 
790  for(const unit_ptr& u : dc().get_team(side).recall_list()) {
791  auto progress = view().stuff_list_entry(&node, "unit");
792  add_unit_entry(progress, *u, dc());
794  }
795 }
796 
798 {
799  int i = node.describe_path().back();
800  auto u = dc().get_team(side).recall_list().begin();
801  std::advance(u, i);
802  config c_unit;
803  (*u)->write(c_unit);
804  model().set_data(config_to_string(c_unit));
805 }
806 
808 {
809  model().set_data(ai::manager::get_singleton().get_active_ai_structure_for_side(side));
810 }
811 
813 {
814  std::ostringstream s;
815  for(unit_map::const_iterator i = dc().units().begin(); i != dc().units().end();
816  ++i) {
817  if(i->side() != side) {
818  continue;
819  }
820  s << '(' << i->get_location() << ") ";
821  if(i->can_recruit()) {
822  s << "LEADER ";
823  }
824 
825  s << "\nid=\"" << i->id() << "\" (" << i->type_id() << ")\n"
826  << "L" << i->level() << "; " << i->experience() << '/'
827  << i->max_experience() << " XP; " << i->hitpoints() << '/'
828  << i->max_hitpoints() << " HP\n";
829  for(const auto & str : i->get_traits_list())
830  {
831  s << "\t" << str << std::endl;
832  }
833  s << std::endl;
834  }
835  model().set_data(s.str());
836 }
837 
839 {
840  model().clear_data();
841 
842  if(node.count_children() > 0) {
843  return;
844  }
845 
846  const team& t = dc().get_team(side);
847 
848  for(const auto& attr : t.variables().attribute_range())
849  {
851  view().stuff_list_entry(&node, "basic")
852  .widget("name", attr.first)
853  .add(),
855  side);
856  }
857 
858  std::map<std::string, std::size_t> wml_array_sizes;
859 
860  for(const auto [key, cfg] : t.variables().all_children_view())
861  {
862  std::ostringstream cur_str;
863  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
864 
865  this->c.set_node_callback(
866  view().stuff_list_entry(&node, "basic")
867  .widget("name", cur_str.str())
868  .add(),
870  side);
871  wml_array_sizes[key]++;
872  }
873 }
874 
876 {
877  widget* w = node.find("name", false);
878  const team& t = dc().get_team(side);
879  if(label* lbl = dynamic_cast<label*>(w)) {
880  model().set_data(t.variables()[lbl->get_label().str()]);
881  }
882 }
883 
885 {
886  widget* w = node.find("name", false);
887  const team& t = dc().get_team(side);
888  if(label* lbl = dynamic_cast<label*>(w)) {
889  const std::string& var = lbl->get_label();
890  std::size_t n_start = var.find_last_of('[') + 1;
891  std::size_t n_len = var.size() - n_start - 1;
892  int n = std::stoi(var.substr(n_start, n_len));
893  model().set_data(config_to_string(t.variables().mandatory_child(var.substr(1, n_start - 3), n)));
894  }
895 }
896 
898 
899 gamestate_inspector::gamestate_inspector(const config& vars, const game_events::manager& events, const display_context& dc, const std::string& title)
900  : modal_dialog(window_id())
901  , title_(title)
902  , vars_(vars)
903  , events_(events)
904  , dc_(dc)
905 {
906  model_.reset(new model);
907 }
908 
910 {
911  view_.reset(new view(*this));
912  controller_.reset(new controller(*model_, *view_, vars_, events_, dc_));
913 
914  if(!title_.empty()) {
915  find_widget<styled_widget>("inspector_name").set_label(title_);
916  }
917  controller_->bind(*this);
918  view_->update(*model_);
919 }
920 
921 } // 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: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: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:75
const std::string & color() const
Definition: team.hpp:247
config to_config() const
Definition: team.cpp:1035
recall_list_manager & recall_list()
Definition: team.hpp:206
const t_string & user_team_name() const
Definition: team.hpp:288
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:1970
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