[epiphany-extensions/tabs-reloaded: 12/16] [tabs-reloaded] Make the close button work



commit d4c9c687b2d3c7a9addeaed809490e0d880f6f56
Author: Benjamin Otte <otte gnome org>
Date:   Fri Aug 7 22:37:32 2009 +0200

    [tabs-reloaded] Make the close button work

 extensions/tabs-reloaded/ephy-cell-renderer-tab.c  |  101 ++++++++++++++++++++
 .../tabs-reloaded/ephy-tabs-reloaded-extension.c   |   72 ++++++++-------
 2 files changed, 139 insertions(+), 34 deletions(-)
---
diff --git a/extensions/tabs-reloaded/ephy-cell-renderer-tab.c b/extensions/tabs-reloaded/ephy-cell-renderer-tab.c
index e869a57..46e1584 100644
--- a/extensions/tabs-reloaded/ephy-cell-renderer-tab.c
+++ b/extensions/tabs-reloaded/ephy-cell-renderer-tab.c
@@ -27,6 +27,13 @@ enum {
   PROP_COLUMNS
 };
 
+enum {
+  ICON_CLICKED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
 
 #define EPHY_CELL_RENDERER_TAB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EPHY_TYPE_CELL_RENDERER_TAB, EphyCellRendererTabPrivate))
 
@@ -61,6 +68,43 @@ ephy_cell_renderer_get_row_height (GtkWidget *widget)
   return height;
 }
 
+static gboolean
+ephy_cell_renderer_tab_activate (GtkCellRenderer      *cell,
+				 GdkEvent             *event,
+				 GtkWidget            *widget,
+				 const gchar          *path,
+				 GdkRectangle         *background_area,
+				 GdkRectangle         *cell_area,
+				 GtkCellRendererState  flags)
+{
+  //EphyCellRendererTab *renderer = EPHY_CELL_RENDERER_TAB (cell);
+  //EphyCellRendererTabPrivate *priv = renderer->priv;
+  int x, y;
+  int icon_width, icon_height;
+
+  /* We only handle mouse events for the small buttons */
+  if (event->type != GDK_BUTTON_PRESS)
+    return FALSE;
+
+  x = event->button.x - cell_area->x - cell->xpad;
+  y = event->button.y - cell_area->y - cell->ypad;
+  gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
+                                     GTK_ICON_SIZE_MENU,
+                                     &icon_width,
+                                     &icon_height);
+  /* clicked below icon */
+  if (y >= icon_height)
+    return FALSE;
+  /* convert to number of icon that was clicked. */
+  x = (cell_area->width - 2 * cell->xpad - x) / icon_width;
+  if (x >= 1)
+    return FALSE;
+
+  g_signal_emit (cell, signals[ICON_CLICKED], 0, path, x);
+
+  return TRUE;
+}
+
 static void
 ephy_cell_renderer_tab_get_size (GtkCellRenderer *cell,
 				 GtkWidget       *widget,
@@ -263,6 +307,42 @@ ephy_cell_renderer_tab_class_finalize (EphyCellRendererTabClass *class)
 }
 
 static void
+ephy_marshal_VOID__STRING_UINT (GClosure     *closure,
+                               GValue       *return_value G_GNUC_UNUSED,
+                               guint         n_param_values,
+                               const GValue *param_values,
+                               gpointer      invocation_hint G_GNUC_UNUSED,
+                               gpointer      marshal_data)
+{
+  typedef void (*GMarshalFunc_VOID__STRING_UINT) (gpointer     data1,
+                                                  const char * arg_2,
+                                                  guint        arg_1,
+                                                  gpointer     data2);
+  register GMarshalFunc_VOID__STRING_UINT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+
+  g_return_if_fail (n_param_values == 3);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_VOID__STRING_UINT) (marshal_data ? marshal_data : cc->callback);
+
+  callback (data1,
+            g_value_get_string (param_values + 1),
+            g_value_get_uint (param_values + 2),
+            data2);
+}
+
+static void
 ephy_cell_renderer_tab_class_init (EphyCellRendererTabClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
@@ -275,6 +355,7 @@ ephy_cell_renderer_tab_class_init (EphyCellRendererTabClass *class)
 
   cell_class->get_size = ephy_cell_renderer_tab_get_size;
   cell_class->render = ephy_cell_renderer_tab_render;
+  cell_class->activate = ephy_cell_renderer_tab_activate;
 
   g_object_class_install_property (object_class,
 				   PROP_TAB,
@@ -294,6 +375,24 @@ ephy_cell_renderer_tab_class_init (EphyCellRendererTabClass *class)
                                                         1,
 							G_PARAM_READWRITE));
 
+  /**
+   * EphyCellRendererTab::icon-clicked:
+   * @cell_renderer: the object which received the signal
+   * @path: string representation of #GtkTreePath describing the 
+   *        event location
+   * @icon: id of the icon that was clicked
+   *
+   * The signal is emitted when one of the icons at the top left of the renderer
+   * is clicked.
+   **/
+  signals[ICON_CLICKED] = g_signal_new ("icon-clicked",
+                                        G_OBJECT_CLASS_TYPE (object_class),
+                                        G_SIGNAL_RUN_LAST,
+                                        0, NULL, NULL,
+                                        ephy_marshal_VOID__STRING_UINT,
+                                        G_TYPE_NONE, 2,
+                                        G_TYPE_STRING, G_TYPE_UINT);
+
   g_type_class_add_private (object_class, sizeof (EphyCellRendererTabPrivate));
 }
 
@@ -305,6 +404,8 @@ ephy_cell_renderer_tab_init (EphyCellRendererTab *renderer)
   priv = renderer->priv = EPHY_CELL_RENDERER_TAB_GET_PRIVATE (renderer);
 
   priv->n_columns = 1;
+
+  GTK_CELL_RENDERER (renderer)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
 }
 
 GtkCellRenderer *
diff --git a/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c b/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c
index f774c8c..3088cf1 100644
--- a/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c
+++ b/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c
@@ -79,44 +79,48 @@ ephy_tabs_reloaded_extension_register_type (GTypeModule *module)
 }
 
 static void
-sanitize_tree_view (GtkTreeView *view)
+icon_clicked_cb (GtkCellRenderer *renderer, 
+                 const char *     path,
+                 guint            icon_id,
+                 EphyWindow *     window)
 {
-  static const struct {
-    gboolean expand;
-  } cell_info[] = {
-    { TRUE }
-  };
-  GtkCellLayout *column;
-  GtkCellRenderer *renderer;
-  GList *renderers, *walk;
-  guint column_id, renderer_id;
+  EphyEmbed *embed;
 
-  renderer_id = 0;
-  for (column_id = 0;; column_id++)
+  g_object_get (renderer, "tab", &embed, NULL);
+  
+  switch (icon_id)
     {
-      column = GTK_CELL_LAYOUT (gtk_tree_view_get_column (view, column_id));
-      if (column == NULL)
-        break;
-      renderers = gtk_cell_layout_get_cells (column);
-      g_list_foreach (renderers, (GFunc) g_object_ref, NULL);
-      gtk_cell_layout_clear (column);
-      for (walk = renderers; walk; walk = g_list_next (walk))
-        {
-          renderer = walk->data;
-          gtk_cell_layout_pack_start (column, renderer, cell_info[renderer_id].expand);
-          renderer_id++;
-          gtk_cell_layout_set_attributes (column, renderer, "tab", 0, NULL);
-        }
-      g_list_foreach (renderers, (GFunc) g_object_unref, NULL);
-      g_list_free (renderers);
+    case 0:
+      /* close */
+      /* yes, this is a hack - I blame Ephy's API */
+      g_signal_emit_by_name (ephy_window_get_notebook (window),
+                             "tab-close-request",
+                             embed);
+      break;
+    default:
+      /* someone added a button but no handler?! */
+      g_assert_not_reached ();
     }
+  
+  g_object_unref (embed);
+}
 
-  /* 
-   * If this fails, someone modified the ui file to contain different
-   * cell renderers and we need to add or remove data functions from 
-   * the funcs array above to match that change.
-   */
-  g_assert (renderer_id == G_N_ELEMENTS (cell_info));
+static void
+sanitize_tree_view (GtkTreeView *view, EphyWindow *window)
+{
+  GtkCellLayout *column;
+  GtkCellRenderer *renderer;
+  GList *renderers;
+
+  column = GTK_CELL_LAYOUT (gtk_tree_view_get_column (view, 0));
+  renderers = gtk_cell_layout_get_cells (column);
+  renderer = g_object_ref (renderers->data);
+  gtk_cell_layout_clear (column);
+  gtk_cell_layout_pack_start (column, renderer, TRUE);
+  gtk_cell_layout_set_attributes (column, renderer, "tab", 0, NULL);
+  g_signal_connect (renderer, "icon-clicked", G_CALLBACK (icon_clicked_cb), window);
+  g_object_unref (renderer);
+  g_list_free (renderers);
 }
 
 static gboolean
@@ -228,7 +232,7 @@ impl_attach_window (EphyExtension *extension,
         gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (tabs),
                                              tree_view_search_equal,
                                              NULL, NULL);
-        sanitize_tree_view (GTK_TREE_VIEW (tabs));
+        sanitize_tree_view (GTK_TREE_VIEW (tabs), window);
         manager = ephy_tabs_manager_new ();
         ephy_tabs_manager_attach (manager, GTK_NOTEBOOK (notebook));
         gtk_tree_view_set_model (GTK_TREE_VIEW (tabs), GTK_TREE_MODEL (manager));



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