[epiphany/wip/titledomain: 2/2] WIP for title+domain widget in the toolbar.



commit c15b64dcd7de8cdc2fcf0ba519fcd8473f76bb02
Author: Xan Lopez <xan igalia com>
Date:   Mon Jul 2 18:41:53 2012 +0200

    WIP for title+domain widget in the toolbar.
    
    TODO:
    
    - Size of the location entry is wrong again due to padding added to
      back/forward buttons to match design.
    
    - Title+domain still shown in some cases where it should not, and
      viceversa.
    
    - Clicking on the widget does nothing.

 src/Makefile.am             |    2 +
 src/ephy-title-domain-box.c |  243 +++++++++++++++++++++++++++++++++++++++++++
 src/ephy-title-domain-box.h |   64 +++++++++++
 src/ephy-toolbar.c          |  101 +++++++++++++++++--
 src/ephy-window.c           |    1 +
 src/resources/epiphany.css  |    4 +
 6 files changed, 408 insertions(+), 7 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 3750c19..cfcb87b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,7 @@ NOINST_H_FILES = \
 	ephy-page-menu-action.h			\
 	ephy-password-info.h			\
 	ephy-private.h				\
+	ephy-title-domain-box.h			\
 	ephy-toolbar.h				\
 	ephy-window-action.h			\
 	languages.h				\
@@ -72,6 +73,7 @@ libephymain_la_SOURCES = \
 	ephy-password-info.c	        	\
 	ephy-session.c				\
 	ephy-shell.c				\
+	ephy-title-domain-box.c			\
 	ephy-toolbar.c				\
 	ephy-window.c				\
 	ephy-window-action.c			\
diff --git a/src/ephy-title-domain-box.c b/src/ephy-title-domain-box.c
new file mode 100644
index 0000000..59696cf
--- /dev/null
+++ b/src/ephy-title-domain-box.c
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright  2012 Igalia S.L.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ephy-title-domain-box.h"
+
+#include <libsoup/soup.h>
+
+struct _EphyTitleDomainBoxPrivate {
+  GtkWidget *title;
+  GtkWidget *domain;
+
+  EphyWebView *view;
+
+  GBinding *title_binding;
+  GBinding *domain_binding;
+};
+
+enum {
+  PROP_0,
+
+  PROP_TITLE,
+  PROP_DOMAIN,
+  PROP_VIEW
+};
+
+#define EPHY_TITLE_DOMAIN_BOX_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBoxPrivate))
+
+G_DEFINE_TYPE (EphyTitleDomainBox, ephy_title_domain_box, GTK_TYPE_BOX)
+
+static gboolean
+transform_uri_to_domain (GBinding *binding,
+                         const GValue *source_value,
+                         GValue *target_value,
+                         gpointer user_data)
+{
+  const char *uri;
+  SoupURI *soup_uri;
+
+  uri = g_value_get_string (source_value);
+  if (!uri)
+    return FALSE;
+
+  soup_uri = soup_uri_new (uri);
+  g_value_set_string (target_value, soup_uri->host);
+  soup_uri_free (soup_uri);
+
+  return TRUE;
+}
+
+static void
+reset_bindings (EphyTitleDomainBox *box)
+{
+  EphyTitleDomainBoxPrivate *priv = box->priv;
+
+  g_clear_object (&priv->title_binding);
+  
+  if (priv->view)
+    priv->title_binding = g_object_bind_property (priv->view, "title",
+                                                  box, "title",
+                                                  G_BINDING_SYNC_CREATE);
+
+  g_clear_object (&priv->domain_binding);
+
+  if (priv->view)
+    priv->domain_binding = g_object_bind_property_full (priv->view, "uri",
+                                                        box, "domain",
+                                                        G_BINDING_SYNC_CREATE,
+                                                        transform_uri_to_domain,
+                                                        NULL, NULL, NULL);
+}
+
+static void
+ephy_title_domain_box_constructed (GObject *object)
+{
+  reset_bindings (EPHY_TITLE_DOMAIN_BOX (object));
+  
+  G_OBJECT_CLASS (ephy_title_domain_box_parent_class)->constructed (object);
+}
+
+static void
+ephy_title_domain_box_get_property (GObject *object,
+                                    guint prop_id,
+                                    GValue *value,
+                                    GParamSpec *pspec)
+{
+  EphyTitleDomainBoxPrivate *priv = EPHY_TITLE_DOMAIN_BOX (object)->priv;
+
+  switch (prop_id) {
+  case PROP_TITLE:
+    break;
+  case PROP_DOMAIN:
+    break;
+  case PROP_VIEW:
+    g_value_set_object (value, priv->view);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+ephy_title_domain_box_set_property (GObject *object,
+                                    guint prop_id,
+                                    const GValue *value,
+                                    GParamSpec *pspec)
+{
+  EphyTitleDomainBoxPrivate *priv = EPHY_TITLE_DOMAIN_BOX (object)->priv;
+
+  switch (prop_id) {
+  case PROP_TITLE: {
+    char *markup = g_markup_printf_escaped ("<span weight='bold'>%s</span>", g_value_get_string (value));
+    gtk_label_set_markup (GTK_LABEL (priv->title), markup);
+    g_free (markup);
+    break;
+  }
+  case PROP_DOMAIN: {
+    const char *base_domain = soup_tld_get_base_domain (g_value_get_string (value), NULL);
+    char *markup = g_markup_printf_escaped ("<span foreground='gray' size='small'>%s</span>", base_domain);
+    gtk_label_set_markup (GTK_LABEL (priv->domain), markup);
+    g_free (markup);
+    break;
+  }
+  case PROP_VIEW:
+    ephy_title_domain_box_set_view (EPHY_TITLE_DOMAIN_BOX (object),
+                                    g_value_get_object (value));
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
+  }
+}
+
+static void
+ephy_title_domain_box_class_init (EphyTitleDomainBoxClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructed = ephy_title_domain_box_constructed;
+  gobject_class->get_property = ephy_title_domain_box_get_property;
+  gobject_class->set_property = ephy_title_domain_box_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_TITLE,
+                                   g_param_spec_string ("title",
+                                                        "Domain",
+                                                        "The box's title",
+                                                        "",
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+  g_object_class_install_property (gobject_class,
+                                   PROP_DOMAIN,
+                                   g_param_spec_string ("domain",
+                                                        "Domain",
+                                                        "The box's domain",
+                                                        "",
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_VIEW,
+                                   g_param_spec_object ("view",
+                                                        "View",
+                                                        "The WebView associated to this widget",
+                                                        EPHY_TYPE_WEB_VIEW,
+                                                        G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+
+  g_type_class_add_private (klass, sizeof (EphyTitleDomainBoxPrivate));
+}
+
+static void
+ephy_title_domain_box_init (EphyTitleDomainBox *box)
+{
+  EphyTitleDomainBoxPrivate *priv;
+
+  priv = box->priv = EPHY_TITLE_DOMAIN_BOX_GET_PRIVATE (box);
+
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (box), GTK_ORIENTATION_VERTICAL);
+  gtk_box_set_spacing (GTK_BOX (box), 0);
+
+  priv->title = gtk_label_new ("");
+  gtk_widget_set_halign (priv->title, GTK_ALIGN_CENTER);
+  gtk_widget_show (priv->title);
+  gtk_box_pack_start (GTK_BOX (box),
+                      priv->title,
+                      FALSE, FALSE, 0);
+
+  priv->domain = gtk_label_new ("");
+  gtk_widget_set_halign (priv->domain, GTK_ALIGN_CENTER);
+  gtk_widget_show (priv->domain);
+  gtk_box_pack_start (GTK_BOX (box),
+                      priv->domain,
+                      FALSE, FALSE, 0);
+}
+
+void
+ephy_title_domain_box_set_view (EphyTitleDomainBox *box,
+                                EphyWebView *view)
+{
+  EphyTitleDomainBoxPrivate *priv;
+
+  g_return_if_fail (EPHY_IS_TITLE_DOMAIN_BOX (box));
+
+  priv = box->priv;
+
+  if (priv->view)
+    g_object_unref (priv->view);
+
+  priv->view = view;
+
+  if (priv->view)
+    g_object_ref (priv->view);
+
+  reset_bindings (box);
+
+  g_object_notify (G_OBJECT (box), "view");
+}
+
+GtkWidget *
+ephy_title_domain_box_new (EphyWebView *view)
+{
+  return g_object_new (EPHY_TYPE_TITLE_DOMAIN_BOX,
+                       "view", view,
+                       NULL);
+}
+
diff --git a/src/ephy-title-domain-box.h b/src/ephy-title-domain-box.h
new file mode 100644
index 0000000..2a7f595
--- /dev/null
+++ b/src/ephy-title-domain-box.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 sts=2 et: */
+/*
+ *  Copyright  2012 Igalia S.L.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION)
+#error "Only <epiphany/epiphany.h> can be included directly."
+#endif
+
+#ifndef EPHY_TITLE_DOMAIN_BOX_H
+#define EPHY_TITLE_DOMAIN_BOX_H
+
+#include <gtk/gtk.h>
+
+#include "ephy-web-view.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_TITLE_DOMAIN_BOX         (ephy_title_domain_box_get_type ())
+#define EPHY_TITLE_DOMAIN_BOX(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBox))
+#define EPHY_TITLE_DOMAIN_BOX_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBoxClass))
+#define EPHY_IS_TITLE_DOMAIN_BOX(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_TITLE_DOMAIN_BOX))
+#define EPHY_IS_TITLE_DOMAIN_BOX_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_TITLE_DOMAIN_BOX))
+#define EPHY_TITLE_DOMAIN_BOX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_TITLE_DOMAIN_BOX, EphyTitleDomainBoxClass))
+
+typedef struct _EphyTitleDomainBoxClass    EphyTitleDomainBoxClass;
+typedef struct _EphyTitleDomainBox         EphyTitleDomainBox;
+typedef struct _EphyTitleDomainBoxPrivate  EphyTitleDomainBoxPrivate;
+
+struct _EphyTitleDomainBox {
+  GtkBox parent;
+
+  /*< private >*/
+  EphyTitleDomainBoxPrivate *priv;
+};
+
+struct _EphyTitleDomainBoxClass {
+  GtkBoxClass parent_class;
+};
+
+GType       ephy_title_domain_box_get_type (void);
+GtkWidget * ephy_title_domain_box_new      (EphyWebView *view);
+void        ephy_title_domain_box_set_view (EphyTitleDomainBox *box,
+                                            EphyWebView *view);
+
+G_END_DECLS
+
+#endif
diff --git a/src/ephy-toolbar.c b/src/ephy-toolbar.c
index 97a72a1..d25f4ca 100644
--- a/src/ephy-toolbar.c
+++ b/src/ephy-toolbar.c
@@ -21,9 +21,11 @@
 #include "config.h"
 #include "ephy-toolbar.h"
 
+#include "ephy-embed-container.h"
 #include "ephy-location-entry.h"
 #include "ephy-middle-clickable-button.h"
 #include "ephy-private.h"
+#include "ephy-title-domain-box.h"
 
 G_DEFINE_TYPE (EphyToolbar, ephy_toolbar, GTK_TYPE_TOOLBAR)
 
@@ -40,6 +42,12 @@ static GParamSpec *object_properties[N_PROPERTIES] = { NULL, };
 struct _EphyToolbarPrivate {
   EphyWindow *window;
   GtkWidget *entry;
+  GtkWidget *title_domain;
+  GtkWidget *title_domain_tool_item;
+  GtkWidget *location_stop_reload;
+
+  EphyWebView *view;
+  gulong active_embed_tracker_id;
 };
 
 static void
@@ -78,12 +86,45 @@ ephy_toolbar_get_property (GObject *object,
 }
 
 static void
+active_embed_load_status_cb (EphyWebView *view, GParamSpec *spec, EphyToolbar *toolbar)
+{
+  WebKitLoadStatus status;
+  EphyToolbarPrivate *priv = toolbar->priv;
+
+  status = webkit_web_view_get_load_status (WEBKIT_WEB_VIEW (view));
+  
+  if (status == WEBKIT_LOAD_FINISHED)
+    gtk_widget_show (priv->title_domain_tool_item);
+  else
+    gtk_widget_hide (priv->title_domain_tool_item);
+}
+
+static void
+active_child_cb (EphyWindow *window, GParamSpec *pspec, EphyToolbar *toolbar)
+{
+  EphyEmbed *embed;
+  EphyToolbarPrivate *priv = toolbar->priv;
+
+  embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+  if (embed) {
+    priv->view = ephy_embed_get_web_view (embed);
+    ephy_title_domain_box_set_view (EPHY_TITLE_DOMAIN_BOX (priv->title_domain), priv->view);
+
+    if (priv->active_embed_tracker_id)
+      g_signal_handlers_disconnect_by_func (priv->view, active_embed_load_status_cb, toolbar);
+
+    priv->active_embed_tracker_id = g_signal_connect (priv->view, "notify::load-status",
+                                                      G_CALLBACK (active_embed_load_status_cb), toolbar);
+  }
+}
+
+static void
 ephy_toolbar_constructed (GObject *object)
 {
   EphyToolbarPrivate *priv = EPHY_TOOLBAR (object)->priv;
   GtkActionGroup *action_group;
   GtkAction *action;
-  GtkToolItem *back_forward, *location_stop_reload, *tool_item;
+  GtkToolItem *back_forward, *tool_item;
   GtkWidget *tool_button, *box, *location, *toolbar;
   GtkSizeGroup *size;
 
@@ -103,6 +144,7 @@ ephy_toolbar_constructed (GObject *object)
   /* Back and Forward */
   back_forward = gtk_tool_item_new ();
   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_name (box, "ephy-back-forward-button-container");
 
   /* Back */
   tool_button = ephy_middle_clickable_button_new ();
@@ -121,6 +163,7 @@ ephy_toolbar_constructed (GObject *object)
   /* FIXME: apparently we need an image inside the button for the action
    * icon to appear. */
   gtk_button_set_image (GTK_BUTTON (tool_button), gtk_image_new ());
+
   action = gtk_action_group_get_action (action_group, "NavigationForward");
   gtk_activatable_set_related_action (GTK_ACTIVATABLE (tool_button),
                                       action);
@@ -138,11 +181,19 @@ ephy_toolbar_constructed (GObject *object)
   gtk_widget_set_margin_right (GTK_WIDGET (back_forward), 12);
 
   /* Location and Reload/Stop */
-  location_stop_reload = gtk_tool_item_new ();
+  priv->location_stop_reload = GTK_WIDGET (gtk_tool_item_new ());
   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
   /* Location */
   priv->entry = location = ephy_location_entry_new ();
+
+  /* Make the whole entry+reload combo visible if the entry is
+   * visible, since some parts of Epiphany set the entry visible in
+   * reaction to some event (like Ctrl+L). */
+  g_object_bind_property (priv->entry, "visible",
+                          priv->location_stop_reload, "visible",
+                          G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
   gtk_box_pack_start (GTK_BOX (box), location,
                       TRUE, TRUE, 0);
   gtk_style_context_add_class (gtk_widget_get_style_context (box),
@@ -158,20 +209,42 @@ ephy_toolbar_constructed (GObject *object)
                                       action);
   gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (tool_button));
 
-  gtk_container_add (GTK_CONTAINER (location_stop_reload), box);
+  gtk_container_add (GTK_CONTAINER (priv->location_stop_reload), box); 
   gtk_container_child_set (GTK_CONTAINER (toolbar),
-                           GTK_WIDGET (location_stop_reload),
+                           GTK_WIDGET (priv->location_stop_reload),
                            "expand", TRUE,
                            NULL);
   
-  gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (location_stop_reload));
+  gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (priv->location_stop_reload));
 
   gtk_size_group_add_widget (size, tool_button);
   gtk_size_group_add_widget (size, location);
   g_object_unref (size);
 
-  gtk_widget_set_margin_right (GTK_WIDGET (location_stop_reload), 12);
-  gtk_widget_show_all (GTK_WIDGET (location_stop_reload));
+  gtk_widget_set_margin_right (GTK_WIDGET (priv->location_stop_reload), 12);
+  gtk_widget_show_all (GTK_WIDGET (priv->location_stop_reload));
+
+  /* Title+domain widget. */
+  priv->title_domain_tool_item = GTK_WIDGET (gtk_tool_item_new ());
+  priv->title_domain = ephy_title_domain_box_new (NULL);
+
+  gtk_container_child_set (GTK_CONTAINER (toolbar),
+                           GTK_WIDGET (priv->title_domain_tool_item),
+                           "expand", TRUE,
+                           NULL);
+  g_signal_connect (priv->window, "notify::active-child",
+                    G_CALLBACK (active_child_cb), toolbar);
+
+  /* Add it, but don't show it, it's hidden by default. */
+  gtk_widget_show (GTK_WIDGET (priv->title_domain));
+  gtk_container_add (GTK_CONTAINER (priv->title_domain_tool_item), priv->title_domain);
+  gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (priv->title_domain_tool_item));
+
+  /* If the location entry is visible the title+domain widget cannot
+   * be, and viceversa. */
+  g_object_bind_property (priv->title_domain_tool_item, "visible",
+                          priv->location_stop_reload, "visible",
+                          G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN | G_BINDING_BIDIRECTIONAL);
 
   /* Page Menu */
   tool_item = gtk_tool_item_new ();
@@ -189,10 +262,24 @@ ephy_toolbar_constructed (GObject *object)
 }
 
 static void
+ephy_toolbar_dispose (GObject *object)
+{
+  EphyToolbarPrivate *priv = EPHY_TOOLBAR (object)->priv;
+
+  if (priv->active_embed_tracker_id) {
+    g_signal_handlers_disconnect_by_func (priv->view, active_embed_load_status_cb, object);
+    priv->active_embed_tracker_id = 0;
+  }
+
+  G_OBJECT_CLASS (ephy_toolbar_parent_class)->dispose (object);
+}
+
+static void
 ephy_toolbar_class_init (EphyToolbarClass *klass)
 {
     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+    gobject_class->dispose = ephy_toolbar_dispose;
     gobject_class->set_property = ephy_toolbar_set_property;
     gobject_class->get_property = ephy_toolbar_get_property;
     gobject_class->constructed = ephy_toolbar_constructed;
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 3e1cf47..86d01a4 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -3751,6 +3751,7 @@ _ephy_window_activate_location (EphyWindow *window)
 	gboolean visible;
 
 	entry = ephy_toolbar_get_location_entry (EPHY_TOOLBAR (priv->toolbar));
+	gtk_widget_show (entry);
 
 	g_object_get (G_OBJECT (priv->toolbar), "visible", &visible, NULL);
 	if (visible == FALSE)
diff --git a/src/resources/epiphany.css b/src/resources/epiphany.css
index 113856f..a623b3e 100644
--- a/src/resources/epiphany.css
+++ b/src/resources/epiphany.css
@@ -14,6 +14,10 @@
   padding: 0;
 }
 
+#ephy-back-forward-button-container GtkButton {
+  padding: 6px;
+}
+
 .primary-toolbar.toolbar {
     padding-left: 0;
     padding-right: 0;



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