[gnome-control-center/extensible-shell] shell: split iconview behaviour and category views into separate objects



commit 7f1303e4a2722cc943c2c6a1c1925710882db217
Author: Thomas Wood <thomas wood intel com>
Date:   Mon Apr 12 23:20:50 2010 +0100

    shell: split iconview behaviour and category views into separate objects
    
    CcShellItemView is a GtkIconView derived object that modifies the the
    item activation behaviour to that required by the shell. In particular,
    items can be activated by a single click, and double or triple clicks are
    ignored. It also expects a particular model to be set and emits a signal
    containing relevant data when an item is activated.
    
    CcShellCategoryView is a widget that provides the category groups for the
    main overview of the shell. It consists of a title and a CcSehllItemView.

 shell/Makefile.am              |   15 ++
 shell/cc-shell-category-view.c |  245 +++++++++++++++++++++++++++++++
 shell/cc-shell-category-view.h |   76 ++++++++++
 shell/cc-shell-item-view.c     |  194 +++++++++++++++++++++++++
 shell/cc-shell-item-view.h     |   72 +++++++++
 shell/cc-shell-marshal.list    |    1 +
 shell/control-center.c         |  314 +++++++++++++++------------------------
 shell/control-center.h         |   32 ++++
 shell/shell.ui                 |   12 +-
 9 files changed, 759 insertions(+), 202 deletions(-)
---
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 7dbeeac..2ee976a 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -9,10 +9,25 @@ INCLUDES =					\
 
 bin_PROGRAMS = gnome-control-center
 
+MARSHAL_FILES = cc-shell-marshal.c cc-shell-marshal.h
+BUILT_SOURCES = $(MARSHAL_FILES)
+
+cc-shell-marshal.h: cc-shell-marshal.list
+	@GLIB_GENMARSHAL@ --prefix=cc_shell_marshal $< --header > $@
+
+cc-shell-marshal.c: cc-shell-marshal.list
+	@GLIB_GENMARSHAL@ --prefix=cc_shell_marshal $< --body --header > $@
+
 gnome_control_center_SOURCES =			\
 	control-center.c			\
+	control-center.h			\
 	shell-search-renderer.c			\
 	shell-search-renderer.h			\
+	cc-shell-category-view.c		\
+	cc-shell-category-view.h		\
+	cc-shell-item-view.c			\
+	cc-shell-item-view.h			\
+	$(MARSHAL_FILES)			\
 	$(NULL)
 
 gnome_control_center_LDADD =			\
diff --git a/shell/cc-shell-category-view.c b/shell/cc-shell-category-view.c
new file mode 100644
index 0000000..9bcc3c7
--- /dev/null
+++ b/shell/cc-shell-category-view.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2010 Intel, Inc.
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Thomas Wood <thos gnome org>
+ */
+
+#include "cc-shell-category-view.h"
+#include "cc-shell-item-view.h"
+#include "cc-shell.h"
+#include "control-center.h"
+
+G_DEFINE_TYPE (CcShellCategoryView, cc_shell_category_view, GTK_TYPE_FRAME)
+
+#define SHELL_CATEGORY_VIEW_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_SHELL_CATEGORY_VIEW, CcShellCategoryViewPrivate))
+
+enum
+{
+  PROP_NAME = 1,
+  PROP_MODEL
+};
+
+struct _CcShellCategoryViewPrivate
+{
+  gchar *name;
+  GtkTreeModel *model;
+
+  GtkWidget *header;
+  GtkWidget *iconview;
+};
+
+static void
+cc_shell_category_view_get_property (GObject    *object,
+                                     guint       property_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  CcShellCategoryViewPrivate *priv = CC_SHELL_CATEGORY_VIEW (object)->priv;
+
+  switch (property_id)
+    {
+    case PROP_NAME:
+      g_value_set_string (value, priv->name);
+      break;
+
+    case PROP_MODEL:
+      g_value_set_object (value, priv->model);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_shell_category_view_set_property (GObject      *object,
+                                     guint         property_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  CcShellCategoryViewPrivate *priv = CC_SHELL_CATEGORY_VIEW (object)->priv;
+
+  switch (property_id)
+    {
+    case PROP_NAME:
+      priv->name = g_value_dup_string (value);
+      break;
+
+    case PROP_MODEL:
+      priv->model = g_value_dup_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_shell_category_view_dispose (GObject *object)
+{
+  CcShellCategoryViewPrivate *priv = CC_SHELL_CATEGORY_VIEW (object)->priv;
+
+  if (priv->model)
+    {
+      g_object_unref (priv->model);
+      priv->model = NULL;
+    }
+
+  G_OBJECT_CLASS (cc_shell_category_view_parent_class)->dispose (object);
+}
+
+static void
+cc_shell_category_view_finalize (GObject *object)
+{
+  CcShellCategoryViewPrivate *priv = CC_SHELL_CATEGORY_VIEW (object)->priv;
+
+  if (priv->name)
+    {
+      g_free (priv->name);
+      priv->name = NULL;
+    }
+
+  G_OBJECT_CLASS (cc_shell_category_view_parent_class)->finalize (object);
+}
+
+static void
+cc_shell_category_view_constructed (GObject *object)
+{
+  CcShellCategoryViewPrivate *priv = CC_SHELL_CATEGORY_VIEW (object)->priv;
+  gchar *header_name;
+  GtkWidget *iconview, *vbox, *header, *self;
+
+  self = GTK_WIDGET (object);
+
+  iconview = cc_shell_item_view_new ();
+  gtk_icon_view_set_model (GTK_ICON_VIEW (iconview), priv->model);
+
+  vbox = gtk_vbox_new (FALSE, 0);
+
+  gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (iconview), COL_PIXBUF);
+  gtk_icon_view_set_text_column (GTK_ICON_VIEW (iconview), COL_NAME);
+  gtk_icon_view_set_item_width (GTK_ICON_VIEW (iconview), 120);
+
+  /* create the header if required */
+  if (priv->name)
+    {
+      header_name = g_strdup_printf ("<b>%s</b>", priv->name);
+
+      header = g_object_new (GTK_TYPE_LABEL,
+                             "use-markup", TRUE,
+                             "label", header_name,
+                             "wrap", TRUE,
+                             "xalign", 0.0,
+                             "xpad", 6,
+                             NULL);
+
+      g_free (header_name);
+      gtk_box_pack_start (GTK_BOX (vbox), header, FALSE, TRUE, 3);
+
+      priv->header = header;
+    }
+
+  /* add the iconview to the vbox */
+  gtk_box_pack_start (GTK_BOX (vbox), iconview, FALSE, TRUE, 0);
+
+  /* add the main vbox to the view */
+  gtk_container_add (GTK_CONTAINER (object), vbox);
+  gtk_widget_show_all (vbox);
+
+  priv->iconview = iconview;
+}
+
+static void
+cc_shell_category_view_style_set (GtkWidget *widget,
+                                  GtkStyle  *old_style)
+{
+  CcShellCategoryViewPrivate *priv = CC_SHELL_CATEGORY_VIEW (widget)->priv;
+
+  if (priv->header)
+    {
+      gtk_widget_modify_bg (priv->header, GTK_STATE_NORMAL,
+                            &widget->style->base[GTK_STATE_NORMAL]);
+      gtk_widget_modify_fg (priv->header, GTK_STATE_NORMAL,
+                            &widget->style->text[GTK_STATE_NORMAL]);
+    }
+
+  if (priv->iconview)
+    {
+      gtk_widget_modify_bg (priv->iconview, GTK_STATE_NORMAL,
+                            &widget->style->base[GTK_STATE_NORMAL]);
+      gtk_widget_modify_fg (priv->iconview, GTK_STATE_NORMAL,
+                            &widget->style->text[GTK_STATE_NORMAL]);
+    }
+}
+
+static void
+cc_shell_category_view_class_init (CcShellCategoryViewClass *klass)
+{
+  GParamSpec *pspec;
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (CcShellCategoryViewPrivate));
+
+  object_class->get_property = cc_shell_category_view_get_property;
+  object_class->set_property = cc_shell_category_view_set_property;
+  object_class->dispose = cc_shell_category_view_dispose;
+  object_class->finalize = cc_shell_category_view_finalize;
+  object_class->constructed = cc_shell_category_view_constructed;
+
+  widget_class->style_set = cc_shell_category_view_style_set;
+
+  pspec = g_param_spec_string ("name",
+                               "Name",
+                               "Name of the category",
+                               NULL,
+                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
+                               | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_NAME, pspec);
+
+  pspec = g_param_spec_object ("model",
+                               "Model",
+                               "Model of the category",
+                               GTK_TYPE_TREE_MODEL,
+                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
+                               | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_MODEL, pspec);
+
+}
+
+static void
+cc_shell_category_view_init (CcShellCategoryView *self)
+{
+  self->priv = SHELL_CATEGORY_VIEW_PRIVATE (self);
+
+  gtk_frame_set_shadow_type (GTK_FRAME (self), GTK_SHADOW_NONE);
+}
+
+GtkWidget *
+cc_shell_category_view_new (const gchar  *name,
+                            GtkTreeModel *model)
+{
+  return g_object_new (CC_TYPE_SHELL_CATEGORY_VIEW,
+                       "name", name,
+                       "model", model, NULL);
+}
+
+CcShellItemView*
+cc_shell_category_view_get_item_view (CcShellCategoryView *self)
+{
+  return (CcShellItemView*) self->priv->iconview;
+}
diff --git a/shell/cc-shell-category-view.h b/shell/cc-shell-category-view.h
new file mode 100644
index 0000000..d434501
--- /dev/null
+++ b/shell/cc-shell-category-view.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2010 Intel, Inc.
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Thomas Wood <thos gnome org>
+ */
+
+
+#ifndef _CC_SHELL_CATEGORY_VIEW_H
+#define _CC_SHELL_CATEGORY_VIEW_H
+
+#include <gtk/gtk.h>
+#include "cc-shell-item-view.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SHELL_CATEGORY_VIEW cc_shell_category_view_get_type()
+
+#define CC_SHELL_CATEGORY_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  CC_TYPE_SHELL_CATEGORY_VIEW, CcShellCategoryView))
+
+#define CC_SHELL_CATEGORY_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  CC_TYPE_SHELL_CATEGORY_VIEW, CcShellCategoryViewClass))
+
+#define CC_IS_SHELL_CATEGORY_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  CC_TYPE_SHELL_CATEGORY_VIEW))
+
+#define CC_IS_SHELL_CATEGORY_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  CC_TYPE_SHELL_CATEGORY_VIEW))
+
+#define CC_SHELL_CATEGORY_VIEW_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  CC_TYPE_SHELL_CATEGORY_VIEW, CcShellCategoryViewClass))
+
+typedef struct _CcShellCategoryView CcShellCategoryView;
+typedef struct _CcShellCategoryViewClass CcShellCategoryViewClass;
+typedef struct _CcShellCategoryViewPrivate CcShellCategoryViewPrivate;
+
+struct _CcShellCategoryView
+{
+  GtkFrame parent;
+
+  CcShellCategoryViewPrivate *priv;
+};
+
+struct _CcShellCategoryViewClass
+{
+  GtkFrameClass parent_class;
+};
+
+GType cc_shell_category_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget *cc_shell_category_view_new (const gchar  *name,
+                                       GtkTreeModel *model);
+CcShellItemView* cc_shell_category_view_get_item_view (CcShellCategoryView *self);
+
+G_END_DECLS
+
+#endif /* _CC_SHELL_CATEGORY_VIEW_H */
diff --git a/shell/cc-shell-item-view.c b/shell/cc-shell-item-view.c
new file mode 100644
index 0000000..3f17aec
--- /dev/null
+++ b/shell/cc-shell-item-view.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2010 Intel, Inc.
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Thomas Wood <thos gnome org>
+ */
+
+#include "cc-shell-item-view.h"
+#include "control-center.h"
+#include "cc-shell-marshal.h"
+
+G_DEFINE_TYPE (CcShellItemView, cc_shell_item_view, GTK_TYPE_ICON_VIEW)
+
+#define SHELL_ITEM_VIEW_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_SHELL_ITEM_VIEW, CcShellItemViewPrivate))
+
+struct _CcShellItemViewPrivate
+{
+  gboolean ignore_release;
+};
+
+
+enum
+{
+  DESKTOP_ITEM_ACTIVATED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0,};
+
+static void
+cc_shell_item_view_get_property (GObject    *object,
+                                 guint       property_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_shell_item_view_set_property (GObject      *object,
+                                 guint         property_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+cc_shell_item_view_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (cc_shell_item_view_parent_class)->dispose (object);
+}
+
+static void
+cc_shell_item_view_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (cc_shell_item_view_parent_class)->finalize (object);
+}
+
+static gboolean
+iconview_button_press_event_cb (GtkWidget       *widget,
+                                GdkEventButton  *event,
+                                CcShellItemView *cc_view)
+{
+  /* be sure to ignore double and triple clicks */
+  cc_view->priv->ignore_release = (event->type != GDK_BUTTON_PRESS);
+
+  return FALSE;
+}
+
+static gboolean
+iconview_button_release_event_cb (GtkWidget       *widget,
+                                  GdkEventButton  *event,
+                                  CcShellItemView *cc_view)
+{
+  CcShellItemViewPrivate *priv = cc_view->priv;
+
+  if (event->button == 1 && !priv->ignore_release)
+    {
+      GList *selection;
+
+      selection =
+        gtk_icon_view_get_selected_items (GTK_ICON_VIEW (cc_view));
+
+      if (!selection)
+        return TRUE;
+
+      gtk_icon_view_item_activated (GTK_ICON_VIEW (cc_view),
+                                    (GtkTreePath*) selection->data);
+
+      g_list_free (selection);
+    }
+
+  return TRUE;
+}
+
+static void
+iconview_item_activated_cb (GtkIconView     *icon_view,
+                            GtkTreePath     *path,
+                            CcShellItemView *cc_view)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  gchar *name, *desktop_file, *id;
+
+  model = gtk_icon_view_get_model (icon_view);
+
+  gtk_icon_view_unselect_all (icon_view);
+
+  /* get the iter and ensure it is valid */
+  if (!gtk_tree_model_get_iter (model, &iter, path))
+    return;
+
+  gtk_tree_model_get (model, &iter,
+                      COL_NAME, &name,
+                      COL_DESKTOP_FILE, &desktop_file,
+                      COL_ID, &id,
+                      -1);
+
+  g_signal_emit (cc_view, signals[DESKTOP_ITEM_ACTIVATED], 0,
+                 name, id, desktop_file);
+
+  g_free (desktop_file);
+  g_free (name);
+  g_free (id);
+}
+
+static void
+cc_shell_item_view_class_init (CcShellItemViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (CcShellItemViewPrivate));
+
+  object_class->get_property = cc_shell_item_view_get_property;
+  object_class->set_property = cc_shell_item_view_set_property;
+  object_class->dispose = cc_shell_item_view_dispose;
+  object_class->finalize = cc_shell_item_view_finalize;
+
+  signals[DESKTOP_ITEM_ACTIVATED] = g_signal_new ("desktop-item-activated",
+                                                  CC_TYPE_SHELL_ITEM_VIEW,
+                                                  G_SIGNAL_RUN_FIRST,
+                                                  0,
+                                                  NULL,
+                                                  NULL,
+                                                  cc_shell_marshal_VOID__STRING_STRING_STRING,
+                                                  G_TYPE_NONE,
+                                                  3,
+                                                  G_TYPE_STRING,
+                                                  G_TYPE_STRING,
+                                                  G_TYPE_STRING);
+}
+
+static void
+cc_shell_item_view_init (CcShellItemView *self)
+{
+  self->priv = SHELL_ITEM_VIEW_PRIVATE (self);
+
+  g_signal_connect (self, "item-activated",
+                    G_CALLBACK (iconview_item_activated_cb), self);
+  g_signal_connect (self, "button-press-event",
+                    G_CALLBACK (iconview_button_press_event_cb), self);
+  g_signal_connect (self, "button-release-event",
+                    G_CALLBACK (iconview_button_release_event_cb), self);
+}
+
+GtkWidget *
+cc_shell_item_view_new (void)
+{
+  return g_object_new (CC_TYPE_SHELL_ITEM_VIEW, NULL);
+}
diff --git a/shell/cc-shell-item-view.h b/shell/cc-shell-item-view.h
new file mode 100644
index 0000000..ec27f14
--- /dev/null
+++ b/shell/cc-shell-item-view.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010 Intel, Inc.
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Thomas Wood <thos gnome org>
+ */
+
+#ifndef _CC_SHELL_ITEM_VIEW_H
+#define _CC_SHELL_ITEM_VIEW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_SHELL_ITEM_VIEW cc_shell_item_view_get_type()
+
+#define CC_SHELL_ITEM_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+  CC_TYPE_SHELL_ITEM_VIEW, CcShellItemView))
+
+#define CC_SHELL_ITEM_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+  CC_TYPE_SHELL_ITEM_VIEW, CcShellItemViewClass))
+
+#define CC_IS_SHELL_ITEM_VIEW(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+  CC_TYPE_SHELL_ITEM_VIEW))
+
+#define CC_IS_SHELL_ITEM_VIEW_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+  CC_TYPE_SHELL_ITEM_VIEW))
+
+#define CC_SHELL_ITEM_VIEW_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+  CC_TYPE_SHELL_ITEM_VIEW, CcShellItemViewClass))
+
+typedef struct _CcShellItemView CcShellItemView;
+typedef struct _CcShellItemViewClass CcShellItemViewClass;
+typedef struct _CcShellItemViewPrivate CcShellItemViewPrivate;
+
+struct _CcShellItemView
+{
+  GtkIconView parent;
+
+  CcShellItemViewPrivate *priv;
+};
+
+struct _CcShellItemViewClass
+{
+  GtkIconViewClass parent_class;
+};
+
+GType cc_shell_item_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget *cc_shell_item_view_new (void);
+
+G_END_DECLS
+
+#endif /* _CC_SHELL_ITEM_VIEW_H */
diff --git a/shell/cc-shell-marshal.list b/shell/cc-shell-marshal.list
new file mode 100644
index 0000000..41e4027
--- /dev/null
+++ b/shell/cc-shell-marshal.list
@@ -0,0 +1 @@
+VOID:STRING,STRING,STRING
diff --git a/shell/control-center.c b/shell/control-center.c
index 3affb43..3675b1c 100644
--- a/shell/control-center.c
+++ b/shell/control-center.c
@@ -21,6 +21,8 @@
 
 #include "config.h"
 
+#include "control-center.h"
+
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 #include <gio/gdesktopappinfo.h>
@@ -33,6 +35,7 @@
 #include "cc-panel.h"
 #include "cc-shell.h"
 #include "shell-search-renderer.h"
+#include "cc-shell-category-view.h"
 
 #include <unique/unique.h>
 
@@ -50,12 +53,12 @@ typedef struct
   GtkWidget  *window;
   GtkWidget  *search_entry;
 
-  GSList *icon_views;
-
   gchar  *current_title;
 
   GtkListStore *store;
+
   GtkTreeModel *search_filter;
+  GtkWidget *search_view;
   GtkCellRenderer *search_renderer;
   gchar *filter_string;
 
@@ -65,76 +68,73 @@ typedef struct
 
 } ShellData;
 
-enum
-{
-  COL_NAME,
-  COL_DESKTOP_FILE,
-  COL_ID,
-  COL_PIXBUF,
-  COL_CATEGORY,
-  COL_SEARCH_TARGET,
-
-  N_COLS
-};
-
-static void item_activated_cb (GtkIconView *icon_view, GtkTreePath *path, ShellData *data);
-
 
-static gboolean
-button_release_cb (GtkWidget      *view,
-                   GdkEventButton *event,
-                   ShellData      *data)
+static void
+activate_panel (const gchar *name,
+                const gchar *id,
+                const gchar *desktop_file,
+                ShellData   *data)
 {
-  if (event->button == 1)
+  if (cc_shell_set_panel (CC_SHELL (data->builder), id))
+    {
+      gtk_label_set_text (GTK_LABEL (W (data->builder, "label-title")), name);
+      gtk_widget_show (W (data->builder, "title-alignment"));
+    }
+  else
     {
-      GList *selection;
+      /* start app directly */
+      g_debug ("Panel module not found for %s", id);
 
-      selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (view));
+      GAppInfo *appinfo;
+      GError *err = NULL;
+      GdkAppLaunchContext *ctx;
+      GKeyFile *key_file;
 
-      if (!selection)
-        return FALSE;
+      key_file = g_key_file_new ();
+      g_key_file_load_from_file (key_file, desktop_file, 0, &err);
 
-      data->last_time = event->time;
+      if (err)
+        {
+          g_warning ("Error starting \"%s\": %s", id, err->message);
 
-      item_activated_cb (GTK_ICON_VIEW (view), selection->data, data);
+          g_error_free (err);
+          err = NULL;
+          return;
+        }
 
-      g_list_free (selection);
-      return TRUE;
-    }
-  return FALSE;
-}
+      appinfo = (GAppInfo*) g_desktop_app_info_new_from_keyfile (key_file);
 
-static void
-selection_changed_cb (GtkIconView *view,
-                      ShellData   *data)
-{
-  GSList *iconviews, *l;
-  GList *selection;
+      g_key_file_free (key_file);
 
-  /* don't clear other selections if this icon view does not have one */
-  selection = gtk_icon_view_get_selected_items (view);
-  if (!selection)
-    return;
-  else
-    g_list_free (selection);
 
-  iconviews = data->icon_views;
+      ctx = gdk_app_launch_context_new ();
+      gdk_app_launch_context_set_screen (ctx, gdk_screen_get_default ());
+      gdk_app_launch_context_set_timestamp (ctx, data->last_time);
 
-  for (l = iconviews; l; l = l->next)
-    {
-      GtkIconView *iconview = l->data;
+      g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (ctx), &err);
 
-      if (iconview != view)
+      g_object_unref (appinfo);
+      g_object_unref (ctx);
+
+      if (err)
         {
-          if ((selection = gtk_icon_view_get_selected_items (iconview)))
-            {
-              gtk_icon_view_unselect_all (iconview);
-              g_list_free (selection);
-            }
+          g_warning ("Error starting \"%s\": %s", id, err->message);
+          g_error_free (err);
+          err = NULL;
         }
     }
 }
 
+static void
+item_activated_cb (CcShellCategoryView *view,
+                   gchar               *name,
+                   gchar               *id,
+                   gchar               *desktop_file,
+                   ShellData           *data)
+{
+  activate_panel (name, id, desktop_file, data);
+}
+
 static gboolean
 model_filter_func (GtkTreeModel *model,
                    GtkTreeIter  *iter,
@@ -185,15 +185,65 @@ category_filter_func (GtkTreeModel *model,
 }
 
 static void
+setup_search (ShellData *data)
+{
+  GtkWidget *search_scrolled, *search_view;
+
+  g_return_if_fail (data->store != NULL);
+
+  /* create the search filter */
+  data->search_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (data->store),
+                                                   NULL);
+
+  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (data->search_filter),
+                                          (GtkTreeModelFilterVisibleFunc)
+                                            model_filter_func,
+                                          data, NULL);
+
+  /* set up the search view */
+  data->search_view = search_view = cc_shell_item_view_new ();
+  gtk_icon_view_set_orientation (GTK_ICON_VIEW (search_view),
+                                 GTK_ORIENTATION_HORIZONTAL);
+  gtk_icon_view_set_spacing (GTK_ICON_VIEW (search_view), 6);
+  gtk_icon_view_set_model (GTK_ICON_VIEW (search_view),
+                           GTK_TREE_MODEL (data->search_filter));
+  gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (search_view), COL_PIXBUF);
+
+  search_scrolled = W (data->builder, "search-scrolled-window");
+  gtk_container_add (GTK_CONTAINER (search_scrolled), search_view);
+
+
+  /* add the custom renderer */
+  data->search_renderer = (GtkCellRenderer*) shell_search_renderer_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (search_view),
+                              data->search_renderer, TRUE);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (search_view),
+                                 data->search_renderer,
+                                 "title", COL_NAME);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (search_view),
+                                 data->search_renderer,
+                                 "search-target", COL_SEARCH_TARGET);
+
+  /* connect the activated signal */
+  g_signal_connect (search_view, "desktop-item-activated",
+                    G_CALLBACK (item_activated_cb), data);
+}
+
+static void
 fill_model (ShellData *data)
 {
   GSList *list, *l;
   GMenuTreeDirectory *d;
   GMenuTree *tree;
-  GtkWidget *vbox, *w;
+  GtkWidget *vbox;
 
   vbox = W (data->builder, "main-vbox");
 
+  gtk_widget_modify_bg (vbox->parent, GTK_STATE_NORMAL,
+                        &vbox->style->base[GTK_STATE_NORMAL]);
+  gtk_widget_modify_fg (vbox->parent, GTK_STATE_NORMAL,
+                        &vbox->style->text[GTK_STATE_NORMAL]);
+
   tree = gmenu_tree_lookup (MENUDIR "/gnomecc.menu", 0);
 
   if (!tree)
@@ -210,82 +260,38 @@ fill_model (ShellData *data)
                                     G_TYPE_STRING, GDK_TYPE_PIXBUF,
                                     G_TYPE_STRING, G_TYPE_STRING);
 
-  data->search_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (data->store), NULL);
-
-  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (data->search_filter),
-                                          (GtkTreeModelFilterVisibleFunc)
-                                            model_filter_func,
-                                          data, NULL);
-
-  w = (GtkWidget *) gtk_builder_get_object (data->builder, "search-view");
-  gtk_icon_view_set_model (GTK_ICON_VIEW (w), GTK_TREE_MODEL (data->search_filter));
-  gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (w), COL_PIXBUF);
-
-
-  data->search_renderer = (GtkCellRenderer*) shell_search_renderer_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (w), data->search_renderer, TRUE);
-  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (w), data->search_renderer,
-                                 "title", COL_NAME);
-  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (w), data->search_renderer,
-                                 "search-target", COL_SEARCH_TARGET);
-
-  g_signal_connect (w, "item-activated",
-                    G_CALLBACK (item_activated_cb), data);
-  g_signal_connect (w, "button-release-event",
-                    G_CALLBACK (button_release_cb), data);
-  g_signal_connect (w, "selection-changed",
-                    G_CALLBACK (selection_changed_cb), data);
 
 
   for (l = list; l; l = l->next)
     {
       GMenuTreeItemType type;
       type = gmenu_tree_item_get_type (l->data);
+
       if (type == GMENU_TREE_ITEM_DIRECTORY)
         {
           GtkTreeModel *filter;
-          GtkWidget *header, *iconview;
-          GSList *foo, *f;
+          GtkWidget *categoryview;
+          GSList *contents, *f;
           const gchar *dir_name;
-          gchar *header_name;
 
-          foo = gmenu_tree_directory_get_contents (l->data);
+          contents = gmenu_tree_directory_get_contents (l->data);
           dir_name = gmenu_tree_directory_get_name (l->data);
 
+          /* create new category view for this category */
           filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (data->store), NULL);
           gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
                                                   (GtkTreeModelFilterVisibleFunc) category_filter_func,
                                                   g_strdup (dir_name), g_free);
 
-          iconview = gtk_icon_view_new_with_model (GTK_TREE_MODEL (filter));
-
-          gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (iconview), COL_PIXBUF);
-          gtk_icon_view_set_text_column (GTK_ICON_VIEW (iconview), COL_NAME);
-          gtk_icon_view_set_item_width (GTK_ICON_VIEW (iconview), 120);
-          g_signal_connect (iconview, "item-activated",
+          categoryview = cc_shell_category_view_new (dir_name, filter);
+          gtk_box_pack_start (GTK_BOX (vbox), categoryview, FALSE, TRUE, 6);
+          g_signal_connect (cc_shell_category_view_get_item_view (CC_SHELL_CATEGORY_VIEW (categoryview)),
+                            "desktop-item-activated",
                             G_CALLBACK (item_activated_cb), data);
-          g_signal_connect (iconview, "button-release-event",
-                            G_CALLBACK (button_release_cb), data);
-          g_signal_connect (iconview, "selection-changed",
-                            G_CALLBACK (selection_changed_cb), data);
-
-          data->icon_views = g_slist_prepend (data->icon_views, iconview);
-
-          header_name = g_strdup_printf ("<b>%s</b>", dir_name);
-
-          header = g_object_new (GTK_TYPE_LABEL,
-                                 "use-markup", TRUE,
-                                 "label", header_name,
-                                 "wrap", TRUE,
-                                 "xalign", 0.0,
-                                 "xpad", 6,
-                                 NULL);
-
-          gtk_box_pack_start (GTK_BOX (vbox), header, FALSE, TRUE, 3);
-          gtk_box_pack_start (GTK_BOX (vbox), iconview, FALSE, TRUE, 0);
-
+          gtk_widget_show (categoryview);
 
-          for (f = foo; f; f = f->next)
+          /* add the items from this category to the model */
+          for (f = contents; f; f = f->next)
             {
               if (gmenu_tree_item_get_type (f->data)
                   == GMENU_TREE_ITEM_ENTRY)
@@ -343,85 +349,7 @@ fill_model (ShellData *data)
 
 }
 
-static void
-activate_panel (const gchar *id,
-                const gchar *desktop_file,
-                ShellData   *data)
-{
-  if (!cc_shell_set_panel (CC_SHELL (data->builder), id))
-    {
-      /* start app directly */
-      g_debug ("Panel module not found for %s", id);
-
-      GAppInfo *appinfo;
-      GError *err = NULL;
-      GdkAppLaunchContext *ctx;
-      GKeyFile *key_file;
-
-      key_file = g_key_file_new ();
-      g_key_file_load_from_file (key_file, desktop_file, 0, &err);
-
-      if (err)
-        {
-          g_warning ("Error starting \"%s\": %s", id, err->message);
-
-          g_error_free (err);
-          err = NULL;
-          return;
-        }
-
-      appinfo = (GAppInfo*) g_desktop_app_info_new_from_keyfile (key_file);
-
-      g_key_file_free (key_file);
-
-
-      ctx = gdk_app_launch_context_new ();
-      gdk_app_launch_context_set_screen (ctx, gdk_screen_get_default ());
-      gdk_app_launch_context_set_timestamp (ctx, data->last_time);
-
-      g_app_info_launch (appinfo, NULL, G_APP_LAUNCH_CONTEXT (ctx), &err);
-
-      g_object_unref (appinfo);
-      g_object_unref (ctx);
-
-      if (err)
-        {
-          g_warning ("Error starting \"%s\": %s", id, err->message);
-          g_error_free (err);
-          err = NULL;
-        }
-    }
-
-}
-
-static void
-item_activated_cb (GtkIconView *icon_view,
-                   GtkTreePath *path,
-                   ShellData   *data)
-{
-  GtkTreeModel *model;
-  GtkTreeIter iter;
-  gchar *name, *desktop_file, *id;
-
-  model = gtk_icon_view_get_model (icon_view);
-
-  /* get the iter and ensure it is valid */
-  if (!gtk_tree_model_get_iter (model, &iter, path))
-    return;
-
-  gtk_tree_model_get (model, &iter, COL_NAME, &name,
-                      COL_DESKTOP_FILE, &desktop_file,
-                      COL_ID, &id, -1);
 
-  g_debug ("activated id: '%s'", id);
-
-  cc_shell_set_title (CC_SHELL (data->builder), name);
-
-  activate_panel (id, desktop_file, data);
-
-  g_free (id);
-  g_free (desktop_file);
-}
 
 static void
 shell_show_overview_page (ShellData *data)
@@ -491,9 +419,8 @@ search_entry_key_press_event_cb (GtkEntry    *entry,
 
       data->last_time = event->time;
 
-      item_activated_cb ((GtkIconView *) gtk_builder_get_object (data->builder,
-                                                                 "search-view"),
-                         path, data);
+      gtk_icon_view_item_activated (GTK_ICON_VIEW (data->search_view), path);
+
       gtk_tree_path_free (path);
       return TRUE;
     }
@@ -587,6 +514,7 @@ main (int argc, char **argv)
                     G_CALLBACK (notebook_switch_page_cb), data);
 
   fill_model (data);
+  setup_search (data);
 
 
   g_signal_connect (gtk_builder_get_object (data->builder, "home-button"),
@@ -650,7 +578,7 @@ main (int argc, char **argv)
       g_free (data->current_title);
       data->current_title = name;
 
-      activate_panel (start_id, start_id, data);
+      activate_panel (name, start_id, NULL, data);
     }
 
   gtk_main ();
diff --git a/shell/control-center.h b/shell/control-center.h
new file mode 100644
index 0000000..88c1a27
--- /dev/null
+++ b/shell/control-center.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Intel, Inc.
+ *
+ * The Control Center 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.
+ *
+ * The Control Center 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 the Control Center; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: Thomas Wood <thos gnome org>
+ */
+
+
+enum
+{
+  COL_NAME,
+  COL_DESKTOP_FILE,
+  COL_ID,
+  COL_PIXBUF,
+  COL_CATEGORY,
+  COL_SEARCH_TARGET,
+
+  N_COLS
+};
diff --git a/shell/shell.ui b/shell/shell.ui
index f40dac0..e42a741 100644
--- a/shell/shell.ui
+++ b/shell/shell.ui
@@ -125,20 +125,14 @@
               <placeholder/>
             </child>
             <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow2">
+              <object class="GtkScrolledWindow" id="search-scrolled-window">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="hscrollbar_policy">automatic</property>
                 <property name="vscrollbar_policy">automatic</property>
                 <property name="shadow_type">in</property>
                 <child>
-                  <object class="GtkIconView" id="search-view">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="orientation">horizontal</property>
-                    <property name="model">liststore</property>
-                    <property name="spacing">6</property>
-                  </object>
+                  <placeholder/>
                 </child>
               </object>
               <packing>
@@ -169,8 +163,8 @@
   <object class="GtkSizeGroup" id="sizegroup">
     <property name="mode">vertical</property>
     <widgets>
-      <widget name="entry-alignment"/>
       <widget name="home-button"/>
+      <widget name="entry-alignment"/>
     </widgets>
   </object>
 </interface>



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