The Battle for Wesnoth  1.15.1+dev
hotkey_item.hpp
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 
15 #pragma once
16 
17 #include <SDL2/SDL_events.h>
18 #include <SDL2/SDL.h>
19 #include <memory>
20 #include <vector>
21 #include <string>
22 #include <boost/algorithm/string.hpp>
23 
24 class config;
25 namespace hotkey {
26 
27 /* forward declarations */
28 class hotkey_base;
29 class hotkey_mouse;
31 typedef std::shared_ptr<hotkey_base> hotkey_ptr;
32 typedef std::shared_ptr<hotkey_mouse> hotkey_mouse_ptr;
33 typedef std::shared_ptr<hotkey_keyboard> hotkey_keyboard_ptr;
34 
35 typedef std::vector<hotkey::hotkey_ptr> hotkey_list;
37 
38 /**
39  * This is the base class for hotkey event matching.
40  */
42 {
43 public:
44  /**
45  * Initialises a new empty hotkey that will be disabled
46  */
47  hotkey_base() : command_("null"), is_default_(true), is_disabled_(false), mod_(0)
48  {}
49 
50  void set_command(const std::string& command)
51  {
52  command_ = command;
53  }
54 
55  /**
56  * Set keyboard modifiers.
57  * @param mods Bitmask of SDL_Keymod.
58  */
59  void set_mods(unsigned int mods)
60  {
61  mod_ = mods;
62  }
63 
64  /**
65  * Returns the string name of the HOTKEY_COMMAND
66  * @return The unique string for a hotkey command.
67  **/
68  const std::string& get_command() const
69  {
70  return command_;
71  }
72 
73  /**
74  * Returns the translated description
75  * @todo unused
76  * @return internationalised description of the command.
77  **/
78  const std::string get_description() const;
79 
80  /**
81  * This controls whether the item should appear in the hotkey preferences.
82  * @return true if the item should be hidden
83  **/
84  virtual bool hidden() const
85  {
86  return false;
87  }
88 
89  /**
90  * This indicates whether a hotkey is from the default config or if it's
91  * from the user preferences.
92  * @return true if from the default configurations, false otherwise
93  */
94  bool is_default() const
95  {
96  return is_default_;
97  }
98 
99  /**
100  * Used to indicate that a hotkey is overridden and should be treated as
101  * a user-set hotkey.
102  */
104  {
105  is_default_ = false;
106  }
107 
108  bool is_disabled() const
109  {
110  return is_disabled_;
111  }
112  void disable()
113  {
114  is_disabled_ = true;
115  }
116  void enable()
117  {
118  is_disabled_ = false;
119  }
120 
121  /**
122  * Unbind this hotkey by linking it to the null-command
123  */
124  void clear()
125  {
126  command_ = "null";
127  }
128 
129  /**
130  * Returns whether this hotkey points to the null-command
131  * @return true if it points to the null-command, false otherwise.
132  */
133  bool null() const
134  {
135  return command_ == "null";
136  }
137 
138  /*
139  * Returns whether there is a associated hotkey_command.
140  * If the none of the hotkey_commands fits this hotkey_item then
141  * @param get_hotkey_command will return the hotkey_command::null_command().
142  * @return true if the hotkey is not bound to the null-command.
143  */
144  bool active() const
145  {
146  return command_ != "null";
147  }
148 
149  /**
150  * Evaluates whether the hotkey bindings are valid.
151  * @return true if they are valid, false otherwise.
152  */
153  virtual bool valid() const = 0;
154 
155  /**
156  * Save the hotkey into the configuration object.
157  * @param cfg The configuration object to save into.
158  */
159  void save(config& cfg) const;
160 
161  /**
162  * Return "name" of hotkey. Example :"ctrl+alt+g"
163  * @return The string representation of the keybindings
164  */
165  const std::string get_name() const;
166 
167  /**
168  * Used to evaluate whether:
169  * 1. The hotkey is valid in the current scope.
170  * 2. The Keyboard modifiers and SDL_Event mathes this hotkey.
171  *
172  * @param event The SDL_Event that has triggered and is being evaluated.
173  */
174  bool matches(const SDL_Event& event) const;
175 
176  /**
177  * Checks whether the hotkey bindings and scope are equal.
178  * @param other the hokey bindings to compare against.
179  * @return true if %other has same scope and bindings.
180  */
181  virtual bool bindings_equal(hotkey_ptr other);
182 
183  virtual ~hotkey_base()
184  {}
185 
186 protected:
187  /**
188  * This is invoked by hotkey_base::get_name and must be implemented by subclasses.
189  * Keyboard modifiers are handled in this class, other hotkeys in the respective classes
190  */
191  virtual const std::string get_name_helper() const = 0;
192  /**
193  * This is invoked by hotkey_base::matches as a helper for the concrete classes.
194  * Implementing classes should only check their parts of the hotkey.
195  * @param event The SDL_Event being generated.
196  * @returns true if they match, false otherwise.
197  */
198  virtual bool matches_helper(const SDL_Event &event) const = 0;
199  virtual void save_helper(config& cfg) const = 0;
200  /**
201  * This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
202  * Implementing classes should only check their parts of the hotkey.
203  * @param other The other hotkey the check against. Not guaranteed to be the same subclass.
204  * @returns true if they match, false otherwise.
205  */
206  virtual bool bindings_equal_helper(hotkey_ptr other) const = 0;
207 
208  /**
209  * The command that should be executed, or "null".
210  */
211  std::string command_;
212 
213  /**
214  * is_default_ is true if the hot-key is part of the default hot-key list defined in data/core/hotkeys.cfg.
215  * is_default_ is false if it is not, in which case it would be defined in the user's preferences file.
216  */
218 
219  /*
220  * The original design of using a "null" command to indicate a disabled hot-key is ambiguous with regards
221  * to when to save a user hot-key to preferences as well as when a default hot-key should be flagged as
222  * disabled. So introduce a separate disabled flag to resolve the ambiguity.
223  * Where the flag is true, the hot-key should not be written to preferences unless it is a default hot-key.
224  */
226 
227  /*
228  * Keyboard modifiers. Treat as opaque, only do comparisons.
229  */
230  unsigned int mod_;
231 };
232 
233 /**
234  * This class is responsible for handling keys, not modifiers.
235  */
237 {
238 public:
239  /**
240  * Initialise new instance of this class that has no key associated with is.
241  */
242  hotkey_keyboard() : hotkey_base(), keycode_(SDLK_UNKNOWN), text_("")
243  {}
244 
245  /**
246  * Set the keycode associated with this class.
247  * @param keycode The SDL_Keycode that this hotkey should be associated with
248  */
249  void set_keycode(SDL_Keycode keycode)
250  {
251  keycode_ = keycode;
252  }
253 
254  void set_text(std::string text)
255  {
256  text_ = text;
257  boost::algorithm::to_lower(text_);
258  }
259 
260  /**
261  * Checks whether this hotkey has been set to a sensible value.
262  * @ return true if it is a known key
263  */
264  virtual bool valid() const
265  {
266  return keycode_ != SDLK_UNKNOWN && !text_.empty();
267  }
268 
269 protected:
270  SDL_Keycode keycode_;
271  std::string text_;
272 
273  virtual void save_helper(config& cfg) const;
274  virtual const std::string get_name_helper() const;
275  virtual bool matches_helper(const SDL_Event &event) const;
276  virtual bool bindings_equal_helper (hotkey_ptr other) const;
277 };
278 
279 /**
280  * This class is used to return non-valid results in order to save
281  * other people from null checks.
282  */
284 {
285 public:
287  {}
288  virtual bool valid() const
289  {
290  return false;
291  }
292 protected:
293  virtual void save_helper(config&) const
294  {}
295  virtual const std::string get_name_helper() const
296  {
297  return "";
298  }
299  virtual bool matches_helper(const SDL_Event&) const
300  {
301  return false;
302  }
303  virtual bool bindings_equal_helper(hotkey_ptr) const
304  {
305  return false;
306  }
307 };
308 
309 /**
310  * This class is responsible for handling mouse button presses.
311  */
313 {
314 public:
315  /**
316  * Initialise new instance of this class that has no button associated with is.
317  */
318  hotkey_mouse() : hotkey_base(), button_ (0)
319  {}
320 
321  /**
322  * Returns true if the hotkey has a valid mouse button associated with it.
323  * @return true if a mouse button is set, false otherwise.
324  */
325  virtual bool valid() const
326  {
327  return button_ != 0;
328  }
329 
330  /* new functionality for this class */
331  void set_button(int button)
332  {
333  button_ = button;
334  }
335 protected:
336  int button_;
337 
338  virtual void save_helper(config& cfg) const;
339  virtual const std::string get_name_helper() const;
340  virtual bool matches_helper(const SDL_Event &event) const;
341  virtual bool bindings_equal_helper (hotkey_ptr other) const;
342 };
343 
344 /**
345  * @todo not implemented
346  */
348 {
349 protected:
350  int button_;
351 };
352 
353 /**
354  * Create and instantiate a hotkey from a config element.
355  * @param cfg The config element to read for data.
356  * @return The new instance of the hotkey item.
357  */
358 hotkey_ptr load_from_config(const config& cfg);
359 
360 /*
361  * Scans the list of hotkeys to see if one has been bound to the command.
362  * @param command The command that is searched for
363  * @return true if there is a hotkey item that has the command bound.
364  */
365 bool has_hotkey_item(const std::string& command);
366 
367 /**
368  * Add a hotkey to the list of hotkeys.
369  * @param item The item to add.
370  */
371 void add_hotkey(const hotkey_ptr item);
372 
373 /**
374  * Remove a hotkey from the list of hotkeys
375  * @todo unusued?
376  */
377 void del_hotkey(const hotkey_ptr item);
378 
379 /**
380  * Create a new hotkey item for a command from an SDL_Event.
381  * @param id The command to bind to.
382  * @param event The SDL_Event to base the creation on.
383  */
384 hotkey_ptr create_hotkey(const std::string &id, const SDL_Event &event);
385 
386 /**
387  * Iterate through the list of hotkeys and return a hotkey that matches
388  * the SDL_Event and the current keyboard modifier state.
389  * @param event The SDL_Event to use as a template.
390  * @return The newly created hotkey item.
391  */
392 const hotkey_ptr get_hotkey(const SDL_Event &event);
393 
394 /**
395  * Iterates through all hotkeys present in the config struct and creates and adds
396  * them to the hotkey list.
397  * @param cfg The config struct to load from.
398  * @param set_as_default Indicates whether the config struct should be treated as the
399  * default game settings.
400  */
401 void load_hotkeys(const config& cfg, bool set_as_default = false);
402 
403 /**
404  * Reset all hotkeys to the defaults.
405  */
406 void reset_default_hotkeys();
407 
408 /**
409  * Returns the list of hotkeys.
410  */
411 const hotkey_list& get_hotkeys();
412 
413 /**
414  * Unset the command bindings for all hotkeys matching the command.
415  *
416  * @param command The binding to be unset
417  */
418 void clear_hotkeys(const std::string& command);
419 
420 /**
421  * Unset the bindings for all hotkeys.
422  */
423 void clear_hotkeys();
424 
425 /**
426  * Returns a comma-separated string of hotkey names. A hotkey name is in the form of
427  * "ctrl+l" or "n" or "mouse 1". The comman separated string is of the form "ctrl+l,n,mouse 1".
428  * @return The comma separated string of hotkey names.
429  */
430 std::string get_names(const std::string& id);
431 
432 /**
433  * Save the non-default hotkeys to the config.
434  * @param cfg The config to save to.
435  */
436 void save_hotkeys(config& cfg);
437 
438 bool is_hotkeyable_event(const SDL_Event &event);
439 
440 }
virtual const std::string get_name_helper() const
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
virtual bool matches_helper(const SDL_Event &) const
This is invoked by hotkey_base::matches as a helper for the concrete classes.
hotkey_mouse()
Initialise new instance of this class that has no button associated with is.
bool is_default_
is_default_ is true if the hot-key is part of the default hot-key list defined in data/core/hotkeys...
std::vector< hotkey::hotkey_ptr >::iterator hotkey_list_iter
Definition: hotkey_item.hpp:36
hotkey_ptr load_from_config(const config &cfg)
Create and instantiate a hotkey from a config element.
void save_hotkeys(config &cfg)
Save the non-default hotkeys to the config.
const std::string get_description() const
Returns the translated description.
const std::string get_name() const
Return "name" of hotkey.
Definition: hotkey_item.cpp:73
virtual bool bindings_equal_helper(hotkey_ptr other) const =0
This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
void set_text(std::string text)
void del_hotkey(hotkey_ptr item)
Remove a hotkey from the list of hotkeys.
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
bool has_hotkey_item(const std::string &command)
bool matches(const SDL_Event &event) const
Used to evaluate whether:
bool is_disabled() const
const std::string & get_command() const
Returns the string name of the HOTKEY_COMMAND.
Definition: hotkey_item.hpp:68
virtual bool valid() const
Returns true if the hotkey has a valid mouse button associated with it.
virtual bool matches_helper(const SDL_Event &event) const =0
This is invoked by hotkey_base::matches as a helper for the concrete classes.
Keyboard shortcuts for game actions.
std::shared_ptr< hotkey_mouse > hotkey_mouse_ptr
Definition: hotkey_item.hpp:32
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
void unset_default()
Used to indicate that a hotkey is overridden and should be treated as a user-set hotkey.
hotkey_keyboard()
Initialise new instance of this class that has no key associated with is.
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
bool null() const
Returns whether this hotkey points to the null-command.
virtual void save_helper(config &cfg) const =0
const hotkey_ptr get_hotkey(const SDL_Event &event)
Iterate through the list of hotkeys and return a hotkey that matches the SDL_Event and the current ke...
void set_button(int button)
std::shared_ptr< hotkey_keyboard > hotkey_keyboard_ptr
Definition: hotkey_item.hpp:33
void add_hotkey(const hotkey_ptr item)
Add a hotkey to the list of hotkeys.
This class is used to return non-valid results in order to save other people from null checks...
std::vector< hotkey::hotkey_ptr > hotkey_list
Definition: hotkey_item.hpp:35
void save(config &cfg) const
Save the hotkey into the configuration object.
bool is_default() const
This indicates whether a hotkey is from the default config or if it&#39;s from the user preferences...
Definition: hotkey_item.hpp:94
virtual const std::string get_name_helper() const =0
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
virtual bool hidden() const
This controls whether the item should appear in the hotkey preferences.
Definition: hotkey_item.hpp:84
std::shared_ptr< hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:30
void reset_default_hotkeys()
Reset all hotkeys to the defaults.
virtual bool valid() const =0
Evaluates whether the hotkey bindings are valid.
This class is responsible for handling mouse button presses.
void set_command(const std::string &command)
Definition: hotkey_item.hpp:50
virtual bool bindings_equal_helper(hotkey_ptr) const
This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
void set_mods(unsigned int mods)
Set keyboard modifiers.
Definition: hotkey_item.hpp:59
This is the base class for hotkey event matching.
Definition: hotkey_item.hpp:41
std::string command_
The command that should be executed, or "null".
virtual void save_helper(config &) const
hotkey_base()
Initialises a new empty hotkey that will be disabled.
Definition: hotkey_item.hpp:47
void load_hotkeys(const config &cfg, bool set_as_default)
Iterates through all hotkeys present in the config struct and creates and adds them to the hotkey lis...
hotkey_ptr create_hotkey(const std::string &id, const SDL_Event &event)
Create a new hotkey item for a command from an SDL_Event.
This class is responsible for handling keys, not modifiers.
virtual bool bindings_equal(hotkey_ptr other)
Checks whether the hotkey bindings and scope are equal.
virtual bool valid() const
Evaluates whether the hotkey bindings are valid.
bool is_hotkeyable_event(const SDL_Event &event)
void clear()
Unbind this hotkey by linking it to the null-command.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
void set_keycode(SDL_Keycode keycode)
Set the keycode associated with this class.
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
virtual bool valid() const
Checks whether this hotkey has been set to a sensible value.
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:371
bool active() const