Listener object is better than 3 lambdas + handle
[lsnes.git] / include / library / keyboard-mapper.hpp
blobf91664516301e44bf4093b52d37a06adbfcd7510
1 #ifndef _library__keyboard_mapper__hpp__included__
2 #define _library__keyboard_mapper__hpp__included__
4 #include <set>
5 #include <list>
6 #include <stdexcept>
7 #include <string>
8 #include "keyboard.hpp"
10 namespace command
12 class group;
15 namespace keyboard
17 class invbind;
18 class ctrlrkey;
20 std::pair<key*, unsigned> keymapper_lookup_subkey(keyboard& kbd, const std::string& name,
21 bool axis) throw(std::bad_alloc, std::runtime_error);
23 /**
24 * Key specifier
26 struct keyspec
28 /**
29 * Create a new key specifier (invalid).
31 keyspec() throw(std::bad_alloc);
32 /**
33 * Create a new key specifier from keyspec.
35 * Parameter keyspec: The key specifier.
37 keyspec(const std::string& keyspec) throw(std::bad_alloc, std::runtime_error);
38 /**
39 * Get the key specifier as a keyspec.
41 operator std::string() throw(std::bad_alloc);
42 /**
43 * Is valid?
45 operator bool() throw();
46 /**
47 * Is not valid?
49 bool operator!() throw();
50 /**
51 * Clear the keyspec.
53 void clear() throw();
54 /**
55 * Compare for equality.
57 bool operator==(const keyspec& keyspec);
58 /**
59 * Compare for not-equality.
61 bool operator!=(const keyspec& keyspec);
62 /**
63 * The modifier.
65 std::string mod;
66 /**
67 * The mask.
69 std::string mask;
70 /**
71 * The key itself.
73 std::string key;
76 class invbind_set;
77 class invbind_info;
79 /**
80 * Set add/drop listener.
82 class set_listener
84 public:
85 /**
86 * Dtor.
88 virtual ~set_listener();
89 /**
90 * New item in set.
92 virtual void create(invbind_set& s, const std::string& name, invbind_info& ibinfo) = 0;
93 /**
94 * Deleted item from set.
96 virtual void destroy(invbind_set& s, const std::string& name) = 0;
97 /**
98 * Destroyed the entiere set.
100 virtual void kill(invbind_set& s) = 0;
105 * Keyboard mapper. Maps keyboard keys into commands.
107 class mapper : public event_listener
109 public:
111 * Create new keyboard mapper.
113 mapper(keyboard& kbd, command::group& domain) throw(std::bad_alloc);
115 * Destroy a keyboard mapper.
117 ~mapper() throw();
119 * Binds a key, erroring out if binding would conflict with existing one.
121 * parameter mod: Modifier set to require to be pressed.
122 * parameter modmask: Modifier set to take into account.
123 * parameter keyname: Key to bind the action to.
124 * parameter command: The command to bind.
125 * throws std::bad_alloc: Not enough memory.
126 * throws std::runtime_error: The binding would conflict with existing one or invalid modifier/key.
128 void bind(std::string mod, std::string modmask, std::string keyname, std::string command)
129 throw(std::bad_alloc, std::runtime_error);
131 * Unbinds a key, erroring out if binding does not exist.
133 * parameter mod: Modifier set to require to be pressed.
134 * parameter modmask: Modifier set to take into account.
135 * parameter keyname: Key to bind the action to.
136 * throws std::bad_alloc: Not enough memory.
137 * throws std::runtime_error: The binding does not exist.
139 void unbind(std::string mod, std::string modmask, std::string keyname) throw(std::bad_alloc,
140 std::runtime_error);
142 * Get keys bound.
144 * Returns: The set of keyspecs that are bound.
146 std::list<keyspec> get_bindings() throw(std::bad_alloc);
148 * Get command for key.
150 std::string get(const keyspec& keyspec) throw(std::bad_alloc);
152 * Bind command for key.
154 * Parameter keyspec: The key specifier to bind to.
155 * Parameter cmd: The command to bind. If "", the key is unbound.
157 void set(const keyspec& keyspec, const std::string& cmd) throw(std::bad_alloc, std::runtime_error);
159 * Get set of inverse binds.
161 * Returns: The set of all inverses.
163 std::set<invbind*> get_inverses() throw(std::bad_alloc);
165 * Find inverse bind by command.
167 * Parameter command: The command.
168 * Returns: The inverse bind, or NULL if none.
170 invbind* get_inverse(const std::string& command) throw(std::bad_alloc);
172 * Get set of controller keys.
174 * Returns: The set of all controller keys.
176 std::set<ctrlrkey*> get_controller_keys() throw(std::bad_alloc);
178 * Get specific controller key.
180 ctrlrkey* get_controllerkey(const std::string& command) throw(std::bad_alloc);
182 * Get list of controller keys for specific keyboard key.
184 std::list<ctrlrkey*> get_controllerkeys_kbdkey(key* kbdkey) throw(std::bad_alloc);
186 * Register inverse bind.
188 void do_register(const std::string& name, invbind& bind) throw(std::bad_alloc);
190 * Unregister inverse bind.
192 void do_unregister(const std::string& name, invbind* dummy) throw(std::bad_alloc);
194 * Register controller key.
196 void do_register(const std::string& name, ctrlrkey& ckey) throw(std::bad_alloc);
198 * Unregister inverse bind.
200 void do_unregister(const std::string& name, ctrlrkey* dummy) throw(std::bad_alloc);
202 * Get keyboard.
204 keyboard& get_keyboard() throw();
206 * Get command group to run commands in..
208 command::group& get_command_group() throw();
210 * Fixup command based on polarity.
212 * Parameter cmd: The raw command.
213 * Parameter polarity: Polarity (true is rising edge, false is falling edge).
214 * Returns: The fixed command, or "" if nothing should be run.
216 static std::string fixup_command_polarity(std::string cmd, bool polarity) throw(std::bad_alloc);
218 * Add a set of inverse binds.
220 void add_invbind_set(invbind_set& set);
222 * Drop a set of inverse binds.
224 void drop_invbind_set(invbind_set& set);
225 private:
226 struct triplet
228 triplet(modifier_set mod, modifier_set mask, key& kkey, unsigned subkey);
229 triplet(key& kkey, unsigned subkey);
230 triplet(keyboard& k, const keyspec& spec);
231 bool operator<(const struct triplet& a) const;
232 bool operator==(const struct triplet& a) const;
233 bool operator<=(const struct triplet& a) const { return !(a > *this); }
234 bool operator!=(const struct triplet& a) const { return !(a == *this); }
235 bool operator>=(const struct triplet& a) const { return !(a < *this); }
236 bool operator>(const struct triplet& a) const { return (a < *this); }
237 keyspec as_keyspec() const throw(std::bad_alloc);
238 bool index;
239 modifier_set mod;
240 modifier_set mask;
241 key* _key;
242 unsigned subkey;
244 class listener : public set_listener
246 public:
247 listener(mapper& _grp);
248 ~listener();
249 void create(invbind_set& s, const std::string& name, invbind_info& ibinfo);
250 void destroy(invbind_set& s, const std::string& name);
251 void kill(invbind_set& s);
252 private:
253 mapper& grp;
254 } _listener;
255 void change_command(const keyspec& spec, const std::string& old, const std::string& newc);
256 void on_key_event(modifier_set& mods, key& key, event& event);
257 void on_key_event_subkey(modifier_set& mods, key& key, unsigned skey, bool polarity);
258 mapper(const mapper&);
259 mapper& operator=(const mapper&);
260 std::map<std::string, invbind*> ibinds;
261 std::map<std::string, ctrlrkey*> ckeys;
262 std::map<triplet, std::string> bindings;
263 std::set<key*> listening;
264 std::set<invbind_set*> invbind_set_cbs;
265 keyboard& kbd;
266 command::group& domain;
267 bool dtor_running;
270 class invbind_info;
273 * Inverse bind set.
275 class invbind_set
277 public:
279 * Create a set.
281 invbind_set();
283 * Destructor.
285 ~invbind_set();
287 * Register a inverse bind.
289 void do_register(const std::string& name, invbind_info& info);
291 * Unregister a inverse bind.
293 void do_unregister(const std::string& name, invbind_info& info);
295 * Add a callback on new invese bind.
297 void add_callback(set_listener& listener) throw(std::bad_alloc);
299 * Drop a callback on new inverse bind.
301 void drop_callback(set_listener& listener);
305 * Inverse bind info.
307 class invbind_info
309 public:
311 * Create inverse bind.
313 * Parameter set: The set to be in.
314 * Parameter _command: Command this is for.
315 * Parameter _name: Name of inverse key.
317 invbind_info(invbind_set& set, const std::string& _command, const std::string& _name)
318 throw(std::bad_alloc);
320 * Destructor.
322 ~invbind_info() throw();
324 * Make inverse bind out of this.
326 invbind* make(mapper& m);
328 * Notify set dying.
330 void set_died();
331 private:
332 invbind_set* in_set;
333 std::string command;
334 std::string name;
338 * Inverse bind. Can map up to 2 keys to some command (and follows forward binds).
340 class invbind
342 public:
344 * Create inverse bind.
346 * Parameter mapper: The keyboard mapper to follow.
347 * Parameter command: Command this is for.
348 * Parameter name: Name of inverse key.
350 invbind(mapper& kmapper, const std::string& command, const std::string& name, bool dynamic = false)
351 throw(std::bad_alloc);
353 * Destructor.
355 ~invbind() throw();
357 * Get keyspec.
359 * Parameter index: Index of the keyspec to get.
360 * Returns: The keyspec.
362 keyspec get(unsigned index) throw(std::bad_alloc);
364 * Clear key (subsequent keys fill the gap).
366 * Parameter index: Index of key to clear.
368 void clear(unsigned index) throw(std::bad_alloc);
370 * Add key to set.
372 * Parameter keyspec: The new keyspec.
374 void append(const keyspec& keyspec) throw(std::bad_alloc);
376 * Get name for command.
378 * Returns: The name.
380 std::string getname() throw(std::bad_alloc);
382 * Notify mapper dying.
384 void mapper_died();
385 private:
386 friend class mapper;
387 invbind(const invbind&);
388 invbind& operator=(const invbind&);
389 void addkey(const keyspec& keyspec);
390 mapper* _mapper;
391 std::string cmd;
392 std::string oname;
393 std::vector<keyspec> specs;
394 bool is_dynamic;
398 * A controller key.
400 * Can overlap with any other bind.
402 class ctrlrkey : public event_listener
404 public:
406 * Create a new controller key.
408 * Parameter mapper: The keyboard mapper to follow.
409 * Parameter command: Command to run.
410 * Parameter name: Name of controller key.
411 * Parameter axis: If true, create a axis-type key.
413 ctrlrkey(mapper& kmapper, const std::string& command, const std::string& name,
414 bool axis = false) throw(std::bad_alloc);
416 * Destructor.
418 ~ctrlrkey() throw();
420 * Get the trigger key.
422 std::pair<key*, unsigned> get(unsigned index) throw();
424 * Get the trigger key.
426 std::string get_string(unsigned index) throw(std::bad_alloc);
428 * Set the trigger key (appends).
430 void append(key* key, unsigned subkey) throw();
432 * Set the trigger key (appends).
434 void append(const std::string& key) throw(std::bad_alloc, std::runtime_error);
436 * Remove the trigger key.
438 void remove(key* key, unsigned subkey) throw();
440 * Get the command.
442 const std::string& get_command() const throw() { return cmd; }
444 * Get the name.
446 const std::string& get_name() const throw() { return oname; }
448 * Is axis-type?
450 bool is_axis() const throw() { return axis; }
451 private:
452 void on_key_event(modifier_set& mods, key& key, event& event);
453 mapper& _mapper;
454 std::string cmd;
455 std::string oname;
456 std::vector<std::pair<key*, unsigned>> keys;
457 bool axis;
461 #endif