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