parametize modifier key usage; fix keyboard-driven sync point setting; add ladspa...
[ardour.git] / gtk2_ardour / keyeditor.cc
1 #include <map>
2
3 #include <ardour/profile.h>
4
5 #include <gtkmm/stock.h>
6 #include <gtkmm/accelkey.h>
7 #include <gtkmm/accelmap.h>
8 #include <gtkmm/uimanager.h>
9
10 #include <pbd/strsplit.h>
11
12 #include "actions.h"
13 #include "keyboard.h"
14 #include "keyeditor.h"
15
16 #include "i18n.h"
17
18 using namespace std;
19 using namespace Gtk;
20 using namespace Gdk;
21
22 KeyEditor::KeyEditor ()
23         : ArdourDialog (_("Keybinding Editor"), false)
24 {
25         can_bind = false;
26         last_state = 0;
27
28         model = TreeStore::create(columns);
29
30         view.set_model (model);
31         view.append_column (_("Action"), columns.action);
32         view.append_column (_("Binding"), columns.binding);
33         view.set_headers_visible (true);
34         view.get_selection()->set_mode (SELECTION_SINGLE);
35         view.set_reorderable (false);
36         view.set_size_request (300,200);
37         view.set_enable_search (false);
38         view.set_rules_hint (true);
39         view.set_name (X_("KeyEditorTree"));
40         
41         view.get_selection()->signal_changed().connect (mem_fun (*this, &KeyEditor::action_selected));
42         
43         scroller.add (view);
44         scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
45
46         get_vbox()->pack_start (scroller);
47         get_vbox()->set_border_width (12);
48
49         scroller.show ();
50         view.show ();
51 }
52
53 void
54 KeyEditor::on_show ()
55 {
56         populate ();
57         view.get_selection()->unselect_all ();
58         ArdourDialog::on_show ();
59 }
60
61 void
62 KeyEditor::on_unmap ()
63 {
64         ArdourDialog::on_unmap ();
65 }
66
67 void
68 KeyEditor::action_selected ()
69 {
70 }
71
72 bool
73 KeyEditor::on_key_press_event (GdkEventKey* ev)
74 {
75         can_bind = true;
76         last_state = ev->state;
77         return false;
78 }
79
80 bool
81 KeyEditor::on_key_release_event (GdkEventKey* ev)
82 {
83         if (ARDOUR::Profile->get_sae() || !can_bind || ev->state != last_state) {
84                 return false;
85         }
86
87         TreeModel::iterator i = view.get_selection()->get_selected();
88
89         if (i != model->children().end()) {
90                 string path = (*i)[columns.path];
91                 
92                 if (!(*i)[columns.bindable]) {
93                         goto out;
94                 } 
95
96                 bool result = AccelMap::change_entry (path,
97                                                       ev->keyval,
98                                                       (ModifierType) ev->state,
99                                                       true);
100
101                 if (result) {
102                         bool known;
103                         AccelKey key;
104
105                         known = ActionManager::lookup_entry (path, key);
106                         
107                         if (known) {
108                                 (*i)[columns.binding] = ActionManager::ui_manager->get_accel_group()->name (key.get_key(), Gdk::ModifierType (key.get_mod()));
109                         } else {
110                                 (*i)[columns.binding] = string();
111                         }
112                 }
113
114                 
115         }
116
117   out:
118         can_bind = false;
119         return true;
120 }
121
122 void
123 KeyEditor::populate ()
124 {
125         vector<string> paths;
126         vector<string> labels;
127         vector<string> keys;
128         vector<AccelKey> bindings;
129         typedef std::map<string,TreeIter> NodeMap;
130         NodeMap nodes;
131         NodeMap::iterator r;
132         
133         ActionManager::get_all_actions (labels, paths, keys, bindings);
134         
135         vector<string>::iterator k;
136         vector<string>::iterator p;
137         vector<string>::iterator l;
138
139         model->clear ();
140
141         for (l = labels.begin(), k = keys.begin(), p = paths.begin(); l != labels.end(); ++k, ++p, ++l) {
142
143                 TreeModel::Row row;
144                 vector<string> parts;
145                 
146                 parts.clear ();
147
148                 split (*p, parts, '/');
149                 
150                 if (parts.empty()) {
151                         continue;
152                 }
153
154                 if ((r = nodes.find (parts[1])) == nodes.end()) {
155
156                         /* top level is missing */
157
158                         TreeIter rowp;
159                         TreeModel::Row parent;
160                         rowp = model->append();
161                         nodes[parts[1]] = rowp;
162                         parent = *(rowp);
163                         parent[columns.action] = parts[1];
164                         parent[columns.bindable] = false;
165
166                         row = *(model->append (parent.children()));
167
168                 } else {
169                         
170                         row = *(model->append ((*r->second)->children()));
171
172                 }
173                 
174                 /* add this action */
175
176                 row[columns.action] = (*l);
177                 row[columns.path] = (*p);
178                 row[columns.bindable] = true;
179                 
180                 if (*k == ActionManager::unbound_string) {
181                         row[columns.binding] = string();
182                 } else {
183                         row[columns.binding] = (*k);
184                 }
185         }
186 }