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