The Battle for Wesnoth  1.19.4+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 "font/text_formatting.hpp"
29 #include "game_events/manager.hpp"
30 #include "serialization/parser.hpp" // for write()
31 
32 #include "gettext.hpp"
33 #include "recall_list_manager.hpp"
34 #include "team.hpp"
35 #include "units/unit.hpp"
36 #include "units/map.hpp"
37 #include "ai/manager.hpp"
38 
39 #include "display_context.hpp"
40 #include "video.hpp"
41 
42 #include <vector>
43 #include <functional>
44 
45 namespace
46 {
47 
48 inline std::string config_to_string(const config& cfg)
49 {
50  std::ostringstream s;
51  write(s, cfg);
52  return s.str();
53 }
54 
55 inline std::string config_to_string(const config& cfg, std::string only_children)
56 {
57  config filtered;
58  for(const config& child : cfg.child_range(only_children)) {
59  filtered.add_child(only_children, child);
60  }
61  return config_to_string(filtered);
62 }
63 
64 }
65 
66 namespace gui2::dialogs
67 {
68 
70 {
71 public:
72  std::string name;
73 
74  std::string get_data_full() const
75  {
76  return data;
77  }
78 
79  std::string get_data_paged(int which_page)
80  {
81  if(std::size_t(which_page) >= pages.size()) {
82  return "";
83  }
84  return data.substr(pages[which_page].first, pages[which_page].second);
85  }
86 
87  void clear_data()
88  {
89  data.clear();
90  pages.clear();
91  }
92 
93  void set_data(const std::string& new_data)
94  {
95  data = new_data;
96  repaginate();
97  }
98 
100  {
101  return std::max<int>(pages.size(), 1);
102  }
103 
104 private:
105  void repaginate()
106  {
107  pages.clear();
108  std::size_t start = 0;
109  while(start + page_characters < data.size()) {
110  // This could search into data that's already on a previous page, which is why the result
111  // is then checked for end < start.
112  std::size_t end = data.find_last_of('\n', start + page_characters);
113  int len;
114  if(end == std::string::npos || end < start) {
115  len = page_characters;
116  } else {
117  len = end - start + 1;
118  }
119  pages.emplace_back(start, len);
120  start += len;
121  }
122  if(start < data.size()) {
123  pages.emplace_back(start, data.size() - start);
124  }
125  }
126  unsigned int page_characters = 10000 / video::get_pixel_scale();
127  std::string data;
128  std::vector<std::pair<std::size_t,int>> pages;
129 };
130 
132 {
133 public:
134  stuff_list_adder(tree_view_node& stuff_list, const std::string& defn)
135  : stuff_list_(stuff_list)
136  , defn_(defn)
137  {
138  }
139 
140  std::vector<int> add()
141  {
143  }
144 
145  stuff_list_adder& widget(const std::string& ref, const std::string& label, bool markup = false)
146  {
147  widget_item& item = data_[ref];
148  item["label"] = label;
149  item["use_markup"] = utils::bool_string(markup);
150  return *this;
151  }
152 
153 private:
155  const std::string defn_;
157 };
158 
160 {
161 public:
163  : stuff_list_(window.find_widget<tree_view>("stuff_list", false, true))
164  , inspect_(window.find_widget<styled_widget>("inspect", false, true))
165  , pages_(window.find_widget<styled_widget>("page_count", false, true))
166  , left_(window.find_widget<styled_widget>("page_left", false, true))
167  , right_(window.find_widget<styled_widget>("page_right", false, true))
168  {
169  }
170 
172  {
174  }
175 
176  void update(model& m)
177  {
178  int n_pages = m.count_pages();
179  current_page_ = std::min(n_pages - 1, std::max(0, current_page_));
181  if(n_pages > 1) {
182  std::ostringstream out;
183  out << current_page_ + 1 << '/' << n_pages;
184  pages_->set_label(out.str());
188  right_->set_active(current_page_ < n_pages - 1);
189  } else {
190  pages_->set_label("");
193  }
194  }
195 
197  {
198  stuff_list_->clear();
199  pages_->set_label("");
202  }
203 
204  void page(int where)
205  {
206  current_page_ += where;
207  }
208 
209 private:
210  int current_page_ = 0;
216 };
217 
219 {
220 public:
222  {
223  }
224 
226  {
227  }
228 
229 protected:
233  const config& vars() const;
234  const game_events::manager& events() const;
235  const display_context& dc() const;
236 };
237 
239 {
240 public:
243  {
244  }
245 
246  void show_list(tree_view_node& node);
247  void show_var(tree_view_node& node);
248  void show_array(tree_view_node& node);
249 };
250 
252 {
253 public:
255  void show_list(tree_view_node& node, bool is_wmi);
256  void show_event(tree_view_node& node, bool is_wmi);
257 
258 private:
260 };
261 
263 {
264 public:
267  {
268  }
269 
270  void show_list(tree_view_node& node);
271  void show_unit(tree_view_node& node);
272  void show_var(tree_view_node& node);
273  void show_array(tree_view_node& node);
274 };
275 
277 {
278 public:
281  {
282  }
283 
284  void show_list(tree_view_node& node, int side);
285  void show_ai(tree_view_node& node, int side);
286  void show_ai_components(tree_view_node& node, int side);
287  void show_ai_tree(tree_view_node& node, int side);
288  void show_recall(tree_view_node& node, int side);
289  void show_recall_unit(tree_view_node& node, int side);
290  void show_units(tree_view_node& node, int side);
291  void show_unit(tree_view_node& node, int side);
292  void show_vars(tree_view_node& node, int side);
293  void show_var(tree_view_node& node, int side);
294  void show_array(tree_view_node& node, int side);
295 };
296 
298 {
300 public:
301  controller(model& m, view& v, const config& vars, const game_events::manager& events, const display_context& dc)
302  : model_(m), view_(v)
303  , vars_(vars), events_(events), dc_(dc)
304  {
305  }
306 
308  {
309  tree_view_node* selected = dynamic_cast<tree_view&>(tree).selected_item();
310  callbacks[selected->describe_path()](*selected);
311 
312  // We recursively fold, but non-recursively unfold.
313  // This is because only one node on a level should be open at any given time.
314  // Furthermore, there's no need to remember that a subnode was open once the parent is closed.
315  if(!selected->is_root_node()) {
316  for(auto& node : selected->parent_node().children()) {
317  if(node.get() != selected) {
318  node->fold(true);
319  }
320  }
321 
322  selected->unfold();
323  }
324 
326  }
327 
329  {
331  }
332 
334  {
336  // The game state could've changed, so reset the dialog
337  callbacks.clear();
338  controllers.clear();
341  model_.clear_data();
343  }
344 
346  {
347  view_.page(next ? 1 : -1);
349  }
350 
351  template<typename T>
352  std::shared_ptr<T> get_controller()
353  {
354  for(auto& c : controllers) {
355  if(std::shared_ptr<T> p = std::dynamic_pointer_cast<T>(c)) {
356  return p;
357  }
358  }
359  std::shared_ptr<T> p = std::make_shared<T>(*this);
360  controllers.push_back(p);
361  return p;
362  }
363 
364  template<typename C>
365  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&))
366  {
367  C& sub_controller = *get_controller<C>();
368  callbacks.emplace(node_path, std::bind(fcn, sub_controller, std::placeholders::_1));
369  }
370 
371  template<typename C, typename T>
372  void set_node_callback(const std::vector<int>& node_path, void (C::* fcn)(tree_view_node&, T), T param)
373  {
374  C& sub_controller = *get_controller<C>();
375  callbacks.emplace(node_path, std::bind(fcn, sub_controller, std::placeholders::_1, param));
376  }
377 
379  {
380  auto stuff_list = window.find_widget<tree_view>("stuff_list", false, true);
381  auto copy_button = window.find_widget<button>("copy", false, true);
382  auto lua_button = window.find_widget<button>("lua", false, true);
383  auto left_button = window.find_widget<button>("page_left", false, true);
384  auto right_button = window.find_widget<button>("page_right", false, true);
385 
386  connect_signal_notify_modified(*stuff_list,
387  std::bind(&gamestate_inspector::controller::handle_stuff_list_item_clicked, this, std::placeholders::_1));
388 
390  *copy_button,
392  this));
393 
395  *lua_button,
397  this, std::ref(window)));
398 
400  *left_button,
402  this, false));
403 
405  *right_button,
407  this, true));
408 
412  }
413 
415  {
417  view_.stuff_list_entry(nullptr, "basic")
418  .widget("name", "variables")
419  .add(),
422  view_.stuff_list_entry(nullptr, "basic")
423  .widget("name", "events")
424  .add(),
426  false);
428  view_.stuff_list_entry(nullptr, "basic")
429  .widget("name", "menu items")
430  .add(),
432  true);
434  view_.stuff_list_entry(nullptr, "basic")
435  .widget("name", "units")
436  .add(),
438  int sides = dc_.teams().size();
439  for(int side = 1; side <= sides; side++) {
440  std::ostringstream label;
441  label << "team " << side;
442  const std::string& name = dc_.get_team(side).user_team_name();
443  if(!name.empty()) {
444  label << " (" << name << ")";
445  }
447  view_.stuff_list_entry(nullptr, "basic")
448  .widget("name", label.str())
449  .add(),
451  side);
452  }
453  // Expand initially selected node
454  callbacks[{0}](window.find_widget<tree_view>("stuff_list").get_root_node().get_child_at(0));
455  }
456 
457 private:
460  using node_callback = std::function<void(tree_view_node&)>;
461  using node_callback_map = std::map<std::vector<int>, node_callback>;
462  std::vector<std::shared_ptr<single_mode_controller>> controllers;
464  const config& vars_;
467 };
468 
470  return c.model_;
471 }
472 
474  return c.view_;
475 }
476 
478  return c.vars_;
479 }
480 
482  return c.events_;
483 }
484 
486  return c.dc_;
487 }
488 
491 {
493 }
494 
496 {
497  model().clear_data();
498 
499  if(node.count_children() > 0) {
500  return;
501  }
502 
503  for(const auto& attr : vars().attribute_range())
504  {
506  view().stuff_list_entry(&node, "basic")
507  .widget("name", attr.first)
508  .add(),
510  }
511 
512  std::map<std::string, std::size_t> wml_array_sizes;
513 
514  for(const auto [key, cfg] : vars().all_children_range())
515  {
516  std::ostringstream cur_str;
517  cur_str << "[" << key << "][" << wml_array_sizes[key] << "]";
518 
519  this->c.set_node_callback(
520  view().stuff_list_entry(&node, "basic")
521  .widget("name", cur_str.str())
522  .add(),
524  wml_array_sizes[key]++;
525  }
526 }
527 
529 {
530  widget* w = node.find("name", false);
531  if(label* lbl = dynamic_cast<label*>(w)) {
532  model().set_data(vars()[lbl->get_label().str()]);
533  }
534 }
535 
537 {
538  widget* w = node.find("name", false);
539  if(label* lbl = dynamic_cast<label*>(w)) {
540  const std::string& var = lbl->get_label();
541  std::size_t n_start = var.find_last_of('[') + 1;
542  std::size_t n_len = var.size() - n_start - 1;
543  int n = std::stoi(var.substr(n_start, n_len));
544  model().set_data(config_to_string(vars().mandatory_child(var.substr(1, n_start - 3), n)));
545  }
546 }
547 
549 {
550  model().clear_data();
551 
552  if(node.count_children() > 0) {
553  return;
554  }
555 
556  for(const auto & cfg : events.child_range(is_wmi ? "menu_item" : "event"))
557  {
558  std::string name = is_wmi ? cfg["id"] : cfg["name"];
559  bool named_event = !is_wmi && !cfg["id"].empty();
560 
561  auto progress = view()
562  .stuff_list_entry(&node, named_event ? "named_event" : "basic")
563  .widget("name", name);
564 
565  if(named_event) {
566  std::ostringstream out;
567  out << "id=\"" << cfg["id"] << '"';
568  progress.widget("id", out.str());
569  }
570 
571  c.set_node_callback(progress.add(), &event_mode_controller::show_event, is_wmi);
572  }
573 
574 }
575 
577 {
578  int n = node.describe_path().back();
579  model().set_data(config_to_string(events.mandatory_child(is_wmi ? "menu_item" : "event", n)));
580 }
581 
583 {
584 
585  color_t team_color = game_config::tc_info(dc.get_team(u.side()).color())[0];
586  std::stringstream s;
587 
588  s << '(' << u.get_location() << ')';
589  progress.widget("loc", s.str());
590 
591  s.str("");
592  s << font::span_color(team_color);
593  s << "side=" << u.side() << "</span>";
594  progress.widget("side", s.str(), true);
595 
596  if(u.can_recruit()) {
597  progress.widget("leader", "<span color='yellow'>LEADER</span> ", 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_range())
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_range())
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:142
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:271
config & add_child(config_key_type key)
Definition: config.cpp:439
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 &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.
tree_view_node & get_root_node()
Definition: tree_view.hpp:53
Base class for all widgets.
Definition: widget.hpp:55
NOT_DANGLING T * find_widget(const std::string &id, const bool must_be_active, const bool must_exist)
Gets a widget with the wanted id.
Definition: widget.hpp:737
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:
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: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:1023
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:1926
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:199
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 span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
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::pair< std::string, unsigned > item
Definition: help_impl.hpp:387
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:759
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