The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
manager_impl.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://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 
16 
17 #include "game_events/handlers.hpp"
19 #include "game_events/pump.hpp"
20 
21 #include "formula/string_utils.hpp"
22 #include "game_data.hpp"
23 #include "log.hpp"
24 #include "reports.hpp"
27 
28 #include <boost/algorithm/string.hpp>
29 
30 #include <iostream>
31 
32 static lg::log_domain log_engine("engine");
33 #define DBG_NG LOG_STREAM(debug, log_engine)
34 #define LOG_NG LOG_STREAM(info, log_engine)
35 #define WRN_NG LOG_STREAM(warn, log_engine)
36 
37 static lg::log_domain log_event_handler("event_handler");
38 #define DBG_EH LOG_STREAM(debug, log_event_handler)
39 
40 namespace game_events
41 {
43 {
44  if(lg::debug().dont_log("event_handler")) {
45  return;
46  }
47 
48  std::stringstream ss;
49 
50  for(const handler_ptr& h : active_) {
51  if(!h) {
52  continue;
53  }
54 
55  const config& cfg = h->get_config();
56  ss << "name=" << cfg["name"] << ", with id=" << cfg["id"] << "; ";
57  }
58 
59  DBG_EH << "active handlers are now " << ss.str() << "\n";
60 }
61 
62 /**
63  * Utility to standardize the event names used in by_name_.
64  * This means stripping leading and trailing spaces, and converting internal
65  * spaces to underscores.
66  */
68 {
69  std::string retval = name;
70 
71  // Trim leading and trailing spaces.
72  boost::trim(retval);
73 
74  // Replace internal spaces with underscores.
75  boost::replace_all(retval, " ", "_");
76 
77  return retval;
78 }
79 
80 /**
81  * Read-only access to the handlers with fixed event names, by event name.
82  */
84 {
85  // Empty list for the "not found" case.
86  static const handler_list empty_list;
87 
88  // Look for the name in the name map.
89  auto find_it = by_name_.find(standardize_name(name));
90  return find_it == by_name_.end() ? empty_list : find_it->second;
91 }
92 
93 /**
94  * Adds an event handler.
95  * An event with a nonempty ID will not be added if an event with that
96  * ID already exists.
97  */
98 void event_handlers::add_event_handler(const config& cfg, manager& man, bool is_menu_item)
99 {
100  const std::string name = cfg["name"];
101  std::string id = cfg["id"];
102 
103  if(!id.empty()) {
104  // Ignore this handler if there is already one with this ID.
105  auto find_it = id_map_.find(id);
106  if(find_it != id_map_.end() && !find_it->second.expired()) {
107  DBG_EH << "ignoring event handler for name='" << name << "' with id '" << id << "'\n";
108  return;
109  }
110  }
111 
112  // Create a new handler.
113  DBG_EH << "inserting event handler for name=" << name << " with id=" << id << "\n";
114  handler_ptr new_handler(new event_handler(cfg, is_menu_item, active_.size(), man));
115 
116  active_.push_back(new_handler);
117 
118  // File by name.
120  dynamic_.push_back(new_handler);
121  } else {
122  for(const std::string& single_name : utils::split(name)) {
123  by_name_[standardize_name(single_name)].push_back(new_handler);
124  }
125  }
126 
127  // File by ID.
128  if(!id.empty()) {
129  id_map_[id] = new_handler;
130  }
131 
132  log_handlers();
133 }
134 
135 /**
136  * Removes an event handler, identified by its ID.
137  * Events with empty IDs cannot be removed.
138  */
140 {
141  if(id.empty()) {
142  return;
143  }
144 
145  DBG_EH << "removing event handler with id " << id << "\n";
146 
147  // Find the existing handler with this ID.
148  auto find_it = id_map_.find(id);
149  if(find_it != id_map_.end()) {
150  handler_ptr handler = find_it->second.lock();
151 
152  // Remove handler.
153  if(handler) {
154  handler->disable();
155  }
156 
157  // Do this even if the lock failed.
158  // The index by name will self-adjust later. No need to adjust it now.
159  id_map_.erase(find_it);
160  }
161 
162  log_handlers();
163 }
164 
166 {
167  auto find_it = id_map_.find(id);
168  if(find_it != id_map_.end() && !find_it->second.expired()) {
169  return find_it->second.lock();
170  }
171 
172  return nullptr;
173 }
174 
175 } // end namespace game_events
void push_back(const handler_ptr &p)
Definition: handlers.hpp:166
std::vector< char_t > string
static std::string standardize_name(const std::string &name)
Utility to standardize the event names used in by_name_.
#define h
id_map_t id_map_
Allows quick locating of handlers by id.
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
This is a wrapper for a list of weak pointers to handlers.
Definition: handlers.hpp:93
void remove_event_handler(const std::string &id)
Removes an event handler, identified by its ID.
void add_event_handler(const config &cfg, manager &man, bool is_menu_item=false)
Adds an event handler.
handler_list dynamic_
Active event handlers with variables in their event names.
static lg::log_domain log_engine("engine")
logger & debug()
Definition: log.cpp:97
Domain specific events.
Definition: action_wml.cpp:88
const handler_list & get(const std::string &name) const
Read-only access to the handlers with fixed event names, by event name.
map_t by_name_
Active event handlers with fixed event names, organized by event name.
Define the game's event mechanism.
std::shared_ptr< event_handler > handler_ptr
Shared pointer to handler objects.
Definition: handlers.hpp:40
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:45
bool might_contain_variables(const std::string &str)
Determines if a string might contain variables to interpolate.
handler_vec active_
Active event handlers.
Define the handlers for the game's events mechanism.
Standard logging facilities (interface).
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:48
static lg::log_domain log_event_handler("event_handler")
const handler_ptr get_event_handler_by_id(const std::string &id)
Gets an event handler, identified by its ID.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
#define DBG_EH