* Added hardware key navigation
authorSergio Villar Senin <svillar@igalia.com>
Wed, 18 Apr 2007 09:49:30 +0000 (09:49 +0000)
committerSergio Villar Senin <svillar@igalia.com>
Wed, 18 Apr 2007 09:49:30 +0000 (09:49 +0000)
pmo-trunk-r1580

src/maemo/modest-main-window.c
src/widgets/modest-folder-view.c
src/widgets/modest-header-view.c

index a0c6141..806f318 100644 (file)
@@ -73,6 +73,10 @@ static void on_account_update                 (TnyAccountStore *account_store,
                                               gchar *account_name,
                                               gpointer user_data);
 
+static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
+                                              GdkEventKey *event,
+                                              gpointer user_data);
+
 /* list my signals */
 enum {
        /* MY_SIGNAL_1, */
@@ -311,6 +315,8 @@ connect_signals (ModestMainWindow *self)
        parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
        
        /* folder view */
+       g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
+                         G_CALLBACK(on_inner_widgets_key_pressed), self);
        g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
                          G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
 
@@ -326,6 +332,8 @@ connect_signals (ModestMainWindow *self)
                          G_CALLBACK(modest_ui_actions_on_header_activated), self);
        g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
                          G_CALLBACK(modest_ui_actions_on_item_not_found), self);
+       g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
+                         G_CALLBACK(on_inner_widgets_key_pressed), self);
 
        /* window */
        g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
@@ -523,6 +531,7 @@ modest_main_window_set_style (ModestMainWindow *self,
 
                /* Reparent header view with scrolled window */
                gtk_widget_reparent (scrolled_win, priv->main_vbox);
+
                break;
        case MODEST_MAIN_WINDOW_STYLE_SPLIT:
                /* Remove header view */
@@ -537,6 +546,9 @@ modest_main_window_set_style (ModestMainWindow *self,
                g_return_if_reached ();
        }
 
+       /* Let header view grab the focus */
+       gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
+
        /* Show changes */
        gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
 }
@@ -715,3 +727,36 @@ on_account_update (TnyAccountStore *account_store,
        /* Free */
        g_object_unref (account_list);
 }
+
+/* 
+ * This function manages the key events used to navigate between
+ * header and folder views (when the window is in split view)
+ *
+ * FROM         KEY        ACTION
+ * -------------------------------------------------
+ * HeaderView   GDK_Left   Move focus to folder view
+ * FolderView   GDK_Right  Move focus to header view
+ *
+ * There is no need to scroll to selected row, the widgets will be the
+ * responsibles of doing that (probably managing the focus-in event
+ */
+static gboolean 
+on_inner_widgets_key_pressed (GtkWidget *widget,
+                             GdkEventKey *event,
+                             gpointer user_data)
+{
+       ModestMainWindowPrivate *priv;
+
+       priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
+
+       /* Do nothing if we're in SIMPLE style */
+       if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
+               return FALSE;
+
+       if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
+               gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
+       else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
+               gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
+
+       return FALSE;
+}
index 4e55fb6..d13655d 100644 (file)
@@ -106,6 +106,10 @@ static gint         expand_row_timeout     (gpointer data);
 
 static void         setup_drag_and_drop    (GtkTreeView *self);
 
+static gboolean     on_key_pressed         (GtkWidget *self,
+                                           GdkEventKey *event,
+                                           gpointer user_data);
+
 enum {
        FOLDER_SELECTION_CHANGED_SIGNAL,
        LAST_SIGNAL
@@ -338,6 +342,10 @@ modest_folder_view_init (ModestFolderView *obj)
        gtk_tree_view_append_column (GTK_TREE_VIEW(obj),column);
 
        setup_drag_and_drop (GTK_TREE_VIEW(obj));
+
+       g_signal_connect (G_OBJECT (obj), 
+                         "key-press-event", 
+                         G_CALLBACK (on_key_pressed), NULL);
 }
 
 static void
@@ -1136,3 +1144,39 @@ setup_drag_and_drop (GtkTreeView *self)
                          G_CALLBACK (drag_drop_cb),
                          NULL);
 }
+
+/*
+ * This function manages the navigation through the folders using the
+ * keyboard or the hardware keys in the device
+ */
+static gboolean
+on_key_pressed (GtkWidget *self,
+               GdkEventKey *event,
+               gpointer user_data)
+{
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+       GtkTreeModel *model;
+       gboolean retval = FALSE;
+
+       /* Up and Down are automatically managed by the treeview */
+       if (event->keyval == GDK_Return) {
+               /* Expand/Collapse the selected row */
+               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self));
+               if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+                       GtkTreePath *path;
+
+                       path = gtk_tree_model_get_path (model, &iter);
+
+                       if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (self), path))
+                               gtk_tree_view_collapse_row (GTK_TREE_VIEW (self), path);
+                       else
+                               gtk_tree_view_expand_row (GTK_TREE_VIEW (self), path, FALSE);
+                       gtk_tree_path_free (path);
+               }
+               /* No further processing */
+               retval = TRUE;
+       }
+
+       return retval;
+}
index b241bb6..1898172 100644 (file)
@@ -62,6 +62,9 @@ static void          setup_drag_and_drop    (GtkTreeView *self);
 
 static GtkTreePath * get_selected_row       (GtkTreeView *self, GtkTreeModel **model);
 
+static gboolean      on_focus_in            (GtkWidget     *sef,
+                                            GdkEventFocus *event,
+                                            gpointer       user_data);
 
 typedef struct _ModestHeaderViewPrivate ModestHeaderViewPrivate;
 struct _ModestHeaderViewPrivate {
@@ -450,6 +453,9 @@ modest_header_view_new (TnyFolder *folder, ModestHeaderViewStyle style)
        
        g_signal_connect (self, "button-press-event",
                          G_CALLBACK(on_header_clicked), NULL);
+
+       g_signal_connect (self, "focus-in-event",
+                         G_CALLBACK(on_focus_in), NULL);
        
        return GTK_WIDGET(self);
 }
@@ -1119,3 +1125,50 @@ get_selected_row (GtkTreeView *self, GtkTreeModel **model)
 
        return path;
 }
+
+/*
+ * This function moves the tree view scroll to the current selected
+ * row when the widget grabs the focus 
+ */
+static gboolean 
+on_focus_in (GtkWidget     *self,
+            GdkEventFocus *event,
+            gpointer       user_data)
+{
+       GtkTreeSelection *selection;
+       GtkTreeModel *model;
+       GList *selected;
+
+       model = gtk_tree_view_get_model (GTK_TREE_VIEW (self));
+       if (!model)
+               return FALSE;
+
+       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self));
+       /* If none selected yet, pick the first one */
+       if (gtk_tree_selection_count_selected_rows (selection) == 0) {
+               GtkTreeIter iter;
+               GtkTreePath *path;
+
+               gtk_tree_model_get_iter_first (model, &iter);
+               path = gtk_tree_model_get_path (model, &iter);
+               gtk_tree_selection_select_path (selection, path);
+               gtk_tree_path_free (path);
+       }
+
+       /* Need to get the all the rows because is selection multiple */
+       selected = gtk_tree_selection_get_selected_rows (selection, &model);
+
+       /* Scroll to first path */
+       gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (self),
+                                     (GtkTreePath *) selected->data,
+                                     NULL,
+                                     TRUE,
+                                     0.5,
+                                     0.0);
+
+       /* Frees */     
+       g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
+       g_list_free (selected);
+
+       return FALSE;
+}