diff options
author | Xan Lopez <xan@igalia.com> | 2012-07-02 18:41:53 +0200 |
---|---|---|
committer | Xan Lopez <xan@igalia.com> | 2012-07-02 18:41:53 +0200 |
commit | c15b64dcd7de8cdc2fcf0ba519fcd8473f76bb02 (patch) | |
tree | d96bfb0260392547ba485e9230b35da7600e2389 | |
parent | 4df50904275b1c1319d67d8c81b4a2570af3df32 (diff) | |
download | epiphany-c15b64dcd7de8cdc2fcf0ba519fcd8473f76bb02.tar.gz |
WIP for title+domain widget in the toolbar.wip/titledomain
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.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/ephy-title-domain-box.c | 243 | ||||
-rw-r--r-- | src/ephy-title-domain-box.h | 64 | ||||
-rw-r--r-- | src/ephy-toolbar.c | 101 | ||||
-rw-r--r-- | src/ephy-window.c | 1 | ||||
-rw-r--r-- | src/resources/epiphany.css | 4 |
6 files changed, 408 insertions, 7 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3750c19ec..cfcb87b2e 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 000000000..59696cf40 --- /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 000000000..2a7f5958e --- /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 97a72a13d..d25f4cad6 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 3e1cf4773..86d01a443 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 113856f42..a623b3ece 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; |