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