[epiphany-extensions/tabs-reloaded: 11/16] [tabs-reloaded] Use a custom cell renderer to render tabs



commit d3b2b830b198d3156e6eeb7fd2890edac2c77f73
Author: Benjamin Otte <otte gnome org>
Date:   Fri Aug 7 19:19:38 2009 +0200

    [tabs-reloaded] Use a custom cell renderer to render tabs

 extensions/tabs-reloaded/Makefile.am               |    2 +
 extensions/tabs-reloaded/ephy-cell-renderer-tab.c  |  315 ++++++++++++++++++++
 extensions/tabs-reloaded/ephy-cell-renderer-tab.h  |   59 ++++
 .../tabs-reloaded/ephy-tabs-reloaded-extension.c   |   78 +-----
 extensions/tabs-reloaded/tabs-reloaded.c           |    2 +
 extensions/tabs-reloaded/tabs-reloaded.ui          |   24 +--
 6 files changed, 386 insertions(+), 94 deletions(-)
---
diff --git a/extensions/tabs-reloaded/Makefile.am b/extensions/tabs-reloaded/Makefile.am
index f3e5160..29ecbde 100644
--- a/extensions/tabs-reloaded/Makefile.am
+++ b/extensions/tabs-reloaded/Makefile.am
@@ -2,6 +2,8 @@ extensiondir = $(EXTENSIONS_DIR)
 extension_LTLIBRARIES = libtabsreloadedextension.la
 
 libtabsreloadedextension_la_SOURCES = \
+	ephy-cell-renderer-tab.c \
+	ephy-cell-renderer-tab.h \
 	ephy-tabs-manager.c \
 	ephy-tabs-manager.h \
 	ephy-tabs-reloaded-extension.c \
diff --git a/extensions/tabs-reloaded/ephy-cell-renderer-tab.c b/extensions/tabs-reloaded/ephy-cell-renderer-tab.c
new file mode 100644
index 0000000..e869a57
--- /dev/null
+++ b/extensions/tabs-reloaded/ephy-cell-renderer-tab.c
@@ -0,0 +1,315 @@
+/*
+ *  Copyright © 2009 Benjamin Otte
+ *
+ *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "config.h"
+
+#include "ephy-cell-renderer-tab.h"
+
+enum {
+  PROP_0,
+  PROP_TAB,
+  PROP_COLUMNS
+};
+
+
+#define EPHY_CELL_RENDERER_TAB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EPHY_TYPE_CELL_RENDERER_TAB, EphyCellRendererTabPrivate))
+
+struct _EphyCellRendererTabPrivate
+{
+  EphyEmbed *   tab;            /* the tab we render */
+  guint         n_columns;      /* number of columns we occupy */
+};
+
+G_DEFINE_DYNAMIC_TYPE (EphyCellRendererTab, ephy_cell_renderer_tab, GTK_TYPE_CELL_RENDERER)
+
+void
+ephy_cell_renderer_tab_register (GTypeModule *module)
+{
+  ephy_cell_renderer_tab_register_type (module);
+}
+
+static guint
+ephy_cell_renderer_get_row_height (GtkWidget *widget)
+{
+  PangoFontMetrics *metrics;
+  guint height;
+
+  metrics = pango_context_get_metrics (gtk_widget_get_pango_context (widget),
+                                       widget->style->font_desc,
+                                       NULL);
+  height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+                         pango_font_metrics_get_descent (metrics));
+
+  pango_font_metrics_unref (metrics);
+
+  return height;
+}
+
+static void
+ephy_cell_renderer_tab_get_size (GtkCellRenderer *cell,
+				 GtkWidget       *widget,
+				 GdkRectangle    *cell_area,
+				 gint            *x_offset,
+				 gint            *y_offset,
+				 gint            *width,
+				 gint            *height)
+{
+  EphyCellRendererTab *renderer = EPHY_CELL_RENDERER_TAB (cell);
+  EphyCellRendererTabPrivate *priv = renderer->priv;
+
+  priv = EPHY_CELL_RENDERER_TAB_GET_PRIVATE (cell);
+
+  if (x_offset) *x_offset = 0;
+  if (y_offset) *y_offset = 0;
+
+  /*
+   * We don't request any width as the width is determined by the user.
+   * This way, we allow shrinking as much as the user wishes */
+  if (width)
+    *width = 2 * cell->xpad + 1;
+  
+  if (height)
+    *height = 2 * cell->ypad + priv->n_columns * ephy_cell_renderer_get_row_height (widget);
+}
+
+static void
+ephy_cell_renderer_tab_render (GtkCellRenderer      *cell,
+                               GdkWindow            *window,
+                               GtkWidget            *widget,
+                               GdkRectangle         *background_area,
+                               GdkRectangle         *cell_area,
+                               GdkRectangle         *expose_area,
+                               GtkCellRendererState  flags)
+
+{
+  EphyCellRendererTab *renderer = EPHY_CELL_RENDERER_TAB (cell);
+  EphyCellRendererTabPrivate *priv = renderer->priv;
+  EphyWebView *view;
+  WebKitWebView *webview;
+  GdkPixbuf *pixbuf;
+  cairo_t *cr;
+  guint x, y, width, height, row_height, n_columns;
+  int icon_width, icon_height;
+  PangoLayout *layout;
+
+  /* FIXME: render "add tab" button here */
+  if (priv->tab == NULL)
+    return;
+
+  view = ephy_embed_get_web_view (priv->tab);
+  webview = WEBKIT_WEB_VIEW (view);
+  row_height = ephy_cell_renderer_get_row_height (widget);
+  x = cell_area->x + cell->xpad;
+  y = cell_area->y + cell->ypad;
+  width = cell_area->width - 2 * cell->xpad;
+  height = cell_area->height - 2 * cell->ypad;
+  gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
+                                     GTK_ICON_SIZE_MENU,
+                                     &icon_width,
+                                     &icon_height);
+  n_columns = priv->n_columns;
+
+  /* setup cairo context:
+   * - clip to exposed area
+   * - set origin correctly
+   * - clip to cell area (minus padding)
+   */
+  cr = gdk_cairo_create (window);
+  gdk_cairo_rectangle (cr, expose_area);
+  cairo_clip (cr);
+  cairo_translate (cr, x, y);
+  cairo_rectangle (cr, 0, 0, width, height);
+  cairo_clip (cr);
+
+  /* render the progressbar */
+  if (webkit_web_view_get_load_status (webview) != WEBKIT_LOAD_FINISHED)
+    {
+      GdkRectangle clip;
+      gtk_paint_box (widget->style,
+                     window,
+                     GTK_STATE_NORMAL, GTK_SHADOW_IN,
+                     NULL, widget, NULL,
+                     x, y + height - row_height, width, row_height);
+      clip.x = x;
+      clip.y = y + height - row_height;
+      clip.width = width * webkit_web_view_get_progress (webview) + 0.5;
+      clip.height = row_height;
+      gtk_paint_box (widget->style,
+                     window,
+                     GTK_STATE_SELECTED, GTK_SHADOW_OUT,
+                     &clip, widget, "bar",
+                     clip.x, clip.y,
+                     clip.width, clip.height);
+      if (n_columns > 1)
+        n_columns--;
+    }
+
+  /* render the title */
+  layout = gtk_widget_create_pango_layout (widget,
+                                           ephy_web_view_get_title (view));
+  pango_layout_set_width (layout, width * PANGO_SCALE);
+  if (pango_layout_get_line_count (layout) >= n_columns)
+    {
+      if (ephy_web_view_get_icon (view))
+        pango_layout_set_indent (layout, icon_width * PANGO_SCALE);
+    }
+  pango_layout_set_height (layout, -(int)n_columns);
+  pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+  gtk_paint_layout (widget->style,
+                    window,
+                    GTK_STATE_NORMAL, /* FIXME */
+		    TRUE,
+                    expose_area,
+                    widget,
+                    "cellrenderertext",
+                    x,
+                    y,
+                    layout);
+  g_object_unref (layout);
+
+  /* render the icons */
+  cairo_translate (cr, cell_area->width, 0);
+  pixbuf = gtk_widget_render_icon (widget, "gtk-close", GTK_ICON_SIZE_MENU, NULL);
+  cairo_translate (cr, -icon_width, 0);
+  gdk_cairo_set_source_pixbuf (cr, 
+                               pixbuf, 
+                               (icon_width - gdk_pixbuf_get_width (pixbuf)) / 2,
+                               (icon_height - gdk_pixbuf_get_height (pixbuf)) / 2);
+  cairo_paint_with_alpha (cr, flags & GTK_CELL_RENDERER_PRELIT ? 1.0 : 0.3);
+  g_object_unref (pixbuf);
+
+  cairo_destroy (cr);
+}
+
+static void
+ephy_cell_renderer_tab_get_property (GObject        *object,
+                                     guint           param_id,
+                                     GValue         *value,
+                                     GParamSpec     *pspec)
+{
+  EphyCellRendererTab *renderer = EPHY_CELL_RENDERER_TAB (object);
+  EphyCellRendererTabPrivate *priv = renderer->priv;
+  
+  switch (param_id)
+    {
+    case PROP_TAB:
+      g_value_set_object (value, priv->tab);
+      break;
+    case PROP_COLUMNS:
+      g_value_set_uint (value, priv->n_columns);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+static void
+ephy_cell_renderer_tab_set_property (GObject      *object,
+                                     guint         param_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  EphyCellRendererTab *renderer = EPHY_CELL_RENDERER_TAB (object);
+  EphyCellRendererTabPrivate *priv = renderer->priv;
+  
+  switch (param_id)
+    {
+    case PROP_TAB:
+      if (priv->tab)
+        g_object_unref (priv->tab);
+      priv->tab = g_value_dup_object (value);
+      break;
+    case PROP_COLUMNS:
+      priv->n_columns = g_value_get_uint (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+    }
+}
+
+static void
+ephy_cell_renderer_tab_finalize (GObject *object)
+{
+  EphyCellRendererTab *renderer = EPHY_CELL_RENDERER_TAB (object);
+  EphyCellRendererTabPrivate *priv = renderer->priv;
+
+  if (priv->tab)
+    g_object_unref (priv->tab);
+
+  G_OBJECT_CLASS (ephy_cell_renderer_tab_parent_class)->finalize (object);
+}
+
+static void
+ephy_cell_renderer_tab_class_finalize (EphyCellRendererTabClass *class)
+{
+}
+
+static void
+ephy_cell_renderer_tab_class_init (EphyCellRendererTabClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+
+  object_class->finalize = ephy_cell_renderer_tab_finalize;
+
+  object_class->get_property = ephy_cell_renderer_tab_get_property;
+  object_class->set_property = ephy_cell_renderer_tab_set_property;
+
+  cell_class->get_size = ephy_cell_renderer_tab_get_size;
+  cell_class->render = ephy_cell_renderer_tab_render;
+
+  g_object_class_install_property (object_class,
+				   PROP_TAB,
+				   g_param_spec_object ("tab",
+							"tab",
+                                                        "the tab to render",
+							EPHY_TYPE_EMBED,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+				   PROP_COLUMNS,
+				   g_param_spec_uint   ("columns",
+							"columns",
+                                                        "number of text columns to span",
+                                                        1,
+                                                        G_MAXUINT,
+                                                        1,
+							G_PARAM_READWRITE));
+
+  g_type_class_add_private (object_class, sizeof (EphyCellRendererTabPrivate));
+}
+
+static void
+ephy_cell_renderer_tab_init (EphyCellRendererTab *renderer)
+{
+  EphyCellRendererTabPrivate *priv;
+
+  priv = renderer->priv = EPHY_CELL_RENDERER_TAB_GET_PRIVATE (renderer);
+
+  priv->n_columns = 1;
+}
+
+GtkCellRenderer *
+ephy_cell_renderer_tab_new (void)
+{
+  return g_object_new (EPHY_TYPE_CELL_RENDERER_TAB, NULL);
+}
+
diff --git a/extensions/tabs-reloaded/ephy-cell-renderer-tab.h b/extensions/tabs-reloaded/ephy-cell-renderer-tab.h
new file mode 100644
index 0000000..5250306
--- /dev/null
+++ b/extensions/tabs-reloaded/ephy-cell-renderer-tab.h
@@ -0,0 +1,59 @@
+/*
+ *  Copyright © 2009 Benjamin Otte
+ *
+ *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_CELL_RENDERER_TAB_H
+
+#include <epiphany/epiphany.h>
+
+
+G_BEGIN_DECLS
+
+
+#define EPHY_TYPE_CELL_RENDERER_TAB		      (ephy_cell_renderer_tab_get_type ())
+#define EPHY_CELL_RENDERER_TAB(obj)		      (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_CELL_RENDERER_TAB, EphyCellRendererTab))
+#define EPHY_CELL_RENDERER_TAB_CLASS(klass)	      (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_CELL_RENDERER_TAB, EphyCellRendererTabClass))
+#define EPHY_IS_CELL_RENDERER_TAB(obj)		      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_CELL_RENDERER_TAB))
+#define EPHY_IS_CELL_RENDERER_TAB_CLASS(klass)	      (G_TYPE_CHECK_CLASS_TYPE ((klass), EPHY_TYPE_CELL_RENDERER_TAB))
+#define EPHY_CELL_RENDERER_TAB_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), EPHY_TYPE_CELL_RENDERER_TAB, EphyCellRendererTabClass))
+
+typedef struct _EphyCellRendererTab EphyCellRendererTab;
+typedef struct _EphyCellRendererTabClass EphyCellRendererTabClass;
+typedef struct _EphyCellRendererTabPrivate EphyCellRendererTabPrivate;
+
+struct _EphyCellRendererTab
+{
+  GtkCellRenderer parent;
+
+  EphyCellRendererTabPrivate *priv;
+};
+
+struct _EphyCellRendererTabClass
+{
+  GtkCellRendererClass parent_class;
+};
+
+GType            ephy_cell_renderer_tab_get_type (void) G_GNUC_CONST;
+void             ephy_cell_renderer_tab_register (GTypeModule *module);
+
+GtkCellRenderer *ephy_cell_renderer_tab_new      (void);
+
+
+G_END_DECLS
+
+
+#endif /* EPHY_CELL_RENDERER_TAB_H */
diff --git a/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c b/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c
index 90ab339..f774c8c 100644
--- a/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c
+++ b/extensions/tabs-reloaded/ephy-tabs-reloaded-extension.c
@@ -79,81 +79,12 @@ ephy_tabs_reloaded_extension_register_type (GTypeModule *module)
 }
 
 static void
-pixbuf_renderer_cell_data_func (GtkCellLayout *  column,
-                                GtkCellRenderer *renderer,
-                                GtkTreeModel *   model,
-                                GtkTreeIter *    iter,
-                                gpointer         unused)
-{
-  EphyEmbed *embed;
-  EphyWebView *view;
-  
-  embed = ephy_tabs_manager_get_tab (EPHY_TABS_MANAGER (model),
-                                     iter);
-  view = ephy_embed_get_web_view (embed);
-
-  g_object_set (renderer,
-                "pixbuf", ephy_web_view_get_icon (view),
-                "visible", ephy_web_view_get_icon (view) != NULL,
-                NULL);
-}
-
-static void
-text_renderer_cell_data_func (GtkCellLayout *  column,
-                              GtkCellRenderer *renderer,
-                              GtkTreeModel *   model,
-                              GtkTreeIter *    iter,
-                              gpointer         unused)
-{
-  EphyEmbed *embed;
-  EphyWebView *view;
-  WebKitWebView *webkit;
-  
-  embed = ephy_tabs_manager_get_tab (EPHY_TABS_MANAGER (model),
-                                     iter);
-  view = ephy_embed_get_web_view (embed);
-  webkit = WEBKIT_WEB_VIEW (view);
-
-  g_object_set (renderer,
-                "text", ephy_web_view_get_title (view),
-                "visible", webkit_web_view_get_load_status (webkit) == WEBKIT_LOAD_FINISHED,
-                NULL);
-}
-
-static void
-progress_renderer_cell_data_func (GtkCellLayout *  column,
-                                  GtkCellRenderer *renderer,
-                                  GtkTreeModel *   model,
-                                  GtkTreeIter *    iter,
-                                  gpointer         unused)
-{
-  EphyEmbed *embed;
-  EphyWebView *view;
-  WebKitWebView *webkit;
-  
-  embed = ephy_tabs_manager_get_tab (EPHY_TABS_MANAGER (model),
-                                     iter);
-  view = ephy_embed_get_web_view (embed);
-  webkit = WEBKIT_WEB_VIEW (view);
-
-  g_object_set (renderer,
-                "text", ephy_web_view_get_title (view),
-                "value", (int) (webkit_web_view_get_progress (webkit) * 100. + 0.5),
-                "visible", webkit_web_view_get_load_status (webkit) != WEBKIT_LOAD_FINISHED,
-                NULL);
-}
-
-static void
 sanitize_tree_view (GtkTreeView *view)
 {
   static const struct {
-    GtkCellLayoutDataFunc func;
     gboolean expand;
   } cell_info[] = {
-    { pixbuf_renderer_cell_data_func, FALSE },
-    { text_renderer_cell_data_func, TRUE },
-    { progress_renderer_cell_data_func, TRUE },
-    { NULL /* close button */, FALSE }
+    { TRUE }
   };
   GtkCellLayout *column;
   GtkCellRenderer *renderer;
@@ -173,13 +104,8 @@ sanitize_tree_view (GtkTreeView *view)
         {
           renderer = walk->data;
           gtk_cell_layout_pack_start (column, renderer, cell_info[renderer_id].expand);
-          if (cell_info[renderer_id].func)
-            gtk_cell_layout_set_cell_data_func (column,
-                                                renderer,
-                                                cell_info[renderer_id].func,
-                                                NULL,
-                                                NULL);
           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);
diff --git a/extensions/tabs-reloaded/tabs-reloaded.c b/extensions/tabs-reloaded/tabs-reloaded.c
index 2c56acc..eb81c7d 100644
--- a/extensions/tabs-reloaded/tabs-reloaded.c
+++ b/extensions/tabs-reloaded/tabs-reloaded.c
@@ -18,6 +18,7 @@
 
 #include "config.h"
 
+#include "ephy-cell-renderer-tab.h"
 #include "ephy-tabs-manager.h"
 #include "ephy-tabs-reloaded-extension.h"
 
@@ -34,6 +35,7 @@ register_module (GTypeModule *module)
 	extension_type = ephy_tabs_reloaded_extension_register_type (module);
 
         ephy_tabs_manager_register (module);
+        ephy_cell_renderer_tab_register (module);
 
 #ifdef ENABLE_NLS
 	/* Initialise i18n */
diff --git a/extensions/tabs-reloaded/tabs-reloaded.ui b/extensions/tabs-reloaded/tabs-reloaded.ui
index f7c5d09..30b0166 100644
--- a/extensions/tabs-reloaded/tabs-reloaded.ui
+++ b/extensions/tabs-reloaded/tabs-reloaded.ui
@@ -19,6 +19,7 @@
             <property name="can_focus">True</property>
             <property name="headers_visible">False</property>
             <property name="headers_clickable">False</property>
+            <property name="rules-hint">True</property>
             <property name="search_column">0</property>
             <property name="show_expanders">False</property>
             <child>
@@ -26,25 +27,12 @@
                 <property name="title">column</property>
                 <property name="expand">True</property>
                 <child>
-                  <object class="GtkCellRendererPixbuf" id="icon"/>
-                </child>
-                <child>
-                  <object class="GtkCellRendererText" id="title">
-                    <property name="width">1</property>
-                    <property name="ellipsize">end</property>
-                    <property name="single_paragraph_mode">True</property>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkCellRendererProgress" id="progress">
-                    <property name="width">1</property>
-                    <property name="text_xalign">0</property>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkCellRendererPixbuf" id="close">
-                    <property name="stock_id">gtk-close</property>
+                  <object class="EphyCellRendererTab" id="icon">
+                    <property name="columns">4</property>
                   </object>
+                  <attributes>
+                    <attribute name="tab">0</attribute>
+                  </attributes>
                 </child>
               </object>
             </child>



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