From 63463849638784e91339acfc27b4b0645b8573f3 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Sat, 29 Sep 2012 16:06:39 +0200 Subject: Use GtkOverlay to show the loading message Remove the EvLoadingWindow from libview and move the implementation to the shell using a EvLoadingMessage widget and GtkOverlay. EvView has now a is-loading property that allows the users to implement their own loading notification system. This fixes several realted to the loading window. origin commit: https://git.gnome.org/browse/evince/commit/?h=gnome-3-8&id=035c1cb --- shell/Makefile.am | 2 + shell/ev-loading-message.c | 180 +++++++++++++++++++++++++++++++++++++++++++++ shell/ev-loading-message.h | 45 ++++++++++++ shell/ev-window.c | 78 ++++++++++++++++++-- 4 files changed, 299 insertions(+), 6 deletions(-) create mode 100644 shell/ev-loading-message.c create mode 100644 shell/ev-loading-message.h (limited to 'shell') diff --git a/shell/Makefile.am b/shell/Makefile.am index 3f0309c8..1bf3cba4 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -43,6 +43,8 @@ atril_SOURCES= \ ev-history.h \ ev-keyring.h \ ev-keyring.c \ + ev-loading-message.c \ + ev-loading-message.h \ ev-message-area.c \ ev-message-area.h \ ev-metadata.c \ diff --git a/shell/ev-loading-message.c b/shell/ev-loading-message.c new file mode 100644 index 00000000..b09d3479 --- /dev/null +++ b/shell/ev-loading-message.c @@ -0,0 +1,180 @@ +/* ev-loading-message.c + * this file is part of atril, a mate document viewer + * + * Copyright (C) 2010, 2012 Carlos Garcia Campos + * + * Atril 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. + * + * Atril 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 "ev-loading-message.h" + +#include +#include + +struct _EvLoadingMessage { + GtkBox base_instance; + + GtkWidget *spinner; +}; + +struct _EvLoadingMessageClass { + GtkBoxClass base_class; +}; + +G_DEFINE_TYPE (EvLoadingMessage, ev_loading_message, GTK_TYPE_BOX) + +static void +ev_loading_message_init (EvLoadingMessage *message) +{ + GtkWidget *widget = GTK_WIDGET (message); + GtkWidget *label; + GtkStyleContext *context; + + gtk_container_set_border_width (GTK_CONTAINER (message), 10); + + message->spinner = gtk_spinner_new (); + gtk_box_pack_start (GTK_BOX (message), message->spinner, FALSE, FALSE, 0); + gtk_widget_show (message->spinner); + + label = gtk_label_new (_("Loading…")); + gtk_box_pack_start (GTK_BOX (message), label, FALSE, FALSE, 0); + gtk_widget_show (label); +} + +static void +get_widget_padding (GtkWidget *widget, + GtkBorder *padding) +{ + GtkStyleContext *context; + GtkStateFlags state; + + context = gtk_widget_get_style_context (widget); + state = gtk_style_context_get_state (context); + gtk_style_context_get_padding (context, state, padding); +} + +static void +ev_loading_message_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EvLoadingMessage *message = EV_LOADING_MESSAGE (widget); + GtkAllocation child_allocation; + GtkBorder padding; + + get_widget_padding (widget, &padding); + child_allocation.y = allocation->x + padding.left; + child_allocation.x = allocation->y + padding.top; + child_allocation.width = MAX (1, allocation->width - (padding.left + padding.right)); + child_allocation.height = MAX (1, allocation->height - (padding.top + padding.bottom)); + + GTK_WIDGET_CLASS (ev_loading_message_parent_class)->size_allocate (widget, &child_allocation); + gtk_widget_set_allocation (widget, allocation); +} + +static void +ev_loading_message_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + GtkBorder padding; + + GTK_WIDGET_CLASS (ev_loading_message_parent_class)->get_preferred_width (widget, minimum_size, natural_size); + + get_widget_padding (widget, &padding); + *minimum_size += padding.left + padding.right; + *natural_size += padding.left + padding.right; +} + +static void +ev_loading_message_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + GtkBorder padding; + + GTK_WIDGET_CLASS (ev_loading_message_parent_class)->get_preferred_height (widget, minimum_size, natural_size); + + get_widget_padding (widget, &padding); + *minimum_size += padding.top + padding.bottom; + *natural_size += padding.top + padding.bottom; +} + +static gboolean +ev_loading_message_draw (GtkWidget *widget, + cairo_t *cr) +{ + GtkStyleContext *context; + gint width, height; + + context = gtk_widget_get_style_context (widget); + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + + gtk_render_background (context, cr, 0, 0, width, height); + gtk_render_frame (context, cr, 0, 0, width, height); + + GTK_WIDGET_CLASS (ev_loading_message_parent_class)->draw (widget, cr); + + return TRUE; +} + +static void +ev_loading_message_hide (GtkWidget *widget) +{ + EvLoadingMessage *message = EV_LOADING_MESSAGE (widget); + + gtk_spinner_stop (GTK_SPINNER (message->spinner)); + + GTK_WIDGET_CLASS (ev_loading_message_parent_class)->hide (widget); +} + +static void +ev_loading_message_show (GtkWidget *widget) +{ + EvLoadingMessage *message = EV_LOADING_MESSAGE (widget); + + gtk_spinner_start (GTK_SPINNER (message->spinner)); + + GTK_WIDGET_CLASS (ev_loading_message_parent_class)->show (widget); +} + +static void +ev_loading_message_class_init (EvLoadingMessageClass *klass) +{ + GtkWidgetClass *gtk_widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class->size_allocate = ev_loading_message_size_allocate; + gtk_widget_class->get_preferred_width = ev_loading_message_get_preferred_width; + gtk_widget_class->get_preferred_height = ev_loading_message_get_preferred_height; + gtk_widget_class->draw = ev_loading_message_draw; + gtk_widget_class->show = ev_loading_message_show; + gtk_widget_class->hide = ev_loading_message_hide; +} + +/* Public methods */ +GtkWidget * +ev_loading_message_new (void) +{ + GtkWidget *message; + + message = g_object_new (EV_TYPE_LOADING_MESSAGE, + "orientation", GTK_ORIENTATION_HORIZONTAL, + "spacing", 12, + NULL); + return message; +} + + diff --git a/shell/ev-loading-message.h b/shell/ev-loading-message.h new file mode 100644 index 00000000..3034b792 --- /dev/null +++ b/shell/ev-loading-message.h @@ -0,0 +1,45 @@ +/* ev-loading-message.h + * this file is part of atril, a mate document viewer + * + * Copyright (C) 2010, 2012 Carlos Garcia Campos + * + * Atril 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. + * + * Atril 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. + */ + +#ifndef EV_LOADING_MESSAGE_H +#define EV_LOADING_MESSAGE_H + +#include + +G_BEGIN_DECLS + +typedef struct _EvLoadingMessage EvLoadingMessage; +typedef struct _EvLoadingMessageClass EvLoadingMessageClass; + +#define EV_TYPE_LOADING_MESSAGE (ev_loading_message_get_type()) +#define EV_LOADING_MESSAGE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_LOADING_MESSAGE, EvLoadingMessage)) +#define EV_IS_LOADING_MESSAGE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_LOADING_MESSAGE)) +#define EV_LOADING_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_LOADING_MESSAGE, EvLoadingMessageClass)) +#define EV_IS_LOADING_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_LOADING_MESSAGE)) +#define EV_LOADING_MESSAGE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_LOADING_MESSAGE, EvLoadingMessageClass)) + +GType ev_loading_message_get_type (void) G_GNUC_CONST; + +GtkWidget *ev_loading_message_new (void); + +G_END_DECLS + +#endif /* EV_LOADING_MESSAGE_H */ + diff --git a/shell/ev-window.c b/shell/ev-window.c index 820b9f32..f323a4f9 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -68,6 +68,7 @@ #include "ev-image.h" #include "ev-job-scheduler.h" #include "ev-jobs.h" +#include "ev-loading-message.h" #include "ev-message-area.h" #include "ev-metadata.h" #include "ev-navigation-action.h" @@ -137,6 +138,7 @@ struct _EvWindowPrivate { GtkWidget *find_bar; GtkWidget *scrolled_window; GtkWidget *view; + GtkWidget *loading_message; GtkWidget *presentation_view; GtkWidget *message_area; GtkWidget *password_view; @@ -163,6 +165,9 @@ struct _EvWindowPrivate { guint progress_idle; GCancellable *progress_cancellable; + /* Loading message */ + guint loading_message_timeout; + /* Dialogs */ GtkWidget *properties; GtkWidget *print_dialog; @@ -868,6 +873,35 @@ ev_window_warning_message (EvWindow *window, ev_window_set_message_area (window, area); } +static gboolean +show_loading_message_cb (EvWindow *window) +{ + window->priv->loading_message_timeout = 0; + gtk_widget_show (window->priv->loading_message); + + return FALSE; +} + +static void +ev_window_show_loading_message (EvWindow *window) +{ + if (window->priv->loading_message_timeout) + return; + window->priv->loading_message_timeout = + g_timeout_add_full (G_PRIORITY_LOW, 0.5, (GSourceFunc)show_loading_message_cb, window, NULL); +} + +static void +ev_window_hide_loading_message (EvWindow *window) +{ + if (window->priv->loading_message_timeout) { + g_source_remove (window->priv->loading_message_timeout); + window->priv->loading_message_timeout = 0; + } + + gtk_widget_hide (window->priv->loading_message); +} + typedef struct _PageTitleData { const gchar *page_label; gchar *page_title; @@ -1019,6 +1053,17 @@ view_caret_cursor_moved_cb (EvView *view, g_free (caret_position); } +static void +view_is_loading_changed_cb (EvView *view, + GParamSpec *spec, + EvWindow *window) +{ + if (ev_view_is_loading (view)) + ev_window_show_loading_message (window); + else + ev_window_hide_loading_message (window); +} + static void ev_window_page_changed_cb (EvWindow *ev_window, gint old_page, @@ -1833,7 +1878,7 @@ ev_window_load_job_cb (EvJob *job, g_assert (job_load->uri); - ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE); + ev_window_hide_loading_message (ev_window); /* Success! */ if (!ev_job_is_failed (job)) { ev_document_model_set_document (ev_window->priv->model, document); @@ -2090,7 +2135,7 @@ ev_window_load_remote_failed (EvWindow *ev_window, { if ( !ev_window->priv->view ) return; - ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE); + ev_window_hide_loading_message (ev_window); ev_window->priv->in_reload = FALSE; ev_window_error_message (ev_window, error, "%s", _("Unable to open document")); @@ -2182,7 +2227,7 @@ window_open_file_copy_ready_cb (GFile *source, ev_window->priv->uri = NULL; g_object_unref (source); - ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE); + ev_window_hide_loading_message (ev_window); } else { ev_window_load_remote_failed (ev_window, error); g_object_unref (source); @@ -2346,7 +2391,7 @@ ev_window_open_uri (EvWindow *ev_window, if (!g_file_is_native (source_file) && !ev_window->priv->local_uri) { ev_window_load_file_remote (ev_window, source_file); } else { - ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE); + ev_window_show_loading_message (ev_window); g_object_unref (source_file); ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE); } @@ -6021,6 +6066,11 @@ ev_window_dispose (GObject *object) priv->interface_settings = NULL; } + if (priv->loading_message_timeout) { + g_source_remove (priv->loading_message_timeout); + priv->loading_message_timeout = 0; + } + if (priv->monitor) { g_object_unref (priv->monitor); priv->monitor = NULL; @@ -7607,6 +7657,7 @@ ev_window_init (EvWindow *ev_window) GError *error = NULL; GtkWidget *sidebar_widget; GtkWidget *menuitem; + GtkWidget *overlay; GObject *mpkeys; guint page_cache_mb; gchar *ui_path; @@ -7863,14 +7914,26 @@ ev_window_init (EvWindow *ev_window) sidebar_widget); ev_window->priv->view_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + + overlay = gtk_overlay_new (); ev_window->priv->scrolled_window = GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW, "shadow-type", GTK_SHADOW_IN, NULL)); + gtk_container_add (GTK_CONTAINER (overlay), ev_window->priv->scrolled_window); + gtk_widget_show (ev_window->priv->scrolled_window); + + ev_window->priv->loading_message = ev_loading_message_new (); + gtk_widget_set_name (ev_window->priv->loading_message, "ev-loading-message"); + gtk_widget_set_halign (ev_window->priv->loading_message, GTK_ALIGN_END); + gtk_widget_set_valign (ev_window->priv->loading_message, GTK_ALIGN_START); + gtk_widget_set_no_show_all (ev_window->priv->loading_message, TRUE); + gtk_overlay_add_overlay (GTK_OVERLAY (overlay), ev_window->priv->loading_message); + gtk_box_pack_start (GTK_BOX (ev_window->priv->view_box), - ev_window->priv->scrolled_window, + overlay, TRUE, TRUE, 0); - gtk_widget_show (ev_window->priv->scrolled_window); + gtk_widget_show (overlay); gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned), ev_window->priv->view_box); @@ -7917,6 +7980,9 @@ ev_window_init (EvWindow *ev_window) g_signal_connect_object (ev_window->priv->view, "layers-changed", G_CALLBACK (view_layers_changed_cb), ev_window, 0); + g_signal_connect_object (ev_window->priv->view, "notify::is-loading", + G_CALLBACK (view_is_loading_changed_cb), + ev_window, 0); g_signal_connect_object (ev_window->priv->view, "cursor-moved", G_CALLBACK (view_caret_cursor_moved_cb), ev_window, 0); -- cgit v1.2.1