provide (Static)ActionMapOwner::action_map()
[ardour.git] / libs / gtkmm2ext / gtkmm2ext / bindings.h
1 #ifndef __libgtkmm2ext_bindings_h__
2 #define __libgtkmm2ext_bindings_h__
3
4 #include <map>
5 #include <vector>
6 #include <list>
7
8 #include <stdint.h>
9
10 #include <gdk/gdkkeysyms.h>
11 #include <gtkmm/action.h>
12 #include <gtkmm/radioaction.h>
13 #include <gtkmm/toggleaction.h>
14
15 #include "pbd/signals.h"
16
17 #include "gtkmm2ext/visibility.h"
18
19 class XMLNode;
20 class XMLProperty;
21
22 namespace Gtkmm2ext {
23
24 class LIBGTKMM2EXT_API KeyboardKey
25 {
26   public:
27         KeyboardKey () {
28                 _val = GDK_VoidSymbol;
29         }
30
31         KeyboardKey (uint32_t state, uint32_t keycode);
32
33         static KeyboardKey null_key() { return KeyboardKey (0, 0); }
34
35         uint32_t state() const { return _val >> 32; }
36         uint32_t key() const { return _val & 0xffff; }
37
38         bool operator<(const KeyboardKey& other) const {
39                 return _val < other._val;
40         }
41
42         bool operator==(const KeyboardKey& other) const {
43                 return _val == other._val;
44         }
45
46         std::string name() const;
47         std::string native_name() const;
48         std::string native_short_name() const;
49         static bool make_key (const std::string&, KeyboardKey&);
50
51         std::string display_label() const;
52
53   private:
54         uint64_t _val;
55 };
56
57 class LIBGTKMM2EXT_API MouseButton {
58   public:
59         MouseButton () {
60                 _val = ~0ULL;
61         }
62
63         MouseButton (uint32_t state, uint32_t button_number);
64         uint32_t state() const { return _val >> 32; }
65         uint32_t button() const { return _val & 0xffff; }
66
67         bool operator<(const MouseButton& other) const {
68                 return _val < other._val;
69         }
70
71         bool operator==(const MouseButton& other) const {
72                 return _val == other._val;
73         }
74
75         std::string name() const;
76         static bool make_button (const std::string&, MouseButton&);
77
78   private:
79         uint64_t _val;
80 };
81
82 class LIBGTKMM2EXT_API Bindings;
83
84 class LIBGTKMM2EXT_API ActionMap {
85   public:
86         ActionMap (std::string const& name);
87         ~ActionMap();
88
89         std::string name() const { return _name; }
90
91         Glib::RefPtr<Gtk::ActionGroup> create_action_group (const std::string& group_name);
92
93         Glib::RefPtr<Gtk::Action> register_action (Glib::RefPtr<Gtk::ActionGroup> group, const char* name, const char* label);
94         Glib::RefPtr<Gtk::Action> register_action (Glib::RefPtr<Gtk::ActionGroup> group,
95                                                    const char* name, const char* label, sigc::slot<void> sl);
96         Glib::RefPtr<Gtk::Action> register_radio_action (Glib::RefPtr<Gtk::ActionGroup> group,
97                                                          Gtk::RadioAction::Group&,
98                                                          const char* name, const char* label,
99                                                          sigc::slot<void,GtkAction*> sl,
100                                                          int value);
101         Glib::RefPtr<Gtk::Action> register_radio_action (Glib::RefPtr<Gtk::ActionGroup> group,
102                                                          Gtk::RadioAction::Group&,
103                                                          const char* name, const char* label,
104                                                          sigc::slot<void> sl);
105         Glib::RefPtr<Gtk::Action> register_toggle_action (Glib::RefPtr<Gtk::ActionGroup> group,
106                                                           const char* name, const char* label, sigc::slot<void> sl);
107
108         Glib::RefPtr<Gtk::Action> find_action (const std::string& name);
109         Glib::RefPtr<Gtk::Action> find_action (char const * group_name, char const * action_name);
110         Glib::RefPtr<Gtk::ToggleAction> find_toggle_action (const std::string& name);
111         Glib::RefPtr<Gtk::ToggleAction> find_toggle_action (char const * group_name, char const * action_name);
112         Glib::RefPtr<Gtk::RadioAction> find_radio_action (const std::string& name);
113         Glib::RefPtr<Gtk::RadioAction> find_radio_action (char const * group_name, char const * action_name);
114
115         void set_bindings (Bindings*);
116         Bindings* bindings() const { return _bindings; }
117
118         typedef std::vector<Glib::RefPtr<Gtk::Action> > Actions;
119         void get_actions (Actions&);
120
121         static std::list<ActionMap*> action_maps;
122
123         /* used by control surface protocols and other UIs */
124         static void get_all_actions (std::vector<std::string>& paths,
125                                      std::vector<std::string>& labels,
126                                      std::vector<std::string>& tooltips,
127                                      std::vector<std::string>& keys,
128                                      std::vector<Glib::RefPtr<Gtk::Action> >& actions);
129
130   private:
131         std::string _name;
132
133         /* hash for faster lookup of actions by name */
134
135         typedef std::map<std::string, Glib::RefPtr<Gtk::Action> > _ActionMap;
136         _ActionMap _actions;
137
138         /* initialized to null; set after a Bindings object has ::associated()
139          * itself with this action map.
140          */
141
142         Bindings* _bindings;
143
144 };
145
146 class LIBGTKMM2EXT_API ActionMapOwner {
147   protected:
148         Gtkmm2ext::ActionMap myactions;
149   public:
150         ActionMapOwner (std::string const & map_name) : myactions (map_name) {}
151         Glib::RefPtr<Gtk::Action> find_action (const std::string& name) { return myactions.find_action (name); }
152         Glib::RefPtr<Gtk::Action> find_action (char const * group_name, char const * action_name) { return myactions.find_action (group_name, action_name); }
153
154         Gtkmm2ext::ActionMap& action_map() { return myactions; }
155 };
156
157 class LIBGTKMM2EXT_API StaticActionMapOwner {
158   protected:
159         virtual Gtkmm2ext::ActionMap& my_actions() const = 0;
160   public:
161         virtual ~StaticActionMapOwner() {}
162         Glib::RefPtr<Gtk::Action> find_action (const std::string& name) { return my_actions().find_action (name); }
163         Glib::RefPtr<Gtk::Action> find_action (char const * group_name, char const * action_name) { return my_actions().find_action (group_name, action_name); }
164
165         Gtkmm2ext::ActionMap& action_map() { return my_actions(); }
166 };
167
168 class LIBGTKMM2EXT_API Bindings {
169   public:
170         enum Operation {
171                 Press,
172                 Release
173         };
174
175         struct ActionInfo {
176                 ActionInfo (std::string const& name) : action_name (name) {}
177                 ActionInfo (std::string const& name, std::string const& grp) : action_name (name), group_name (grp) {}
178
179                 std::string action_name;
180                 std::string group_name; /* may be empty */
181                 Glib::RefPtr<Gtk::Action> action;
182         };
183         typedef std::map<KeyboardKey,ActionInfo> KeybindingMap;
184
185         Bindings (std::string const& name);
186         ~Bindings ();
187
188         std::string const& name() const { return _name; }
189
190         void associate ();
191         void dissociate ();
192
193         bool empty() const;
194         bool empty_keys () const;
195         bool empty_mouse () const;
196
197         bool add (KeyboardKey, Operation, std::string const&, XMLProperty const*, bool can_save = false);
198         bool replace (KeyboardKey, Operation, std::string const& action_name, bool can_save = true);
199         bool remove (Operation, std::string const& action_name, bool can_save = false);
200
201         bool activate (KeyboardKey, Operation);
202
203         void add (MouseButton, Operation, std::string const&, XMLProperty const*);
204         void remove (MouseButton, Operation);
205         bool activate (MouseButton, Operation);
206
207         bool is_bound (KeyboardKey const&, Operation) const;
208         std::string bound_name (KeyboardKey const&, Operation) const;
209         bool is_registered (Operation op, std::string const& action_name) const;
210
211         KeyboardKey get_binding_for_action (Glib::RefPtr<Gtk::Action>, Operation& op);
212
213         bool load (XMLNode const& node);
214         void load_operation (XMLNode const& node);
215         void save (XMLNode& root);
216         void save_as_html (std::ostream&, bool) const;
217
218         /* GTK has the following position a Gtk::Action:
219          *
220          *  accel_path: <Actions>/GroupName/ActionName
221          *  name: ActionName
222          *
223          * We want proper namespacing and we're not interested in
224          * the silly <Actions> "extra" namespace. So in Ardour:
225          *
226          * accel_path: <Actions>/GroupName/ActionName
227          * name: GroupName/ActionName
228          *
229          * This (static) method returns the "ardour" name for the action.
230          */
231         static std::string ardour_action_name (Glib::RefPtr<Gtk::Action>);
232
233         void set_action_map (ActionMap&);
234
235         /* used for editing bindings */
236         void get_all_actions (std::vector<std::string>& paths,
237                               std::vector<std::string>& labels,
238                               std::vector<std::string>& tooltips,
239                               std::vector<std::string>& keys,
240                               std::vector<Glib::RefPtr<Gtk::Action> >& actions);
241
242         /* all bindings currently in existence, as grouped into Bindings */
243         static void reset_bindings () { bindings.clear (); }
244         static std::list<Bindings*> bindings;
245         static Bindings* get_bindings (std::string const& name, ActionMap&);
246         static void associate_all ();
247         static void save_all_bindings_as_html (std::ostream&);
248
249         static PBD::Signal1<void,Bindings*> BindingsChanged;
250
251   private:
252         std::string  _name;
253         ActionMap*   _action_map;
254         KeybindingMap press_bindings;
255         KeybindingMap release_bindings;
256
257         typedef std::map<MouseButton,ActionInfo> MouseButtonBindingMap;
258         MouseButtonBindingMap button_press_bindings;
259         MouseButtonBindingMap button_release_bindings;
260
261         void push_to_gtk (KeyboardKey, Glib::RefPtr<Gtk::Action>);
262
263         KeybindingMap& get_keymap (Operation op);
264         const KeybindingMap& get_keymap (Operation op) const;
265         MouseButtonBindingMap& get_mousemap (Operation op);
266 };
267
268 } // namespace
269
270 std::ostream& operator<<(std::ostream& out, Gtkmm2ext::KeyboardKey const & k);
271
272 #endif /* __libgtkmm2ext_bindings_h__ */