file chooser entry: Capture Escape and emit :hide-entry
authorMatthias Clasen <mclasen@redhat.com>
Sat, 27 Jun 2015 05:40:04 +0000 (01:40 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 4 Jul 2015 04:29:24 +0000 (00:29 -0400)
Make the file chooser entry optionally capture Escape
and emit a signal. Make the file chooser widget hide the
entry on that signal and go back to the path bar.
This gives us a two-level undo:
location entry -> path bar -> dialog close.
When the location entry is permanently displayed in the
header for save mode, we still let the first Escape close
the dialog.

gtk/gtkfilechooserdialog.c
gtk/gtkfilechooserentry.c
gtk/gtkfilechooserentry.h
gtk/gtkfilechooserwidget.c

index 189284213bb16968c0e2776d3dc887264ab32d22..9fb53e9be7843d63b80ee995a9307f42381ceef7 100644 (file)
@@ -558,7 +558,7 @@ setup_save_entry (GtkFileChooserDialog *dialog)
 
       box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
       label = gtk_label_new_with_mnemonic (_("_Name"));
-      entry = _gtk_file_chooser_entry_new (FALSE);
+      entry = _gtk_file_chooser_entry_new (FALSE, FALSE);
       gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
       gtk_container_add (GTK_CONTAINER (box), label);
       gtk_container_add (GTK_CONTAINER (box), entry);
index 032d19d02c7790709f0dae4d255f54e7c96427df..821a5ee33c9fd0d5ae9b742051f7bef544b625a7 100644 (file)
@@ -31,6 +31,7 @@
 #include "gtksizerequest.h"
 #include "gtkwindow.h"
 #include "gtkintl.h"
+#include "gtkmarshalers.h"
 
 typedef struct _GtkFileChooserEntryClass GtkFileChooserEntryClass;
 
@@ -59,6 +60,7 @@ struct _GtkFileChooserEntry
   guint current_folder_loaded : 1;
   guint complete_on_load : 1;
   guint eat_tabs       : 1;
+  guint eat_escape     : 1;
   guint local_only     : 1;
 };
 
@@ -69,6 +71,14 @@ enum
   N_COLUMNS
 };
 
+enum
+{
+  HIDE_ENTRY,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
 static void     gtk_file_chooser_entry_finalize       (GObject          *object);
 static void     gtk_file_chooser_entry_dispose        (GObject          *object);
 static void     gtk_file_chooser_entry_grab_focus     (GtkWidget        *widget);
@@ -157,6 +167,15 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
 
   widget_class->grab_focus = gtk_file_chooser_entry_grab_focus;
   widget_class->focus_out_event = gtk_file_chooser_entry_focus_out_event;
+
+  signals[HIDE_ENTRY] =
+    g_signal_new (I_("hide-entry"),
+                  G_OBJECT_CLASS_TYPE (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  0,
+                  NULL, NULL,
+                  _gtk_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
 }
 
 static void
@@ -397,6 +416,13 @@ gtk_file_chooser_entry_tab_handler (GtkWidget *widget,
   chooser_entry = GTK_FILE_CHOOSER_ENTRY (widget);
   editable = GTK_EDITABLE (widget);
 
+  if (event->keyval == GDK_KEY_Escape &&
+      chooser_entry->eat_escape)
+    {
+      g_signal_emit (widget, signals[HIDE_ENTRY], 0);
+      return TRUE;
+    }
+
   if (!chooser_entry->eat_tabs)
     return FALSE;
 
@@ -709,6 +735,7 @@ delete_text_callback (GtkFileChooserEntry *chooser_entry,
 /**
  * _gtk_file_chooser_entry_new:
  * @eat_tabs: If %FALSE, allow focus navigation with the tab key.
+ * @eat_escape: If %TRUE, capture Escape key presses and emit ::hide-entry
  *
  * Creates a new #GtkFileChooserEntry object. #GtkFileChooserEntry
  * is an internal implementation widget for the GTK+ file chooser
@@ -718,12 +745,14 @@ delete_text_callback (GtkFileChooserEntry *chooser_entry,
  * Returns: the newly created #GtkFileChooserEntry
  **/
 GtkWidget *
-_gtk_file_chooser_entry_new (gboolean       eat_tabs)
+_gtk_file_chooser_entry_new (gboolean eat_tabs,
+                             gboolean eat_escape)
 {
   GtkFileChooserEntry *chooser_entry;
 
   chooser_entry = g_object_new (GTK_TYPE_FILE_CHOOSER_ENTRY, NULL);
   chooser_entry->eat_tabs = (eat_tabs != FALSE);
+  chooser_entry->eat_escape = (eat_escape != FALSE);
 
   return GTK_WIDGET (chooser_entry);
 }
index dd830770978e50685ad772ff371940877176023c..cf7d8504ba9e4cca45b443ac828bcd332e2bb44e 100644 (file)
@@ -31,7 +31,8 @@ G_BEGIN_DECLS
 typedef struct _GtkFileChooserEntry      GtkFileChooserEntry;
 
 GType              _gtk_file_chooser_entry_get_type           (void) G_GNUC_CONST;
-GtkWidget *        _gtk_file_chooser_entry_new                (gboolean             eat_tab);
+GtkWidget *        _gtk_file_chooser_entry_new                (gboolean             eat_tab,
+                                                               gboolean             eat_escape);
 void               _gtk_file_chooser_entry_set_action         (GtkFileChooserEntry *chooser_entry,
                                                               GtkFileChooserAction action);
 GtkFileChooserAction _gtk_file_chooser_entry_get_action       (GtkFileChooserEntry *chooser_entry);
index 1c24421883e8a8d01adfcbac27caced2af25cb5f..810948a65ee9fc05fddc5e8938cd09a11263d84a 100644 (file)
@@ -2039,6 +2039,12 @@ location_entry_changed_cb (GtkEditable          *editable,
     reset_location_timeout (impl);
 }
 
+static void
+location_entry_close_clicked (GtkFileChooserWidget *impl)
+{
+  location_mode_set (impl, LOCATION_MODE_PATH_BAR);
+}
+
 static void
 location_entry_setup (GtkFileChooserWidget *impl)
 {
@@ -2050,6 +2056,8 @@ location_entry_setup (GtkFileChooserWidget *impl)
 
   g_signal_connect (priv->location_entry, "changed",
                     G_CALLBACK (location_entry_changed_cb), impl);
+  g_signal_connect_swapped (priv->location_entry, "hide-entry",
+                            G_CALLBACK (location_entry_close_clicked), impl);
 
   _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->local_only);
   _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
@@ -2073,7 +2081,7 @@ location_entry_create (GtkFileChooserWidget *impl)
 
   if (!priv->location_entry)
     {
-      priv->location_entry = _gtk_file_chooser_entry_new (TRUE);
+      priv->location_entry = _gtk_file_chooser_entry_new (TRUE, TRUE);
       location_entry_setup (impl);
     }
 }