[gnome-photos/wip/search: 4/27] Add PhotosSearchbar



commit f6b584c57056138bcc287d751b42440ec62b4077
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Jan 2 16:53:53 2014 +0100

    Add PhotosSearchbar

 configure.ac           |    1 +
 src/Makefile.am        |    2 +
 src/photos-searchbar.c |  344 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/photos-searchbar.h |   95 +++++++++++++
 4 files changed, 442 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index dc7cbd0..a418dff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -110,6 +110,7 @@ PKG_CHECK_MODULES(LIBRSVG, [librsvg-2.0 >= $LIBRSVG_MIN_VERSION])
 PKG_CHECK_MODULES(TRACKER, [tracker-miner-0.18 tracker-sparql-0.18])
 
 LIBGD_INIT([
+  gtk-hacks
   header-bar
   main-icon-view
   main-view
diff --git a/src/Makefile.am b/src/Makefile.am
index 43ed1e9..43f6f2d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -162,6 +162,8 @@ gnome_photos_SOURCES = \
        photos-search-type.h \
        photos-search-type-manager.c \
        photos-search-type-manager.h \
+       photos-searchbar.c \
+       photos-searchbar.h \
        photos-selection-controller.c \
        photos-selection-controller.h \
        photos-selection-toolbar.c \
diff --git a/src/photos-searchbar.c b/src/photos-searchbar.c
new file mode 100644
index 0000000..6997a6e
--- /dev/null
+++ b/src/photos-searchbar.c
@@ -0,0 +1,344 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Documents
+ */
+
+
+#include "config.h"
+
+#include <glib.h>
+#include <libgd/gd.h>
+
+#include "photos-application.h"
+#include "photos-searchbar.h"
+
+
+struct _PhotosSearchbarPrivate
+{
+  GtkApplication *app;
+  GtkWidget *search_container;
+  GtkWidget *search_entry;
+  GtkWidget *toolbar;
+  gboolean in;
+  gboolean preedit_changed;
+  gboolean search_change_blocked;
+  gulong search_state_id;
+};
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (PhotosSearchbar, photos_searchbar, GTK_TYPE_REVEALER);
+
+
+static void
+photos_searchbar_action_state_changed (PhotosSearchbar *self, const gchar *action_name, GVariant *value)
+{
+  if (g_variant_get_boolean (value))
+    photos_searchbar_show (self);
+  else
+    photos_searchbar_hide (self);
+}
+
+
+static void
+photos_searchbar_default_hide (PhotosSearchbar *self)
+{
+  PhotosSearchbarPrivate *priv = self->priv;
+
+  priv->in = FALSE;
+  gtk_revealer_set_reveal_child (GTK_REVEALER (self), FALSE);
+
+  /* Clear all the search properties when hiding the entry */
+  gtk_entry_set_text (GTK_ENTRY (priv->search_entry), "");
+}
+
+
+static void
+photos_searchbar_default_show (PhotosSearchbar *self)
+{
+  PhotosSearchbarPrivate *priv = self->priv;
+  GdkDevice *event_device;
+
+  event_device = gtk_get_current_event_device ();
+  gtk_revealer_set_reveal_child (GTK_REVEALER (self), TRUE);
+  priv->in = TRUE;
+
+  if (event_device != NULL)
+    gd_entry_focus_hack (priv->search_entry, event_device);
+}
+
+
+static void
+photos_searchbar_enable_search (PhotosSearchbar *self, gboolean enable)
+{
+  GVariant *state;
+
+  state = g_variant_new ("b", enable);
+  g_action_group_change_action_state (G_ACTION_GROUP (self->priv->app), "search", state);
+}
+
+
+static gboolean
+photos_is_keynav_event (PhotosSearchbar *self, GdkEventKey *event)
+{
+  return event->keyval == GDK_KEY_Tab
+    || event->keyval == GDK_KEY_KP_Tab
+    || event->keyval == GDK_KEY_Up
+    || event->keyval == GDK_KEY_KP_Up
+    || event->keyval == GDK_KEY_Down
+    || event->keyval == GDK_KEY_KP_Down
+    || event->keyval == GDK_KEY_Left
+    || event->keyval == GDK_KEY_KP_Left
+    || event->keyval == GDK_KEY_Right
+    || event->keyval == GDK_KEY_KP_Right
+    || event->keyval == GDK_KEY_Home
+    || event->keyval == GDK_KEY_KP_Home
+    || event->keyval == GDK_KEY_End
+    || event->keyval == GDK_KEY_KP_End
+    || event->keyval == GDK_KEY_Page_Up
+    || event->keyval == GDK_KEY_KP_Page_Up
+    || event->keyval == GDK_KEY_Page_Down
+    || event->keyval == GDK_KEY_KP_Page_Down
+    || ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0);
+}
+
+
+static gboolean
+photos_is_space_event (PhotosSearchbar *self, GdkEventKey *event)
+{
+  return event->keyval == GDK_KEY_space;
+}
+
+
+static gboolean
+photos_searchbar_key_press_event (PhotosSearchbar *self, GdkEventKey *event)
+{
+  gboolean ret_val = GDK_EVENT_PROPAGATE;
+
+  if (event->keyval == GDK_KEY_Escape)
+    {
+      photos_searchbar_enable_search (self, FALSE);
+      ret_val = GDK_EVENT_STOP;
+    }
+
+  return ret_val;
+}
+
+
+static void
+photos_searchbar_preedit_changed (PhotosSearchbar *self, const gchar *preedit)
+{
+  self->priv->preedit_changed = TRUE;
+}
+
+
+static void
+photos_searchbar_search_changed (PhotosSearchbar *self)
+{
+  PhotosSearchbarPrivate *priv = self->priv;
+
+  if (priv->search_change_blocked)
+    return;
+
+  PHOTOS_SEARCHBAR_GET_CLASS (self)->entry_changed (self);
+}
+
+
+static void
+photos_searchbar_constructed (GObject *object)
+{
+  PhotosSearchbar *self = PHOTOS_SEARCHBAR (object);
+  PhotosSearchbarPrivate *priv = self->priv;
+  GtkToolItem *item;
+  GVariant *state;
+
+  G_OBJECT_CLASS (photos_searchbar_parent_class)->constructed (object);
+
+  PHOTOS_SEARCHBAR_GET_CLASS (self)->create_search_widgets (self);
+
+  item = gtk_tool_item_new ();
+  gtk_tool_item_set_expand (item, TRUE);
+  gtk_container_add (GTK_CONTAINER (item), priv->search_container);
+  gtk_toolbar_insert (GTK_TOOLBAR (priv->toolbar), item, 0);
+
+  g_signal_connect_swapped (priv->search_entry,
+                            "key-press-event",
+                            G_CALLBACK (photos_searchbar_key_press_event),
+                            self);
+  g_signal_connect_swapped (priv->search_entry,
+                            "search-changed",
+                            G_CALLBACK (photos_searchbar_search_changed),
+                            self);
+
+
+  /* g_signal_connect_object will not be able to disconnect the
+   * handler in time because we change the state of the action during
+   * dispose.
+   */
+  priv->search_state_id = g_signal_connect_swapped (priv->app,
+                                                    "action-state-changed::search",
+                                                    G_CALLBACK (photos_searchbar_action_state_changed),
+                                                    self);
+  state = g_action_group_get_action_state (G_ACTION_GROUP (priv->app), "search");
+  photos_searchbar_action_state_changed (self, "search", state);
+  g_variant_unref (state);
+
+  gtk_widget_show_all (GTK_WIDGET (self));
+}
+
+
+static void
+photos_searchbar_dispose (GObject *object)
+{
+  PhotosSearchbar *self = PHOTOS_SEARCHBAR (object);
+  PhotosSearchbarPrivate *priv = self->priv;
+
+  if (priv->search_state_id != 0)
+    {
+      g_signal_handler_disconnect (priv->app, priv->search_state_id);
+      priv->search_state_id = 0;
+    }
+
+  if (priv->app != NULL)
+    photos_searchbar_enable_search (self, FALSE);
+
+  g_clear_object (&priv->app);
+
+  G_OBJECT_CLASS (photos_searchbar_parent_class)->dispose (object);
+}
+
+
+static void
+photos_searchbar_init (PhotosSearchbar *self)
+{
+  PhotosSearchbarPrivate *priv;
+  GtkStyleContext *context;
+
+  self->priv = photos_searchbar_get_instance_private (self);
+  priv = self->priv;
+
+  priv->app = photos_application_new ();
+
+  priv->toolbar = gtk_toolbar_new ();
+  context = gtk_widget_get_style_context (priv->toolbar);
+  gtk_style_context_add_class (context, "primary-toolbar");
+  gtk_container_add (GTK_CONTAINER (self), priv->toolbar);
+}
+
+
+static void
+photos_searchbar_class_init (PhotosSearchbarClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->constructed = photos_searchbar_constructed;
+  object_class->dispose = photos_searchbar_dispose;
+  class->hide = photos_searchbar_default_hide;
+  class->show = photos_searchbar_default_show;
+}
+
+
+GtkWidget *
+photos_searchbar_new (void)
+{
+  return g_object_new (PHOTOS_TYPE_SEARCHBAR, NULL);
+}
+
+
+gboolean
+photos_searchbar_handle_event (PhotosSearchbar *self, GdkEventKey *event)
+{
+  PhotosSearchbarPrivate *priv = self->priv;
+  gboolean res;
+  gboolean ret_val = GDK_EVENT_PROPAGATE;
+  const gchar *new_text;
+  const gchar *old_text;
+
+  if (priv->in)
+    goto out;
+
+  if (photos_is_keynav_event (self, event))
+    goto out;
+
+  if (photos_is_space_event (self, event))
+    goto out;
+
+  if (!gtk_widget_get_realized (priv->search_entry))
+    gtk_widget_realize (priv->search_entry);
+
+  priv->preedit_changed = FALSE;
+  g_signal_connect_swapped (priv->search_entry,
+                            "preedit-changed",
+                            G_CALLBACK (photos_searchbar_preedit_changed),
+                            self);
+
+  old_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
+  res = gtk_widget_event (priv->search_entry, (GdkEvent *) event);
+  new_text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
+
+  g_signal_handlers_disconnect_by_func (priv->search_entry, photos_searchbar_preedit_changed, self);
+
+  if ((res && (g_strcmp0 (new_text, old_text) != 0)) || priv->preedit_changed)
+    {
+      ret_val = GDK_EVENT_STOP;
+
+      if (!priv->in)
+        photos_searchbar_enable_search (self, TRUE);
+    }
+
+ out:
+  return ret_val;
+}
+
+
+void
+photos_searchbar_hide (PhotosSearchbar *self)
+{
+  PHOTOS_SEARCHBAR_GET_CLASS (self)->hide (self);
+}
+
+
+void
+photos_searchbar_set_search_change_blocked (PhotosSearchbar *self, gboolean search_change_blocked)
+{
+  self->priv->search_change_blocked = search_change_blocked;
+}
+
+
+void
+photos_searchbar_set_search_container (PhotosSearchbar *self, GtkWidget *search_container)
+{
+  self->priv->search_container = search_container;
+}
+
+
+void
+photos_searchbar_set_search_entry (PhotosSearchbar *self, GtkWidget *search_entry)
+{
+  self->priv->search_entry = search_entry;
+}
+
+
+void
+photos_searchbar_show (PhotosSearchbar *self)
+{
+  PHOTOS_SEARCHBAR_GET_CLASS (self)->show (self);
+}
diff --git a/src/photos-searchbar.h b/src/photos-searchbar.h
new file mode 100644
index 0000000..e6b564d
--- /dev/null
+++ b/src/photos-searchbar.h
@@ -0,0 +1,95 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Documents
+ */
+
+#ifndef PHOTOS_SEARCHBAR_H
+#define PHOTOS_SEARCHBAR_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_SEARCHBAR (photos_searchbar_get_type ())
+
+#define PHOTOS_SEARCHBAR(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   PHOTOS_TYPE_SEARCHBAR, PhotosSearchbar))
+
+#define PHOTOS_SEARCHBAR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   PHOTOS_TYPE_SEARCHBAR, PhotosSearchbarClass))
+
+#define PHOTOS_IS_SEARCHBAR(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   PHOTOS_TYPE_SEARCHBAR))
+
+#define PHOTOS_IS_SEARCHBAR_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   PHOTOS_TYPE_SEARCHBAR))
+
+#define PHOTOS_SEARCHBAR_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   PHOTOS_TYPE_SEARCHBAR, PhotosSearchbarClass))
+
+typedef struct _PhotosSearchbar        PhotosSearchbar;
+typedef struct _PhotosSearchbarClass   PhotosSearchbarClass;
+typedef struct _PhotosSearchbarPrivate PhotosSearchbarPrivate;
+
+struct _PhotosSearchbar
+{
+  GtkRevealer parent_instance;
+  PhotosSearchbarPrivate *priv;
+};
+
+struct _PhotosSearchbarClass
+{
+  GtkRevealerClass parent_class;
+
+  /* virtual methods */
+  void (*create_search_widgets) (PhotosSearchbar *self);
+  void (*entry_changed) (PhotosSearchbar *self);
+  void (*hide) (PhotosSearchbar *self);
+  void (*show) (PhotosSearchbar *self);
+};
+
+GType                photos_searchbar_get_type                      (void) G_GNUC_CONST;
+
+GtkWidget           *photos_searchbar_new                           (void);
+
+gboolean             photos_searchbar_handle_event                  (PhotosSearchbar *self, GdkEventKey 
*event);
+
+void                 photos_searchbar_hide                          (PhotosSearchbar *self);
+
+void                 photos_searchbar_set_search_change_blocked     (PhotosSearchbar *self,
+                                                                     gboolean search_change_blocked);
+
+void                 photos_searchbar_set_search_container          (PhotosSearchbar *self,
+                                                                     GtkWidget *search_container);
+
+void                 photos_searchbar_set_search_entry              (PhotosSearchbar *self, GtkWidget 
*search_entry);
+
+void                 photos_searchbar_show                          (PhotosSearchbar *self);
+
+G_END_DECLS
+
+#endif /* PHOTOS_SEARCHBAR_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]