redesign key editor to work with tabbed notebook, one tab per set of bindings
This commit is contained in:
parent
0f748492b3
commit
e35e26fa9b
|
@ -29,6 +29,7 @@
|
|||
#include <gtkmm/accelmap.h>
|
||||
#include <gtkmm/uimanager.h>
|
||||
|
||||
#include "gtkmm2ext/bindings.h"
|
||||
#include "gtkmm2ext/utils.h"
|
||||
|
||||
#include "pbd/strsplit.h"
|
||||
|
@ -48,6 +49,7 @@ using namespace Gdk;
|
|||
using namespace PBD;
|
||||
|
||||
using Gtkmm2ext::Keyboard;
|
||||
using Gtkmm2ext::Bindings;
|
||||
|
||||
KeyEditor::KeyEditor ()
|
||||
: ArdourWindow (_("Key Bindings"))
|
||||
|
@ -57,28 +59,10 @@ KeyEditor::KeyEditor ()
|
|||
{
|
||||
last_keyval = 0;
|
||||
|
||||
model = TreeStore::create(columns);
|
||||
|
||||
view.set_model (model);
|
||||
view.append_column (_("Action"), columns.action);
|
||||
view.append_column (_("Shortcut"), columns.binding);
|
||||
view.set_headers_visible (true);
|
||||
view.get_selection()->set_mode (SELECTION_SINGLE);
|
||||
view.set_reorderable (false);
|
||||
view.set_size_request (500,300);
|
||||
view.set_enable_search (false);
|
||||
view.set_rules_hint (true);
|
||||
view.set_name (X_("KeyEditorTree"));
|
||||
|
||||
view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &KeyEditor::action_selected));
|
||||
|
||||
scroller.add (view);
|
||||
scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
vpacker.set_spacing (6);
|
||||
vpacker.set_border_width (12);
|
||||
vpacker.pack_start (scroller);
|
||||
|
||||
notebook.signal_switch_page ().connect (sigc::mem_fun (*this, &KeyEditor::page_change));
|
||||
|
||||
vpacker.pack_start (notebook, true, true);
|
||||
|
||||
if (!ARDOUR::Profile->get_sae()) {
|
||||
|
||||
Label* hint = manage (new Label (_("Select an action, then press the key(s) to (re)set its shortcut")));
|
||||
|
@ -106,19 +90,114 @@ KeyEditor::KeyEditor ()
|
|||
|
||||
add (vpacker);
|
||||
|
||||
view.show ();
|
||||
scroller.show ();
|
||||
vpacker.show ();
|
||||
|
||||
unbind_button.set_sensitive (false);
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::add_tab (string const & name, Bindings& bindings)
|
||||
{
|
||||
Tab* t = new Tab (*this, name, &bindings);
|
||||
t->populate ();
|
||||
t->show_all ();
|
||||
notebook.append_page (*t, name);
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::unbind ()
|
||||
{
|
||||
current_tab()->unbind ();
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::page_change (GtkNotebookPage*, guint)
|
||||
{
|
||||
current_tab()->view.get_selection()->unselect_all ();
|
||||
unbind_button.set_sensitive (false);
|
||||
}
|
||||
|
||||
bool
|
||||
KeyEditor::on_key_press_event (GdkEventKey* ev)
|
||||
{
|
||||
if (!ev->is_modifier) {
|
||||
last_keyval = ev->keyval;
|
||||
}
|
||||
return ArdourWindow::on_key_press_event (ev);
|
||||
}
|
||||
|
||||
bool
|
||||
KeyEditor::on_key_release_event (GdkEventKey* ev)
|
||||
{
|
||||
if (ARDOUR::Profile->get_sae() || last_keyval == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_tab()->bind (ev, last_keyval);
|
||||
|
||||
last_keyval = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
KeyEditor::Tab::Tab (KeyEditor& ke, string const & str, Bindings* b)
|
||||
: owner (ke)
|
||||
, name (str)
|
||||
, bindings (b)
|
||||
{
|
||||
model = TreeStore::create(columns);
|
||||
|
||||
view.set_model (model);
|
||||
view.append_column (_("Action"), columns.action);
|
||||
view.append_column (_("Shortcut"), columns.binding);
|
||||
view.set_headers_visible (true);
|
||||
view.get_selection()->set_mode (SELECTION_SINGLE);
|
||||
view.set_reorderable (false);
|
||||
view.set_size_request (500,300);
|
||||
view.set_enable_search (false);
|
||||
view.set_rules_hint (true);
|
||||
view.set_name (X_("KeyEditorTree"));
|
||||
|
||||
view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &Tab::action_selected));
|
||||
|
||||
scroller.add (view);
|
||||
scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
set_spacing (6);
|
||||
set_border_width (12);
|
||||
pack_start (scroller);
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::Tab::action_selected ()
|
||||
{
|
||||
if (view.get_selection()->count_selected_rows() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreeModel::iterator i = view.get_selection()->get_selected();
|
||||
|
||||
unbind_button.set_sensitive (false);
|
||||
owner.unbind_button.set_sensitive (false);
|
||||
|
||||
if (i != model->children().end()) {
|
||||
|
||||
string path = (*i)[columns.path];
|
||||
|
||||
if (!(*i)[columns.bindable]) {
|
||||
return;
|
||||
}
|
||||
|
||||
string binding = (*i)[columns.binding];
|
||||
|
||||
if (!binding.empty()) {
|
||||
owner.unbind_button.set_sensitive (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::Tab::unbind ()
|
||||
{
|
||||
TreeModel::iterator i = view.get_selection()->get_selected();
|
||||
|
||||
owner.unbind_button.set_sensitive (false);
|
||||
|
||||
if (i != model->children().end()) {
|
||||
string path = (*i)[columns.path];
|
||||
|
@ -138,106 +217,48 @@ KeyEditor::unbind ()
|
|||
}
|
||||
|
||||
void
|
||||
KeyEditor::on_show ()
|
||||
KeyEditor::Tab::bind (GdkEventKey* release_event, guint pressed_key)
|
||||
{
|
||||
populate ();
|
||||
view.get_selection()->unselect_all ();
|
||||
ArdourWindow::on_show ();
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::on_unmap ()
|
||||
{
|
||||
ArdourWindow::on_unmap ();
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::action_selected ()
|
||||
{
|
||||
if (view.get_selection()->count_selected_rows() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreeModel::iterator i = view.get_selection()->get_selected();
|
||||
|
||||
unbind_button.set_sensitive (false);
|
||||
|
||||
if (i != model->children().end()) {
|
||||
|
||||
string path = (*i)[columns.path];
|
||||
|
||||
if (!(*i)[columns.bindable]) {
|
||||
return;
|
||||
}
|
||||
|
||||
string binding = (*i)[columns.binding];
|
||||
GdkModifierType mod = (GdkModifierType)(Keyboard::RelevantModifierKeyMask & release_event->state);
|
||||
|
||||
if (!binding.empty()) {
|
||||
unbind_button.set_sensitive (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
KeyEditor::on_key_press_event (GdkEventKey* ev)
|
||||
{
|
||||
if (!ev->is_modifier) {
|
||||
last_keyval = ev->keyval;
|
||||
}
|
||||
return ArdourWindow::on_key_press_event (ev);
|
||||
}
|
||||
|
||||
bool
|
||||
KeyEditor::on_key_release_event (GdkEventKey* ev)
|
||||
{
|
||||
if (ARDOUR::Profile->get_sae() || last_keyval == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TreeModel::iterator i = view.get_selection()->get_selected();
|
||||
|
||||
if (i != model->children().end()) {
|
||||
string path = (*i)[columns.path];
|
||||
|
||||
if (!(*i)[columns.bindable]) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
GdkModifierType mod = (GdkModifierType)(Keyboard::RelevantModifierKeyMask & ev->state);
|
||||
|
||||
Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (ev->keyval);
|
||||
Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (release_event->keyval);
|
||||
Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator (mod);
|
||||
|
||||
bool result = AccelMap::change_entry (path,
|
||||
last_keyval,
|
||||
pressed_key,
|
||||
Gdk::ModifierType(mod),
|
||||
true);
|
||||
|
||||
if (result) {
|
||||
AccelKey key;
|
||||
(*i)[columns.binding] = ActionManager::get_key_representation (path, key);
|
||||
unbind_button.set_sensitive (true);
|
||||
owner.unbind_button.set_sensitive (true);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
last_keyval = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
KeyEditor::populate ()
|
||||
KeyEditor::Tab::populate ()
|
||||
{
|
||||
vector<string> paths;
|
||||
vector<string> labels;
|
||||
vector<string> tooltips;
|
||||
vector<string> keys;
|
||||
vector<AccelKey> bindings;
|
||||
vector<Gtkmm2ext::KeyboardKey> binds;
|
||||
typedef std::map<string,TreeIter> NodeMap;
|
||||
NodeMap nodes;
|
||||
NodeMap::iterator r;
|
||||
|
||||
ActionManager::get_all_actions (labels, paths, tooltips, keys, bindings);
|
||||
bindings->get_all_actions (labels, paths, tooltips, keys, binds);
|
||||
|
||||
vector<string>::iterator k;
|
||||
vector<string>::iterator p;
|
||||
|
@ -260,16 +281,11 @@ KeyEditor::populate ()
|
|||
}
|
||||
|
||||
//kinda kludgy way to avoid displaying menu items as mappable
|
||||
if ( parts[1] == _("Main_menu") )
|
||||
continue;
|
||||
if ( parts[1] == _("redirectmenu") )
|
||||
continue;
|
||||
if ( parts[1] == _("Editor_menus") )
|
||||
continue;
|
||||
if ( parts[1] == _("RegionList") )
|
||||
continue;
|
||||
if ( parts[1] == _("ProcessorMenu") )
|
||||
if ((parts[1].find ("Menu") == parts[1].length() - 4) ||
|
||||
(parts[1].find ("menu") == parts[1].length() - 4) ||
|
||||
(parts[1] == _("RegionList"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((r = nodes.find (parts[1])) == nodes.end()) {
|
||||
|
||||
|
@ -313,7 +329,15 @@ void
|
|||
KeyEditor::reset ()
|
||||
{
|
||||
Keyboard::the_keyboard().reset_bindings ();
|
||||
populate ();
|
||||
view.get_selection()->unselect_all ();
|
||||
populate ();
|
||||
|
||||
for (Tabs::iterator t = tabs.begin(); t != tabs.end(); ++t) {
|
||||
(*t)->view.get_selection()->unselect_all ();
|
||||
(*t)->populate ();
|
||||
}
|
||||
}
|
||||
|
||||
KeyEditor::Tab*
|
||||
KeyEditor::current_tab ()
|
||||
{
|
||||
return dynamic_cast<Tab*> (notebook.get_nth_page (notebook.get_current_page()));
|
||||
}
|
||||
|
|
|
@ -23,56 +23,85 @@
|
|||
#include <string>
|
||||
|
||||
#include <gtkmm/buttonbox.h>
|
||||
#include <gtkmm/notebook.h>
|
||||
#include <gtkmm/scrolledwindow.h>
|
||||
#include <gtkmm/treeview.h>
|
||||
#include <gtkmm/treestore.h>
|
||||
#include <gtkmm/scrolledwindow.h>
|
||||
|
||||
#include "ardour_window.h"
|
||||
|
||||
namespace Gtkmm2ext {
|
||||
class Bindings;
|
||||
}
|
||||
|
||||
class KeyEditor : public ArdourWindow
|
||||
{
|
||||
public:
|
||||
KeyEditor ();
|
||||
|
||||
void add_tab (std::string const &name, Gtkmm2ext::Bindings&);
|
||||
|
||||
protected:
|
||||
void on_show ();
|
||||
void on_unmap ();
|
||||
bool on_key_press_event (GdkEventKey*);
|
||||
bool on_key_release_event (GdkEventKey*);
|
||||
|
||||
private:
|
||||
struct KeyEditorColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
KeyEditorColumns () {
|
||||
add (action);
|
||||
add (binding);
|
||||
add (path);
|
||||
add (bindable);
|
||||
}
|
||||
Gtk::TreeModelColumn<std::string> action;
|
||||
Gtk::TreeModelColumn<std::string> binding;
|
||||
Gtk::TreeModelColumn<std::string> path;
|
||||
Gtk::TreeModelColumn<bool> bindable;
|
||||
class Tab : public Gtk::VBox
|
||||
{
|
||||
public:
|
||||
Tab (KeyEditor&, std::string const &name, Gtkmm2ext::Bindings*);
|
||||
|
||||
void populate ();
|
||||
void unbind ();
|
||||
void bind (GdkEventKey* release_event, guint pressed_key);
|
||||
void action_selected ();
|
||||
|
||||
struct KeyEditorColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
KeyEditorColumns () {
|
||||
add (action);
|
||||
add (binding);
|
||||
add (path);
|
||||
add (bindable);
|
||||
}
|
||||
Gtk::TreeModelColumn<std::string> action;
|
||||
Gtk::TreeModelColumn<std::string> binding;
|
||||
Gtk::TreeModelColumn<std::string> path;
|
||||
Gtk::TreeModelColumn<bool> bindable;
|
||||
};
|
||||
|
||||
Gtk::VBox vpacker;
|
||||
/* give KeyEditor full access to these. This is just a helper
|
||||
class with no special semantics
|
||||
*/
|
||||
|
||||
KeyEditor& owner;
|
||||
std::string name;
|
||||
Gtkmm2ext::Bindings* bindings;
|
||||
Gtk::ScrolledWindow scroller;
|
||||
Gtk::TreeView view;
|
||||
Glib::RefPtr<Gtk::TreeStore> model;
|
||||
KeyEditorColumns columns;
|
||||
};
|
||||
|
||||
Gtk::VBox vpacker;
|
||||
Gtk::ScrolledWindow scroller;
|
||||
Gtk::TreeView view;
|
||||
Glib::RefPtr<Gtk::TreeStore> model;
|
||||
KeyEditorColumns columns;
|
||||
friend class Tab;
|
||||
|
||||
Gtk::VBox vpacker;
|
||||
Gtk::Notebook notebook;
|
||||
Gtk::Button unbind_button;
|
||||
Gtk::HButtonBox unbind_box;
|
||||
Gtk::HBox reset_box;
|
||||
Gtk::Button reset_button;
|
||||
Gtk::Label reset_label;
|
||||
|
||||
void unbind ();
|
||||
|
||||
guint last_keyval;
|
||||
|
||||
void action_selected ();
|
||||
void populate ();
|
||||
typedef std::vector<Tab*> Tabs;
|
||||
|
||||
Tabs tabs;
|
||||
Tab* current_tab();
|
||||
|
||||
void unbind ();
|
||||
void reset ();
|
||||
void page_change (GtkNotebookPage*, guint);
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_key_editor_h__ */
|
||||
|
|
Loading…
Reference in New Issue
Block a user