The Battle for Wesnoth  1.15.5+dev
context_manager.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 #define GETTEXT_DOMAIN "wesnoth-editor"
15 
16 #include "resources.hpp"
17 #include "team.hpp"
18 
19 #include "display.hpp"
22 #include "filesystem.hpp"
23 #include "formula/string_utils.hpp"
24 #include "game_board.hpp"
27 #include "gettext.hpp"
28 
29 #include "editor/action/action.hpp"
31 #include "preferences/editor.hpp"
32 
38 #include "gui/dialogs/message.hpp"
40 #include "gui/widgets/retval.hpp"
41 
44 #include "game_config_view.hpp"
45 
46 #include "terrain/translation.hpp"
47 
48 #include <memory>
49 
50 namespace editor {
51 
52 static std::vector<std::string> saved_windows_;
53 
54 static const std::string get_menu_marker(const bool changed)
55 {
56  std::ostringstream ss;
57  ss << "[<span ";
58 
59  if(changed) {
60  ss << "color='#f00' ";
61  }
62 
63  ss << "size='large'>" << font::unicode_bullet << "</span>]";
64  return ss.str();
65 }
66 
68  : locs_(nullptr)
69  , gui_(gui)
70  , game_config_(game_config)
71  , default_dir_(preferences::editor::default_dir())
72  , map_generators_()
73  , last_map_generator_(nullptr)
74  , current_context_index_(0)
75  , auto_update_transitions_(preferences::editor::auto_update_transitions())
76  , map_contexts_()
77  , clipboard_()
78 {
79  resources::filter_con = this;
80 
81  if(default_dir_.empty()) {
83  }
84 
86  init_map_generators(game_config);
87 }
88 
90 {
91  // Restore default window title
93 
94  resources::filter_con = nullptr;
95 }
96 
98 {
100 
101  // TODO register the tod_manager with the gui?
104 
105  gui().init_flags();
106 
107  reload_map();
108 
109  // Enable the labels of the current context;
111 
113 }
114 
116 {
117  gui_.rebuild_all();
123  if(locs_) {
124  for(const auto& loc : get_map_context().map().special_locations().left) {
125  locs_->add_item(loc.first);
126  }
127  if(!get_map_context().is_pure_map()) {
128  // If the scenario has more than 9 teams, add locations for them
129  // (First 9 teams are always in the list)
130  size_t n_teams = get_map_context().teams().size();
131  for(size_t i = 10; i <= n_teams; i++) {
132  locs_->add_item(std::to_string(i));
133  }
134  }
135  }
136 }
137 
139 {
140  gui_.reload_map();
143  refresh_all();
144 }
145 
147 {
148  switch (auto_update_transitions_) {
150  return (item == "editor-auto-update-transitions");
152  return (item == "editor-partial-update-transitions");
154  return (item == "editor-no-update-transitions");
155  }
156 
157  return true; //should not be reached
158 }
159 
161 {
164 
166  return true;
167  }
168 
169  return false;
170 }
171 
173 {
174  std::vector<std::string> modified;
175  for(auto& mc : map_contexts_) {
176  if(mc->modified()) {
177  if(!mc->get_name().empty()) {
178  modified.push_back(mc->get_name());
179  } else if(!mc->get_filename().empty()) {
180  modified.push_back(mc->get_filename());
181  } else {
182  modified.push_back(mc->get_default_context_name());
183  }
184  }
185  }
186 
187  for(std::string& str : modified) {
188  message += "\n" + font::unicode_bullet + " " + str;
189  }
190 
191  return modified.size();
192 }
193 
194 void context_manager::load_map_dialog(bool force_same_context /* = false */)
195 {
197  if(fn.empty()) {
198  fn = default_dir_;
199  }
200 
202 
203  dlg.set_title(_("Load Map"))
204  .set_path(fn);
205 
206  if(dlg.show()) {
207  load_map(dlg.path(), !force_same_context);
208  }
209 }
210 
211 void context_manager::load_mru_item(unsigned int index, bool force_same_context /* = false */)
212 {
213  const std::vector<std::string>& mru = preferences::editor::recent_files();
214  if(mru.empty() || index >= mru.size()) {
215  return;
216  }
217 
218  load_map(mru[index], !force_same_context);
219 }
220 
222 {
223  team& t = get_map_context().teams()[side_index];
224 
225  editor_team_info team_info(t);
226 
228  get_map_context().set_side_setup(team_info);
229  }
230 }
231 
233 {
234  map_context& context = get_map_context();
235 
236  // TODO
237  //std::string fn = filesystem::directory_name(context.get_filename());
238 
239  std::string id = context.get_id();
240  std::string name = context.get_name();
241  std::string description = context.get_description();
242 
243  int turns = context.get_time_manager()->number_of_turns();
244  int xp_mod = context.get_xp_mod();
245 
246  bool victory = context.victory_defeated();
247  bool random = context.random_start_time();
248 
250  id, name, description, turns, xp_mod, victory, random
251  );
252 
253  if(!ok) {
254  return;
255  }
256 
257  context.set_scenario_setup(id, name, description, turns, xp_mod, victory, random);
258 
259  if(!name.empty()) {
261  }
262 }
263 
265 {
266  const editor_map& map = get_map_context().map();
267 
268  int w = map.w();
269  int h = map.h();
270 
271  if(gui2::dialogs::editor_new_map::execute(_("New Map"), w, h)) {
273  new_map(w, h, fill, true);
274  }
275 }
276 
278 {
279  const editor_map& map = get_map_context().map();
280 
281  int w = map.w();
282  int h = map.h();
283 
284  if(gui2::dialogs::editor_new_map::execute(_("New Scenario"), w, h)) {
286  new_scenario(w, h, fill, true);
287  }
288 }
289 
290 void context_manager::expand_open_maps_menu(std::vector<config>& items, int i)
291 {
292  auto pos = items.erase(items.begin() + i);
293  std::vector<config> contexts;
294 
295  for(std::size_t mci = 0; mci < map_contexts_.size(); ++mci) {
296  map_context& mc = *map_contexts_[mci];
297 
298  std::string filename;
299  if(mc.is_pure_map()) {
300  filename = filesystem::base_name(mc.get_filename());
301  } else {
302  filename = mc.get_name();
303  }
304 
305  if(filename.empty()) {
306  filename = mc.get_default_context_name();
307  }
308 
309  std::ostringstream ss;
310  ss << "[" << mci + 1 << "] ";
311 
312  const bool changed = mc.modified();
313 
314  if(changed) {
315  ss << "<i>" << filename << "</i>";
316  } else {
317  ss << filename;
318  }
319 
320  if(mc.is_embedded()) {
321  ss << " (E)";
322  }
323 
324  const std::string label = ss.str();
325  const std::string details = get_menu_marker(changed);
326 
327  contexts.emplace_back("label", label, "details", details);
328  }
329 
330  items.insert(pos, contexts.begin(), contexts.end());
331 }
332 
333 void context_manager::expand_load_mru_menu(std::vector<config>& items, int i)
334 {
335  std::vector<std::string> mru = preferences::editor::recent_files();
336 
337  auto pos = items.erase(items.begin() + i);
338 
339  if(mru.empty()) {
340  items.insert(pos, config {"label", _("No Recent Files")});
341  return;
342  }
343 
344  for(std::string& path : mru) {
345  // TODO: add proper leading ellipsization instead, since otherwise
346  // it'll be impossible to tell apart files with identical names and
347  // different parent paths.
349  }
350 
351  std::vector<config> temp;
352  std::transform(mru.begin(), mru.end(), std::back_inserter(temp), [](const std::string& str) {
353  return config {"label", str};
354  });
355 
356  items.insert(pos, temp.begin(), temp.end());
357 }
358 
359 void context_manager::expand_areas_menu(std::vector<config>& items, int i)
360 {
362  if(!tod) {
363  return;
364  }
365 
366  auto pos = items.erase(items.begin() + i);
367  std::vector<config> area_entries;
368 
369  std::vector<std::string> area_ids = tod->get_area_ids();
370 
371  for(std::size_t mci = 0; mci < area_ids.size(); ++mci) {
372  const std::string& area = area_ids[mci];
373 
374  std::stringstream ss;
375  ss << "[" << mci + 1 << "] ";\
376 
377  if(area.empty()) {
378  ss << "<i>" << _("Unnamed Area") << "</i>";
379  } else {
380  ss << area;
381  }
382 
383  const bool changed =
384  mci == static_cast<std::size_t>(get_map_context().get_active_area())
385  && tod->get_area_by_index(mci) != get_map_context().map().selection();
386 
387  const std::string label = ss.str();
388  const std::string details = get_menu_marker(changed);
389 
390  area_entries.emplace_back("label", label, "details", details);
391  }
392 
393  items.insert(pos, area_entries.begin(), area_entries.end());
394 }
395 
396 void context_manager::expand_sides_menu(std::vector<config>& items, int i)
397 {
398  auto pos = items.erase(items.begin() + i);
399  std::vector<config> contexts;
400 
401  for(std::size_t mci = 0; mci < get_map_context().teams().size(); ++mci) {
402 
403  const team& t = get_map_context().teams()[mci];
404  const std::string& teamname = t.user_team_name();
405  std::stringstream label;
406  label << "[" << mci+1 << "] ";
407 
408  if(teamname.empty()) {
409  label << "<i>" << _("New Side") << "</i>";
410  } else {
411  label << teamname;
412  }
413 
414  contexts.emplace_back("label", label.str());
415  }
416 
417  items.insert(pos, contexts.begin(), contexts.end());
418 }
419 
420 void context_manager::expand_time_menu(std::vector<config>& items, int i)
421 {
422  auto pos = items.erase(items.begin() + i);
423  std::vector<config> times;
424 
426 
427  assert(tod_m != nullptr);
428 
429  for(const time_of_day& time : tod_m->times()) {
430  times.emplace_back(
431  "details", time.name, // Use 'details' field here since the image will take the first column
432  "image", time.image
433  );
434  }
435 
436  items.insert(pos, times.begin(), times.end());
437 }
438 
439 void context_manager::expand_local_time_menu(std::vector<config>& items, int i)
440 {
441  auto pos = items.erase(items.begin() + i);
442  std::vector<config> times;
443 
445 
446  for(const time_of_day& time : tod_m->times(get_map_context().get_active_area())) {
447  times.emplace_back(
448  "details", time.name, // Use 'details' field here since the image will take the first column
449  "image", time.image
450  );
451  }
452 
453  items.insert(pos, times.begin(), times.end());
454 }
455 
457 {
459  if(fn.empty()) {
460  fn = default_dir_;
461  }
462 
464 
465  dlg.set_title(_("Apply Mask"))
466  .set_path(fn);
467 
468  if(dlg.show()) {
469  try {
470  map_context mask(game_config_, dlg.path());
471  editor_action_apply_mask a(mask.map());
473  } catch (const editor_map_load_exception& e) {
474  gui2::show_transient_message(_("Error loading mask"), e.what());
475  return;
476  } catch (const editor_action_exception& e) {
478  return;
479  }
480  }
481 }
482 
483 void context_manager::perform_refresh(const editor_action& action, bool drag_part /* =false */)
484 {
486  refresh_after_action(drag_part);
487 }
488 
490 {
491  int active_area = get_map_context().get_active_area();
492  std::string name = get_map_context().get_time_manager()->get_area_ids()[active_area];
493 
494  if(gui2::dialogs::edit_text::execute(N_("Rename Area"), N_("Identifier:"), name)) {
495  get_map_context().get_time_manager()->set_area_id(active_area, name);
496  }
497 }
498 
500 {
502  if(fn.empty()) {
503  fn = default_dir_;
504  }
505 
507 
508  dlg.set_title(_("Choose Target Map"))
509  .set_path(fn);
510 
511  if(dlg.show()) {
512  try {
513  map_context map(game_config_, dlg.path());
514  editor_action_create_mask a(map.map());
516  } catch (const editor_map_load_exception& e) {
517  gui2::show_transient_message(_("Error loading map"), e.what());
518  return;
519  } catch (const editor_action_exception& e) {
521  return;
522  }
523  }
524 }
525 
527 {
528  if(get_map_context().needs_reload()) {
529  reload_map();
530  return;
531  }
532 
533  const std::set<map_location>& changed_locs = get_map_context().changed_locations();
534 
535  if(get_map_context().needs_terrain_rebuild()) {
538  && (!drag_part || get_map_context().everything_changed())))
539  {
540  gui_.rebuild_all();
543  } else {
544  for(const map_location& loc : changed_locs) {
545  gui_.rebuild_terrain(loc);
546  }
547  gui_.invalidate(changed_locs);
548  }
549  } else {
550  if(get_map_context().everything_changed()) {
552  } else {
553  gui_.invalidate(changed_locs);
554  }
555  }
556 
557  if(get_map_context().needs_labels_reset()) {
559  }
560 
563 }
564 
566 {
567  const editor_map& map = get_map_context().map();
568 
569  int w = map.w();
570  int h = map.h();
571 
573  bool copy = false;
574 
575  if(!gui2::dialogs::editor_resize_map::execute(w, h, dir, copy)) {
576  return;
577  }
578 
579  if(w != map.w() || h != map.h()) {
581  if(copy) {
583  }
584 
585  int x_offset = map.w() - w;
586  int y_offset = map.h() - h;
587 
588  switch (dir) {
592  y_offset = 0;
593  break;
597  y_offset /= 2;
598  break;
602  break;
603  default:
604  y_offset = 0;
605  WRN_ED << "Unknown resize expand direction" << std::endl;
606  break;
607  }
608 
609  switch (dir) {
613  x_offset = 0;
614  break;
618  x_offset /= 2;
619  break;
623  break;
624  default:
625  x_offset = 0;
626  break;
627  }
628 
629  editor_action_resize_map a(w, h, x_offset, y_offset, fill);
630  perform_refresh(a);
631  }
632 }
633 
635 {
636  std::string input_name = get_map_context().get_filename();
637  if(input_name.empty()) {
638  input_name = filesystem::get_dir(default_dir_ + "/maps");
639  }
640 
642 
643  dlg.set_title(_("Save Map As"))
644  .set_save_mode(true)
645  .set_path(input_name)
646  .set_extension(".map");
647 
648  if(!dlg.show()) {
649  return;
650  }
651 
652  save_map_as(dlg.path());
653 }
654 
656 {
657  std::string input_name = get_map_context().get_filename();
658  if(input_name.empty()) {
659  input_name = filesystem::get_dir(default_dir_ + "/scenarios");
660  }
661 
663 
664  dlg.set_title(_("Save Scenario As"))
665  .set_save_mode(true)
666  .set_path(input_name)
667  .set_extension(".cfg");
668 
669  if(!dlg.show()) {
670  return;
671  }
672 
673  save_scenario_as(dlg.path());
674 }
675 
677 {
678  for(const config& i : game_config.child_range("multiplayer")) {
679  if(i["map_generation"].empty() && i["scenario_generation"].empty()) {
680  continue;
681  }
682 
683  const config& generator_cfg = i.child("generator");
684  if(!generator_cfg) {
685  ERR_ED << "Scenario \"" << i["name"] << "\" with id " << i["id"]
686  << " has map_generation= but no [generator] tag" << std::endl;
687  } else {
688  map_generators_.emplace_back(create_map_generator(i["map_generation"].empty() ? i["scenario_generation"] : i["map_generation"], generator_cfg));
689  }
690  }
691 }
692 
694 {
695  if(map_generators_.empty()) {
696  gui2::show_error_message(_("No random map generators found."));
697  return;
698  }
699 
702 
703  if(dialog.show()) {
704  std::string map_string;
706  try {
707  map_string = map_generator->create_map(dialog.get_seed());
708  } catch (const mapgen_exception& e) {
709  gui2::show_transient_message(_("Map creation failed."), e.what());
710  return;
711  }
712 
713  if(map_string.empty()) {
714  gui2::show_transient_message("", _("Map creation failed."));
715  } else {
716  editor_map new_map(game_config_, map_string);
717  editor_action_whole_map a(new_map);
718  get_map_context().set_needs_labels_reset(); // Ensure Player Start labels are updated together with newly generated map
719  perform_refresh(a);
720  }
721 
722  last_map_generator_ = map_generator;
723  }
724 }
725 
727 {
728  if(get_map_context().modified()) {
729  const int res = gui2::show_message(_("Unsaved Changes"),
730  _("Do you want to discard all changes made to the map since the last save?"), gui2::dialogs::message::yes_no_buttons);
731  return gui2::retval::CANCEL != res;
732  }
733 
734  return true;
735 }
736 
738 {
740 }
741 
742 void context_manager::save_all_maps(bool auto_save_windows)
743 {
744  int current = current_context_index_;
745  saved_windows_.clear();
746  for(std::size_t i = 0; i < map_contexts_.size(); ++i) {
747  switch_context(i);
749  if(auto_save_windows) {
750  if(name.empty() || filesystem::is_directory(name)) {
751  std::ostringstream s;
752  s << default_dir_ << "/" << "window_" << i + 1;
753  name = s.str();
755  }
756  }
757  saved_windows_.push_back(name);
758  save_map();
759  }
760 
761  switch_context(current);
762 }
763 
765 {
766  const std::string& name = get_map_context().get_filename();
767  if(name.empty() || filesystem::is_directory(name)) {
768  if(get_map_context().is_pure_map()) {
770  } else {
772  }
773  } else {
774  if(get_map_context().is_pure_map()) {
775  write_map();
776  } else {
777  write_scenario();
778  }
779  }
780 }
781 
783 {
784  std::size_t is_open = check_open_map(filename);
785  if(is_open < map_contexts_.size() && is_open != static_cast<unsigned>(current_context_index_)) {
786  gui2::show_transient_message(_("This scenario is already open."), filename);
787  return false;
788  }
789 
790  std::string old_filename = get_map_context().get_filename();
791  bool embedded = get_map_context().is_embedded();
792 
793  get_map_context().set_filename(filename);
794  get_map_context().set_embedded(false);
795 
796  if(!write_scenario(true)) {
797  get_map_context().set_filename(old_filename);
798  get_map_context().set_embedded(embedded);
799  return false;
800  }
801 
802  return true;
803 }
804 
806 {
807  std::size_t is_open = check_open_map(filename);
808  if(is_open < map_contexts_.size() && is_open != static_cast<unsigned>(current_context_index_)) {
809  gui2::show_transient_message(_("This map is already open."), filename);
810  return false;
811  }
812 
813  std::string old_filename = get_map_context().get_filename();
814  bool embedded = get_map_context().is_embedded();
815 
816  get_map_context().set_filename(filename);
817  get_map_context().set_embedded(false);
818 
819  if(!write_map(true)) {
820  get_map_context().set_filename(old_filename);
821  get_map_context().set_embedded(embedded);
822  return false;
823  }
824 
825  return true;
826 }
827 
828 bool context_manager::write_scenario(bool display_confirmation)
829 {
830  try {
832  if(display_confirmation) {
833  gui2::show_transient_message("", _("Scenario saved."));
834  }
835  } catch (const editor_map_save_exception& e) {
837  return false;
838  }
839 
840  return true;
841 }
842 
843 bool context_manager::write_map(bool display_confirmation)
844 {
845  try {
847  if(display_confirmation) {
848  gui2::show_transient_message("", _("Map saved."));
849  }
850  } catch (const editor_map_save_exception& e) {
852  return false;
853  }
854 
855  return true;
856 }
857 
858 std::size_t context_manager::check_open_map(const std::string& fn) const
859 {
860  std::size_t i = 0;
861  while(i < map_contexts_.size() && map_contexts_[i]->get_filename() != fn) {
862  ++i;
863  }
864 
865  return i;
866 }
867 
869 {
870  std::size_t i = check_open_map(fn);
871  if(i < map_contexts_.size()) {
872  gui2::show_transient_message(_("This map is already open."), fn);
873  switch_context(i);
874  return true;
875  }
876 
877  return false;
878 }
879 
880 void context_manager::load_map(const std::string& filename, bool new_context)
881 {
882  if(new_context && check_switch_open_map(filename)) {
883  return;
884  }
885 
886  LOG_ED << "Load map: " << filename << (new_context ? " (new)" : " (same)") << "\n";
887  try {
888  {
889  context_ptr mc(new map_context(game_config_, filename));
890  if(mc->get_filename() != filename) {
891  if(new_context && check_switch_open_map(mc->get_filename())) {
892  return;
893  }
894  }
895 
896  if(new_context) {
897  int new_id = add_map_context_of(std::move(mc));
898  switch_context(new_id);
899  } else {
900  replace_map_context_with(std::move(mc));
901  }
902  }
903 
904  if(get_map_context().is_embedded()) {
905  const std::string& msg = _("Loaded embedded map data");
906  gui2::show_transient_message(_("Map loaded from scenario"), msg);
907  } else {
908  if(get_map_context().get_filename() != filename) {
909  if(get_map_context().get_map_data_key().empty()) {
910  ERR_ED << "Internal error, map context filename changed: "
911  << filename << " -> " << get_map_context().get_filename()
912  << " with no apparent scenario load\n";
913  } else {
914  utils::string_map symbols;
915  symbols["old"] = filename;
916  const std::string& msg = _("Loaded referenced map file:\n$new");
917  symbols["new"] = get_map_context().get_filename();
918  symbols["map_data"] = get_map_context().get_map_data_key();
919  gui2::show_transient_message(_("Map loaded from scenario"),
920  //TODO: msg is already translated does vgettext make sense?
921  VGETTEXT(msg.c_str(), symbols));
922  }
923  }
924  }
925  } catch(const editor_map_load_exception& e) {
926  gui2::show_transient_message(_("Error loading map"), e.what());
927  return;
928  }
929 }
930 
932 {
933  if(!confirm_discard()) {
934  return;
935  }
936 
938  if(filename.empty()) {
939  ERR_ED << "Empty filename in map revert" << std::endl;
940  return;
941  }
942 
943  load_map(filename, false);
944 }
945 
946 void context_manager::new_map(int width, int height, const t_translation::terrain_code& fill, bool new_context)
947 {
948  const config& default_schedule = game_config_.find_child("editor_times", "id", "default");
949  editor_map m(game_config_, width, height, fill);
950 
951  if(new_context) {
952  int new_id = add_map_context(m, true, default_schedule);
953  switch_context(new_id);
954  } else {
955  replace_map_context(m, true, default_schedule);
956  }
957 }
958 
959 void context_manager::new_scenario(int width, int height, const t_translation::terrain_code& fill, bool new_context)
960 {
961  const config& default_schedule = game_config_.find_child("editor_times", "id", "default");
962  editor_map m(game_config_, width, height, fill);
963 
964  if(new_context) {
965  int new_id = add_map_context(m, false, default_schedule);
966  switch_context(new_id);
967  } else {
968  replace_map_context(m, false, default_schedule);
969  }
970 
971  // Give the new scenario an initial side.
973  gui_.init_flags();
974 }
975 
976 //
977 // Context manipulation
978 //
979 
980 template<typename... T>
981 int context_manager::add_map_context(const T&... args)
982 {
983  map_contexts_.emplace_back(new map_context(args...));
984  return map_contexts_.size() - 1;
985 }
986 
988 {
989  map_contexts_.emplace_back(std::move(mc));
990  return map_contexts_.size() - 1;
991 }
992 
993 template<typename... T>
995 {
996  context_ptr new_mc(new map_context(args...));
997  replace_map_context_with(std::move(new_mc));
998 }
999 
1001 {
1004 }
1005 
1007 {
1008  if(saved_windows_.empty()) {
1011 
1012  const config& default_schedule = game_config_.find_child("editor_times", "id", "default");
1013  add_map_context(editor_map(game_config_, 44, 33, default_terrain), true, default_schedule);
1014  } else {
1015  for(const std::string& filename : saved_windows_) {
1016  add_map_context(game_config_, filename);
1017  }
1018 
1019  saved_windows_.clear();
1020  }
1021 }
1022 
1024 {
1025  if(!confirm_discard()) return;
1026 
1027  if(map_contexts_.size() == 1) {
1029  map_contexts_.erase(map_contexts_.begin());
1030  } else if(current_context_index_ == static_cast<int>(map_contexts_.size()) - 1) {
1031  map_contexts_.pop_back();
1033  } else {
1035  }
1036 
1038 }
1039 
1040 void context_manager::switch_context(const int index, const bool force)
1041 {
1042  if(index < 0 || static_cast<std::size_t>(index) >= map_contexts_.size()) {
1043  WRN_ED << "Invalid index in switch map context: " << index << std::endl;
1044  return;
1045  }
1046 
1047  if(index == current_context_index_ && !force) {
1048  return;
1049  }
1050 
1051  // Disable the labels of the current context before switching.
1052  // The refresher handles enabling the new ones.
1053  get_map_context().get_labels().enable(false);
1054 
1056 
1058 }
1059 
1061 {
1063 
1064  if(name.empty()) {
1066  }
1067 
1068  if(name.empty()){
1070  }
1071 
1072  const std::string& wm_title_string = name + " - " + game_config::get_default_title_string();
1073  CVideo::get_singleton().set_window_title(wm_title_string);
1074 }
1075 
1076 } //Namespace editor
int auto_update_transitions()
Definition: editor.cpp:24
bool write_scenario(bool display_confirmation=false)
Dialog was closed with the CANCEL button.
Definition: retval.hpp:37
void set_side_setup(editor_team_info &info)
TODO.
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition: message.cpp:152
const std::string & get_name() const
boost::optional< uint32_t > get_seed()
::tod_manager * tod_manager
Definition: resources.cpp:29
int h() const
Effective map height, in hexes.
Definition: map.hpp:128
void apply_mask_dialog()
Display an apply mask dialog and process user input.
std::size_t check_open_map(const std::string &fn) const
Check if a map is already open.
bool check_switch_open_map(const std::string &fn)
Check if a map is already open.
std::unique_ptr< map_context > context_ptr
std::size_t modified_maps(std::string &modified)
int auto_update_transitions_
Flag to rebuild terrain on every terrain change.
const t_translation::terrain_code & get_selected_bg_terrain()
std::vector< std::string > recent_files()
Retrieves the list of recently opened files.
Definition: editor.cpp:118
const terrain_code NONE_TERRAIN
Definition: translation.hpp:59
void edit_scenario_dialog()
Display a scenario edit dialog and process user input.
std::map< std::string, t_string > string_map
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3025
file_dialog & set_extension(const std::string &value)
Sets the default file extension for file names in save mode.
game_classification * classification
Definition: resources.cpp:34
file_dialog & set_path(const std::string &value)
Sets the initial file selection.
void change_display_context(const display_context *dc)
Definition: display.cpp:509
void replace_map_context_with(context_ptr &&mc)
std::vector< context_ptr > map_contexts_
The currently opened map context object.
void new_side()
Adds a new side to the map.
void reload_map()
Reload the map after it has significantly changed (when e.g.
bool save_scenario()
Saves the scenario under the current filename.
void resize_map_dialog()
Display a load map dialog and process user input.
#define a
config_array_view child_range(config_key_type key) const
void save_scenario_as_dialog()
Display a save map as dialog and process user input.
void rename_area_dialog()
Display an dialog to querry a new id for an [time_area].
void refresh_after_action(bool drag_part=false)
Refresh the display after an action has been performed.
void init_flags()
Init the flag list and the team colors used by ~TC.
Definition: display.cpp:301
const std::string & get_filename() const
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup, const bool restore_background)
Shows a transient message to the user.
void set_area_id(int area_index, const std::string &id)
map_labels & get_labels()
void save_map()
Save the map, open dialog if not named yet.
#define LOG_ED
General purpose widgets.
std::string default_dir_
Default directory for map load/save as dialogs.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:50
std::string get_default_title_string()
void perform_refresh(const editor_action &action, bool drag_part=false)
Perform an action on the current map_context, then refresh the display.
file_dialog & set_save_mode(bool value)
Sets the dialog&#39;s behavior on non-existent file name inputs.
static CVideo & get_singleton()
Definition: video.hpp:48
#define h
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
const std::vector< std::string > items
int add_map_context(const T &... args)
Add a map context.
Replace contents of the entire map, Useful as a fallback undo method when something else would be imp...
Definition: action.hpp:37
std::string str
Definition: statement.cpp:110
int get_xp_mod() const
-file sdl_utils.hpp
bool show(const unsigned auto_close_time=0)
Shows the window.
bool confirm_discard()
Shows an are-you-sure dialog if the map was modified.
void set_needs_reload(bool value=true)
Setter for the reload flag.
map_context & get_map_context()
Get the current map context object.
void refresh_all()
Refresh everything, i.e.
int add_map_context_of(context_ptr &&mc)
map_generator * get_selected_map_generator()
void set_scenario_setup(const std::string &id, const std::string &name, const std::string &description, int turns, int xp_mod, bool victory_defeated, bool random_time)
TODO.
static bfs::path get_dir(const bfs::path &dirpath)
Definition: filesystem.cpp:278
void revert_map()
Revert the map by reloading it from disk.
const std::string & get_id() const
bool modified() const
void expand_areas_menu(std::vector< config > &items, int i)
Menu expanding for the map&#39;s defined areas.
std::string path() const
Gets the current file selection.
std::string default_dir()
Definition: editor.cpp:32
#define WRN_ED
game_classification & get_classification()
void set_window_title(const std::string &title)
Sets the title of the main window.
Definition: video.cpp:354
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:57
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
void close_current_context()
Closes the active map context.
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:100
const std::set< map_location > & selection() const
Return the selection set.
Definition: editor_map.hpp:149
void load_map_dialog(bool force_same_context=false)
Display a load map dialog and process user input.
std::string get_user_data_dir()
Definition: filesystem.cpp:795
void reset_starting_position_labels(display &disp)
void recalculate_minimap()
Schedule the minimap for recalculation.
Definition: display.hpp:616
void select_map_generator(map_generator *mg)
filter_context * filter_con
Definition: resources.cpp:23
void set_embedded(bool v)
const game_config_view & game_config_
const std::set< map_location > changed_locations() const
void set_auto_update_transitions(int value)
Definition: editor.cpp:28
void new_scenario_dialog()
Display a new map dialog and process user input.
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
Editor action classes.
bool random_start_time() const
bool save_map()
Saves the map under the current filename.
void enable(bool is_enabled)
Definition: label.cpp:253
std::string path
Definition: game_config.cpp:39
Modify, read and display user preferences.
Shows a yes and no button.
Definition: message.hpp:79
map_display and display: classes which take care of displaying the map and game-data on the screen...
void refresh_on_context_change()
Performs the necessary housekeeping necessary when switching contexts.
bool is_pure_map() const
void create_buttons()
Definition: display.cpp:873
Manage the empty-palette in the editor.
Definition: action.cpp:29
std::string default_terrain
Definition: game_config.cpp:70
void perform_action(const editor_action &action)
Performs an action (thus modifying the map).
const char * what() const noexcept
Definition: exceptions.hpp:37
void invalidate_all()
Function to invalidate all tiles.
Definition: display.cpp:3018
bool is_active_transitions_hotkey(const std::string &item)
void switch_context(const int index, const bool force=false)
Switches the context to the one under the specified index.
void new_scenario(int width, int height, const t_translation::terrain_code &fill, bool new_context)
Create a new scenario.
Paint the same terrain on a number of locations on the map.
Definition: action.hpp:284
void new_map(int width, int height, const t_translation::terrain_code &fill, bool new_context)
Create a new map.
bool is_embedded() const
int number_of_turns() const
void load_map(const std::string &filename, bool new_context)
Load a map given the filename.
virtual std::string create_map(boost::optional< uint32_t > randomseed=boost::none)=0
Creates a new map and returns it.
std::vector< std::string > get_area_ids() const
void set_needs_terrain_rebuild(bool value=true)
Setter for the terrain rebuild flag.
Encapsulates the map of the game.
Definition: location.hpp:42
class location_palette * locs_
const std::string & get_description() const
void clear_changed_locations()
int w() const
Effective map width, in hexes.
Definition: map.hpp:125
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:69
map_generator * create_map_generator(const std::string &name, const config &cfg, const config *vars)
Definition: map_create.cpp:28
std::size_t i
Definition: function.cpp:933
void add_item(const std::string &id)
void fill_selection()
Fill the selection with the foreground terrain.
void save_map_as_dialog()
Display a save map as dialog and process user input.
bool write_map(bool display_confirmation=false)
Save the map under a given filename.
Game configuration data as global variables.
Definition: build_info.cpp:55
void expand_local_time_menu(std::vector< config > &items, int i)
Menu expanding for the map&#39;s defined areas.
void rebuild_terrain(const map_location &loc)
bool save_scenario_as(const std::string &filename)
const tod_manager * get_time_manager() const
static map_location::DIRECTION s
const std::vector< time_of_day > & times(const map_location &loc=map_location::null_location()) const
editor_display & gui()
Base class for all editor actions.
Definition: action_base.hpp:40
terrain_code read_terrain_code(utils::string_view str, const ter_layer filler)
Reads a single terrain from a string.
void save_all_maps(bool auto_save_windows=false)
Save all maps, open dialog if not named yet, except when using auto_save_windows which will name unna...
const std::string & get_map_data_key() const
void create_mask_to_dialog()
Display an apply mask dialog and process user input.
Declarations for File-IO.
int w
This class wraps around a map to provide a concise interface for the editor to work with...
Definition: map_context.hpp:58
#define N_(String)
Definition: gettext.hpp:108
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
const std::string unicode_bullet
Definition: constants.cpp:43
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
void replace_map_context(const T &... args)
Replace the current map context and refresh accordingly.
const config & find_child(config_key_type key, const std::string &name, const std::string &value) const
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
context_manager(editor_display &gui, const game_config_view &game_config)
void expand_sides_menu(std::vector< config > &items, int i)
Menu expanding for the map&#39;s player sides.
bool victory_defeated() const
static std::string get_filename(const std::string &file_code)
map_generator * last_map_generator_
int turns()
Definition: game.cpp:582
void edit_side_dialog(int side_index)
Display a side edit dialog and process user input.
double t
Definition: astarsearch.cpp:64
void reload_map()
Updates internals that cache map size.
Definition: display.cpp:503
virtual const editor_map & map() const override
Const map accessor.
lu_byte left
Definition: lparser.cpp:1026
int get_active_area() const
#define ERR_ED
void set_needs_labels_reset(bool value=true)
Setter for the labels reset flag.
std::vector< std::unique_ptr< map_generator > > map_generators_
Available random map generators.
void set_filename(const std::string &fn)
void expand_load_mru_menu(std::vector< config > &items, int i)
Menu expanding for most recent loaded list.
const std::set< map_location > & get_area_by_index(int index) const
void init_map_generators(const game_config_view &game_config)
init available random map generators
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
Definition: message.cpp:205
void generate_map_dialog()
Display a generate random map dialog and process user input.
void set_window_title()
Displays the specified map name in the window titlebar.
void create_default_context()
Creates a default map context object, used to ensure there is always at least one.
The dialog for selecting which random generator to use in the editor.
#define e
bool save_map_as(const std::string &filename)
Save the map under a given filename.
void expand_time_menu(std::vector< config > &items, int i)
Menu expanding for the map&#39;s defined areas.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
void load_mru_item(unsigned index, bool force_same_context=false)
Open the specified entry from the recent files list.
virtual const std::vector< team > & teams() const override
Const teams accessor.
static std::vector< std::string > saved_windows_
static const std::string get_menu_marker(const bool changed)
void expand_open_maps_menu(std::vector< config > &items, int i)
Menu expanding for open maps list.
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
const t_string & user_team_name() const
Definition: team.hpp:298
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:384
const t_string get_default_context_name() const
void rebuild_all()
Rebuild all dynamic terrain.
Definition: display.cpp:498
auto * ss
Definition: result_set.cpp:281
void new_map_dialog()
Display a new map dialog and process user input.
file_dialog & set_title(const std::string &value)
Sets the current dialog title text.
Definition: file_dialog.hpp:56