Implement a keynav policy for the budget page. Addresses bug #339515.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13847 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Chris Shoemaker 2006-04-25 04:18:45 +00:00
parent 5179270a50
commit a6644b75fc
3 changed files with 155 additions and 23 deletions

View File

@ -35,6 +35,7 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include "gnc-tree-view.h"
@ -2084,4 +2085,98 @@ gnc_tree_view_append_column (GncTreeView *view,
return gtk_tree_view_insert_column (GTK_TREE_VIEW(view), column, n);
}
static gboolean
get_column_next_to(GtkTreeView *tv, GtkTreeViewColumn **col, gboolean backward)
{
GList *cols, *node;
GtkTreeViewColumn *c = NULL;
gint seen = 0;
gboolean wrapped = FALSE;
cols = gtk_tree_view_get_columns(tv);
g_return_val_if_fail(g_list_length(cols) > 0, FALSE);
node = g_list_find(cols, *col);
g_return_val_if_fail(node, FALSE);
do {
node = backward ? node->prev : node->next;
if (!node) {
wrapped = TRUE;
node = backward ? g_list_last(cols) : cols;
}
c = GTK_TREE_VIEW_COLUMN(node->data);
if (c && gtk_tree_view_column_get_visible(c))
seen++;
if (c == *col) break;
} while (!seen);
g_list_free(cols);
*col = c;
return wrapped;
}
gboolean
gnc_tree_view_path_is_valid(GncTreeView *view, GtkTreePath *path)
{
GtkTreeView *tv = GTK_TREE_VIEW(view);
GtkTreeModel *s_model;
GtkTreeIter iter;
s_model = gtk_tree_view_get_model(tv);
return gtk_tree_model_get_iter(s_model, &iter, path);
}
void
gnc_tree_view_keynav(GncTreeView *view, GtkTreeViewColumn **col,
GtkTreePath *path, GdkEventKey *event)
{
GtkTreeView *tv = GTK_TREE_VIEW(view);
gint depth;
gboolean shifted;
if (event->type != GDK_KEY_PRESS) return;
switch (event->keyval) {
case GDK_Tab:
case GDK_ISO_Left_Tab:
case GDK_KP_Tab:
shifted = event->state & GDK_SHIFT_MASK;
if (get_column_next_to(tv, col, shifted)) {
/* This is the end (or beginning) of the line, buddy. */
depth = gtk_tree_path_get_depth(path);
if (shifted) {
if (!gtk_tree_path_prev(path) && depth > 1) {
gtk_tree_path_up(path);
}
} else if (gtk_tree_view_row_expanded(tv, path)) {
gtk_tree_path_down(path);
} else {
gtk_tree_path_next(path);
if (!gnc_tree_view_path_is_valid(view, path) && depth > 1) {
gtk_tree_path_prev(path);
gtk_tree_path_up(path);
gtk_tree_path_next(path);
}
}
}
break;
case GDK_Return:
case GDK_KP_Enter:
if (gtk_tree_view_row_expanded(tv, path)) {
gtk_tree_path_down(path);
} else {
gtk_tree_path_next(path);
if (!gnc_tree_view_path_is_valid(view, path) && depth > 1) {
gtk_tree_path_prev(path);
gtk_tree_path_up(path);
gtk_tree_path_next(path);
}
}
break;
}
return;
}
/** @} */

View File

@ -369,6 +369,19 @@ gnc_tree_view_get_show_column_menu (GncTreeView *view);
GtkCellRenderer *
gnc_tree_view_column_get_renderer(GtkTreeViewColumn *column);
/* Takes a GdkEventKey and the current path and column for the
* treeview. Interprets the event as something that might move the
* cursor. Returns the new column and the possibly changed (if
* navigation wrapped a row) path. */
void
gnc_tree_view_keynav(GncTreeView *view, GtkTreeViewColumn **col,
GtkTreePath *path, GdkEventKey *event);
/* Returns TRUE if path is a vaid path for the treeview */
gboolean
gnc_tree_view_path_is_valid(GncTreeView *view, GtkTreePath *path);
/** @} */
/** @} */

View File

@ -95,12 +95,14 @@ static GncPluginPage *gnc_plugin_page_budget_recreate_page (
GtkWidget *window, GKeyFile *file, const gchar *group);
static gboolean gnc_plugin_page_budget_button_press_cb(
static gboolean gppb_button_press_cb(
GtkWidget *widget, GdkEventButton *event, GncPluginPage *page);
static void gnc_plugin_page_budget_double_click_cb(
static gboolean gppb_key_press_cb(
GtkWidget *treeview, GdkEventKey *event, gpointer userdata);
static void gppb_double_click_cb(
GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col,
GncPluginPageBudget *page);
static void gnc_plugin_page_budget_selection_changed_cb(
static void gppb_selection_changed_cb(
GtkTreeSelection *selection, GncPluginPageBudget *page);
static void gnc_plugin_page_budget_view_refresh (GncPluginPageBudget *page);
@ -394,17 +396,16 @@ gnc_plugin_page_budget_create_widget (GncPluginPage *plugin_page)
selection = gtk_tree_view_get_selection(tree_view);
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
g_signal_connect (G_OBJECT (selection), "changed",
G_CALLBACK (gnc_plugin_page_budget_selection_changed_cb),
plugin_page);
g_signal_connect (G_OBJECT (tree_view), "button-press-event",
G_CALLBACK (gnc_plugin_page_budget_button_press_cb),
plugin_page);
g_signal_connect (G_OBJECT (tree_view), "row-activated",
G_CALLBACK (gnc_plugin_page_budget_double_click_cb),
page);
g_signal_connect(G_OBJECT(selection), "changed",
G_CALLBACK(gppb_selection_changed_cb), plugin_page);
g_signal_connect(G_OBJECT(tree_view), "button-press-event",
G_CALLBACK(gppb_button_press_cb), plugin_page);
g_signal_connect(G_OBJECT(tree_view), "row-activated",
G_CALLBACK(gppb_double_click_cb), page);
g_signal_connect_after(G_OBJECT(tree_view), "key-press-event",
G_CALLBACK(gppb_key_press_cb), NULL);
gnc_plugin_page_budget_selection_changed_cb (NULL, page);
gppb_selection_changed_cb (NULL, page);
gtk_tree_view_set_headers_visible(tree_view, TRUE);
gtk_widget_show (GTK_WIDGET (tree_view));
gtk_container_add (GTK_CONTAINER (scrolled_window),
@ -564,8 +565,7 @@ gnc_plugin_page_budget_recreate_page (GtkWidget *window, GKeyFile *key_file,
* Button presses on all other pages are caught by the signal
* registered in gnc-main-window.c. */
static gboolean
gnc_plugin_page_budget_button_press_cb (GtkWidget *widget,
GdkEventButton *event,
gppb_button_press_cb(GtkWidget *widget, GdkEventButton *event,
GncPluginPage *page)
{
gboolean result;
@ -578,11 +578,36 @@ gnc_plugin_page_budget_button_press_cb (GtkWidget *widget,
return result;
}
static gboolean
gppb_key_press_cb(GtkWidget *treeview, GdkEventKey *event, gpointer userdata)
{
GtkTreeView *tv = GTK_TREE_VIEW(treeview);
GtkTreeViewColumn *col;
GtkTreePath *path = NULL;
if (event->type != GDK_KEY_PRESS) return TRUE;
switch (event->keyval) {
case GDK_Tab:
case GDK_ISO_Left_Tab:
case GDK_KP_Tab:
case GDK_Return:
case GDK_KP_Enter:
gtk_tree_view_get_cursor(tv, &path, &col);
if (!path) return TRUE;
//finish_edit(col);
break;
}
gnc_tree_view_keynav(GNC_TREE_VIEW(tv), &col, path, event);
if (path && gnc_tree_view_path_is_valid(GNC_TREE_VIEW(tv), path))
gtk_tree_view_set_cursor(tv, path, col, TRUE);
return TRUE;
}
static void
gnc_plugin_page_budget_double_click_cb (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *col,
GncPluginPageBudget *page)
gppb_double_click_cb(GtkTreeView *treeview, GtkTreePath *path,
GtkTreeViewColumn *col, GncPluginPageBudget *page)
{
GtkWidget *window;
GncPluginPage *new_page;
@ -600,7 +625,7 @@ gnc_plugin_page_budget_double_click_cb (GtkTreeView *treeview,
}
static void
gnc_plugin_page_budget_selection_changed_cb (GtkTreeSelection *selection,
gppb_selection_changed_cb(GtkTreeSelection *selection,
GncPluginPageBudget *page)
{
GtkActionGroup *action_group;
@ -628,7 +653,6 @@ gnc_plugin_page_budget_selection_changed_cb (GtkTreeSelection *selection,
"sensitive", sensitive);
}
/* Command callbacks */
static void