The Battle for Wesnoth  1.13.4+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 - 2016 by David White <[email protected]>
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"
18 #include "game_events/manager.hpp"
20 #include "game_events/pump.hpp"
21 
22 #include "formula/string_utils.hpp"
23 #include "game_data.hpp"
24 #include "log.hpp"
25 #include "reports.hpp"
26 #include "resources.hpp"
29 #include "soundsource.hpp"
30 #include "util.hpp"
31 
32 #include <boost/unordered_map.hpp>
33 #include <iostream>
34 
35 
36 static lg::log_domain log_engine("engine");
37 #define DBG_NG LOG_STREAM(debug, log_engine)
38 #define LOG_NG LOG_STREAM(info, log_engine)
39 #define WRN_NG LOG_STREAM(warn, log_engine)
40 
41 static lg::log_domain log_event_handler("event_handler");
42 #define DBG_EH LOG_STREAM(debug, log_event_handler)
43 
44 namespace game_events {
45 
47  {
48  if(lg::debug().dont_log("event_handler")) return;
49 
50  std::stringstream ss;
51 
52  for (const handler_ptr & h : active_) {
53  if ( !h )
54  continue;
55  const config& cfg = h->get_config();
56  ss << "name=" << cfg["name"] << ", with id=" << cfg["id"] << "; ";
57  }
58  DBG_EH << "active handlers are now " << ss.str() << "\n";
59  }
60 
61  /**
62  * Utility to standardize the event names used in by_name_.
63  * This means stripping leading and trailing spaces, and converting internal
64  * spaces to underscores.
65  */
67  {
68  std::string retval;
69  size_t name_index = 0;
70  size_t name_size = name.size();
71 
72  // Trim trailing spaces off the name.
73  while ( name_size > 0 && name[name_size-1] == ' ' )
74  --name_size ;
75 
76  // Trim leading spaces off the name.
77  while ( name_index < name_size && name[name_index] == ' ' )
78  ++name_index;
79 
80  // Copy the rest, converting any remaining spaces to underscores.
81  retval.reserve(name_size - name_index);
82  while ( name_index < name_size ) {
83  char c = name[name_index++];
84  retval.push_back(c == ' ' ? '_' : c);
85  }
86 
87  return retval;
88  }
89 
90  /**
91  * Read-only access to the handlers with fixed event names, by event name.
92  */
94  {
95  // Empty list for the "not found" case.
96  static const handler_list empty_list;
97 
98  // Look for the name in the name map.
99  map_t::const_iterator find_it = by_name_.find(standardize_name(name));
100  return find_it == by_name_.end() ? empty_list : find_it->second;
101  }
102 
103  /**
104  * Adds an event handler.
105  * An event with a nonempty ID will not be added if an event with that
106  * ID already exists.
107  */
108  void t_event_handlers::add_event_handler(const config & cfg, manager & man, bool is_menu_item)
109  {
110  const std::string name = cfg["name"];
111  std::string id = cfg["id"];
112 
113  if(!id.empty()) {
114  // Ignore this handler if there is already one with this ID.
115  id_map_t::iterator find_it = id_map_.find(id);
116  if ( find_it != id_map_.end() && !find_it->second.expired() ) {
117  DBG_EH << "ignoring event handler for name='" << name
118  << "' with id '" << id << "'\n";
119  return;
120  }
121  }
122 
123  // Create a new handler.
124  DBG_EH << "inserting event handler for name=" << name <<
125  " with id=" << id << "\n";
126  handler_ptr new_handler(new event_handler(cfg, is_menu_item, active_.size(), man));
127  active_.push_back(new_handler);
128 
129  // File by name.
130  if ( utils::might_contain_variables(name) )
131  dynamic_.push_back(new_handler);
132  else {
133  std::vector<std::string> name_list = utils::split(name);
134  for (const std::string & single_name : name_list)
135  by_name_[standardize_name(single_name)].push_back(new_handler);
136  }
137  // File by ID.
138  if ( !id.empty() )
139  id_map_[id] = new_handler;
140 
141  log_handlers();
142  }
143 
144  /**
145  * Removes an event handler, identified by its ID.
146  * Events with empty IDs cannot be removed.
147  */
149  {
150  if ( id.empty() )
151  return;
152 
153  DBG_EH << "removing event handler with id " << id << "\n";
154 
155  // Find the existing handler with this ID.
156  id_map_t::iterator find_it = id_map_.find(id);
157  if ( find_it != id_map_.end() ) {
158  handler_ptr handler = find_it->second.lock();
159  // Remove handler.
160  if ( handler )
161  handler->disable();
162  id_map_.erase(find_it); // Do this even if the lock failed.
163  // The index by name will self-adjust later. No need to adjust it now.
164  }
165 
166  log_handlers();
167  }
168 
169 } // end namespace game_events
void push_back(const handler_ptr &p)
Definition: handlers.hpp:137
static thandler * handler
Definition: handler.cpp:60
static std::string standardize_name(const std::string &name)
Utility to standardize the event names used in by_name_.
const handler_list & get() const
Read-only access to the handlers with varying event names.
const GLfloat * c
Definition: glew.h:12741
id_map_t id_map_
Active event handlers with variables in their event names.
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 fixed event names, organized by event name.
map_t by_name_
Active event handlers. Will not have elements removed unless the t_event_handlers is clear()ed...
This is a wrapper for a list of weak pointers to handlers.
Definition: handlers.hpp:88
GLuint id
Definition: glew.h:1647
void remove_event_handler(std::string const &id)
Removes an event handler, identified by its ID.
static lg::log_domain log_engine("engine")
logger & debug()
Definition: log.cpp:97
Templates and utility-routines for strings and numbers.
Domain specific events.
Definition: action_wml.cpp:93
void log_handlers()
Allows quick locating of handlers by id.
Define the game's event mechanism.
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:47
GLuint const GLchar * name
Definition: glew.h:1782
bool might_contain_variables(const std::string &str)
Determines if a string might contain variables to interpolate.
Define the handlers for the game's events mechanism.
Standard logging facilities (interface).
static lg::log_domain log_event_handler("event_handler")
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei const GLcharARB ** string
Definition: glew.h:4503
#define DBG_EH