From d235b8faa65ef78789298fff756904f272c02be1 Mon Sep 17 00:00:00 2001 From: fgerlits Date: Wed, 28 Sep 2005 12:52:03 +0000 Subject: [PATCH] Added keyboard shortcuts for move up, move down and delete. This fixes issue #1430. --- .../gLiveSupport/src/LiveModeWindow.cxx | 56 +++++++++- .../gLiveSupport/src/LiveModeWindow.h | 24 +++- .../gLiveSupport/src/ScratchpadWindow.cxx | 103 +++++++++++++++++- .../gLiveSupport/src/ScratchpadWindow.h | 42 +++++++ 4 files changed, 222 insertions(+), 3 deletions(-) diff --git a/livesupport/products/gLiveSupport/src/LiveModeWindow.cxx b/livesupport/products/gLiveSupport/src/LiveModeWindow.cxx index 475c42bd1..f4f972cb5 100644 --- a/livesupport/products/gLiveSupport/src/LiveModeWindow.cxx +++ b/livesupport/products/gLiveSupport/src/LiveModeWindow.cxx @@ -53,6 +53,20 @@ using namespace LiveSupport::GLiveSupport; /* ================================================ local constants & macros */ +/* + * The modifier keys we check against in onKeyPressed(). + * The following modifiers are omitted, hence ignored: + * GDK_LOCK_MASK (caps lock), + * GDK_MOD2_MASK (don't know what; always on on my computer), + * GDK_MOD3_MASK (don't know what; always off on my computer), + * GDK_BUTTONX_MASK (mouse buttons, X = 1..5). + */ +static const guint MODIFIERS_CHECKED = GDK_SHIFT_MASK + | GDK_CONTROL_MASK + | GDK_MOD1_MASK // Alt + | GDK_MOD4_MASK // Windows key + | GDK_MOD5_MASK; // Alt-gr + /* =============================================== local function prototypes */ @@ -106,6 +120,10 @@ LiveModeWindow :: LiveModeWindow (Ptr::Ref gLiveSupport, &LiveModeWindow::onEntryClicked)); treeView->signal_row_activated().connect(sigc::mem_fun(*this, &LiveModeWindow::onDoubleClick)); + + // register the signal handler for keyboard key presses + treeView->signal_key_press_event().connect(sigc::mem_fun(*this, + &LiveModeWindow::onKeyPressed)); // Add the TreeView, inside a ScrolledWindow, with the button underneath: scrolledWindow.add(*treeView); @@ -284,7 +302,7 @@ LiveModeWindow :: onOutputPlay(void) throw () * Event handler for an entry being clicked in the list. *----------------------------------------------------------------------------*/ void -LiveModeWindow :: onEntryClicked (GdkEventButton * event) throw () +LiveModeWindow :: onEntryClicked(GdkEventButton * event) throw () { if (event->type == GDK_BUTTON_PRESS && event->button == 3) { Glib::RefPtr refSelection = @@ -323,3 +341,39 @@ LiveModeWindow :: onDoubleClick(const Gtk::TreeModel::Path & path, onOutputPlay(); } + +/*------------------------------------------------------------------------------ + * Event handler for a key pressed. + *----------------------------------------------------------------------------*/ +bool +LiveModeWindow :: onKeyPressed(GdkEventKey * event) throw () +{ + if (event->type == GDK_KEY_PRESS) { + Glib::RefPtr refSelection = + treeView->get_selection(); + Gtk::TreeModel::iterator iter = refSelection->get_selected(); + + if (iter) { + if ((event->keyval == GDK_Up + || event->keyval == GDK_KP_Up) + && (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) { + treeView->onUpMenuOption(); + return true; + + } else if ((event->keyval == GDK_Down + || event->keyval == GDK_KP_Down) + && (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) { + treeView->onDownMenuOption(); + return true; + + } else if (event->keyval == GDK_Delete + || event->keyval == GDK_KP_Delete) { + treeView->onRemoveMenuOption(); + return true; + } + } + } + + return false; +} + diff --git a/livesupport/products/gLiveSupport/src/LiveModeWindow.h b/livesupport/products/gLiveSupport/src/LiveModeWindow.h index 4312683c8..d6e2595e6 100644 --- a/livesupport/products/gLiveSupport/src/LiveModeWindow.h +++ b/livesupport/products/gLiveSupport/src/LiveModeWindow.h @@ -164,7 +164,7 @@ class LiveModeWindow : public WhiteWindow, public LocalizedObject * @param event the button event recieved */ void - onEntryClicked(GdkEventButton * event) throw (); + onEntryClicked(GdkEventButton * event) throw (); /** * Signal handler for the user double-clicking, or pressing Enter @@ -177,6 +177,28 @@ class LiveModeWindow : public WhiteWindow, public LocalizedObject const Gtk::TreeViewColumn * column) throw (); + /** + * Signal handler for a key pressed at one of the entries. + * The keys handled are: + *
    + *
  • Alt-Up : move item up
  • + *
  • Alt-Down : move item down
  • + *
  • Delete : remove item
  • + *
+ * + * Technical note: the symbolic key names are found in + * /usr/include/gtk-2.0/gdk/gdkkeysyms.h, + * and the symbolic modifier names are found in + * /usr/include/gtk-2.0/gdk/gdktypes.h. + * + * TODO: make keys customizable from a config file? + * + * @param event the button event recieved + * @return true if the key press was fully handled, false if not + */ + bool + onKeyPressed(GdkEventKey * event) throw (); + /** * Signal handler for the "rows reordered" event. */ diff --git a/livesupport/products/gLiveSupport/src/ScratchpadWindow.cxx b/livesupport/products/gLiveSupport/src/ScratchpadWindow.cxx index 04b6c0095..6a4eb5ec9 100644 --- a/livesupport/products/gLiveSupport/src/ScratchpadWindow.cxx +++ b/livesupport/products/gLiveSupport/src/ScratchpadWindow.cxx @@ -53,6 +53,20 @@ using namespace LiveSupport::GLiveSupport; /* ================================================ local constants & macros */ +/* + * The modifier keys we check against in onKeyPressed(). + * The following modifiers are omitted, hence ignored: + * GDK_LOCK_MASK (caps lock), + * GDK_MOD2_MASK (don't know what; always on on my computer), + * GDK_MOD3_MASK (don't know what; always off on my computer), + * GDK_BUTTONX_MASK (mouse buttons, X = 1..5). + */ +static const guint MODIFIERS_CHECKED = GDK_SHIFT_MASK + | GDK_CONTROL_MASK + | GDK_MOD1_MASK // Alt + | GDK_MOD4_MASK // Windows key + | GDK_MOD5_MASK; // Alt-gr + /* =============================================== local function prototypes */ @@ -122,6 +136,10 @@ ScratchpadWindow :: ScratchpadWindow (Ptr::Ref gLiveSupport, treeView->signal_row_activated().connect(sigc::mem_fun(*this, &ScratchpadWindow::onDoubleClick)); + // register the signal handler for keyboard key presses + treeView->signal_key_press_event().connect(sigc::mem_fun(*this, + &ScratchpadWindow::onKeyPressed)); + // Add the TreeView, inside a ScrolledWindow, with the button underneath: scrolledWindow.add(*treeView); @@ -388,13 +406,37 @@ ScratchpadWindow :: onEntryClicked (GdkEventButton * event) throw () } +/*------------------------------------------------------------------------------ + * Select the row which contains the playable specified. + *----------------------------------------------------------------------------*/ +void +ScratchpadWindow :: selectRow(Ptr::Ref playable) throw () +{ + Gtk::TreeModel::const_iterator iter; + + for (iter = treeModel->children().begin(); + iter != treeModel->children().end(); ++iter) { + + Gtk::TreeRow row = *iter; + Ptr::Ref currentPlayable = row[modelColumns.playableColumn]; + + if (*playable->getId() == *currentPlayable->getId()) { + Glib::RefPtr + selection = treeView->get_selection(); + selection->select(iter); + return; + } + } +} + + /*------------------------------------------------------------------------------ * Event handler for the Up menu item selected from the entry context menu *----------------------------------------------------------------------------*/ void ScratchpadWindow :: onUpItem(void) throw () { - Ptr::Ref playable = currentRow[modelColumns.playableColumn]; + Ptr::Ref playable = currentRow[modelColumns.playableColumn]; Ptr::Ref scratchpadContents; GLiveSupport::PlayableList::iterator it; @@ -421,6 +463,8 @@ ScratchpadWindow :: onUpItem(void) throw () it++; } + + selectRow(playable); } @@ -460,6 +504,8 @@ ScratchpadWindow :: onDownItem(void) throw () it++; } + + selectRow(playable); } @@ -590,3 +636,58 @@ ScratchpadWindow :: onDoubleClick(const Gtk::TreeModel::Path & path, } } + +/*------------------------------------------------------------------------------ + * Event handler for a key pressed. + *----------------------------------------------------------------------------*/ +bool +ScratchpadWindow :: onKeyPressed(GdkEventKey * event) throw () +{ + if (event->type == GDK_KEY_PRESS) { + if ((event->keyval == GDK_Up + || event->keyval == GDK_KP_Up) + && (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) { + if (isSelectionSingle()) { + onUpItem(); + return true; + } + + } else if ((event->keyval == GDK_Down + || event->keyval == GDK_KP_Down) + && (event->state & MODIFIERS_CHECKED) == GDK_MOD1_MASK) { + if (isSelectionSingle()) { + onDownItem(); + return true; + } + + } else if (event->keyval == GDK_Delete + || event->keyval == GDK_KP_Delete) { + onRemoveItemButtonClicked(); + return true; + } + } + + return false; +} + + +/*------------------------------------------------------------------------------ + * Check whether exactly one row is selected. + *----------------------------------------------------------------------------*/ +bool +ScratchpadWindow :: isSelectionSingle(void) throw () +{ + Glib::RefPtr + selection = treeView->get_selection(); + std::vector + selectedRows = selection->get_selected_rows(); + + if (selectedRows.size() == 1) { + Gtk::TreeIter iter = treeModel->get_iter(selectedRows.at(0)); + currentRow = *iter; + return true; + } else { + return false; + } +} + diff --git a/livesupport/products/gLiveSupport/src/ScratchpadWindow.h b/livesupport/products/gLiveSupport/src/ScratchpadWindow.h index 18337ff21..fddd2bee2 100644 --- a/livesupport/products/gLiveSupport/src/ScratchpadWindow.h +++ b/livesupport/products/gLiveSupport/src/ScratchpadWindow.h @@ -79,6 +79,26 @@ class ScratchpadWindow : public WhiteWindow, public LocalizedObject { private: + /** + * Check whether exactly one row is selected, and if so, set + * the currentRow variable to point to it. + * + * This is an auxilliary function used by onKeyPressed(). + * + * @return true if a single row is selected, false if not. + */ + bool + isSelectionSingle(void) throw (); + + /** + * Select the (first) row which contains the playable specified. + * If no such row is found, then it does nothing. + * + * @param playable the playable to be selected. + */ + void + selectRow(Ptr::Ref playable) throw (); + protected: @@ -234,6 +254,28 @@ class ScratchpadWindow : public WhiteWindow, const Gtk::TreeViewColumn * column) throw (); + /** + * Signal handler for a key pressed at one of the entries. + * The keys handled are: + *
    + *
  • Alt-Up : move item up
  • + *
  • Alt-Down : move item down
  • + *
  • Delete : remove item
  • + *
+ * + * Technical note: the symbolic key names are found in + * /usr/include/gtk-2.0/gdk/gdkkeysyms.h, + * and the symbolic modifier names are found in + * /usr/include/gtk-2.0/gdk/gdktypes.h. + * + * TODO: make keys customizable from a config file? + * + * @param event the button event recieved + * @return true if the key press was fully handled, false if not + */ + bool + onKeyPressed(GdkEventKey * event) throw (); + /** * Signal handler for the "up" menu item selected from * the entry context menu.