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 --- libview/Makefile.am | 2 - libview/ev-loading-window.c | 294 ---------------------------------------- libview/ev-loading-window.h | 49 ------- libview/ev-view.c | 130 +++++------------- libview/ev-view.h | 2 + previewer/ev-previewer-window.c | 2 - shell/Makefile.am | 2 + shell/ev-loading-message.c | 180 ++++++++++++++++++++++++ shell/ev-loading-message.h | 45 ++++++ shell/ev-window.c | 78 ++++++++++- 10 files changed, 332 insertions(+), 452 deletions(-) delete mode 100644 libview/ev-loading-window.c delete mode 100644 libview/ev-loading-window.h create mode 100644 shell/ev-loading-message.c create mode 100644 shell/ev-loading-message.h diff --git a/libview/Makefile.am b/libview/Makefile.am index 855a1f20..b382810a 100644 --- a/libview/Makefile.am +++ b/libview/Makefile.am @@ -6,7 +6,6 @@ NOINST_H_FILES = \ ev-image-accessible.h \ ev-link-accessible.h \ ev-page-accessible.h \ - ev-loading-window.h \ ev-page-cache.h \ ev-pixbuf-cache.h \ ev-timeline.h \ @@ -38,7 +37,6 @@ libatrilview_la_SOURCES = \ ev-document-model.c \ ev-form-field-accessible.c \ ev-image-accessible.c \ - ev-loading-window.c \ ev-jobs.c \ ev-job-scheduler.c \ ev-link-accessible.c \ diff --git a/libview/ev-loading-window.c b/libview/ev-loading-window.c deleted file mode 100644 index 52de665c..00000000 --- a/libview/ev-loading-window.c +++ /dev/null @@ -1,294 +0,0 @@ -/* ev-loading-window.c - * this file is part of atril, a mate document viewer - * - * Copyright (C) 2010 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 -#include -#include "ev-loading-window.h" - -enum { - PROP_0, - PROP_PARENT -}; - -struct _EvLoadingWindow { - GtkWindow base_instance; - - GtkWindow *parent; - GtkWidget *spinner; - - gint x; - gint y; - gint width; - gint height; -}; - -struct _EvLoadingWindowClass { - GtkWindowClass base_class; -}; - -G_DEFINE_TYPE (EvLoadingWindow, ev_loading_window, GTK_TYPE_WINDOW) - -static void -ev_loading_window_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EvLoadingWindow *window = EV_LOADING_WINDOW (object); - - switch (prop_id) { - case PROP_PARENT: - window->parent = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -ev_loading_window_init (EvLoadingWindow *window) -{ - GtkWindow *gtk_window = GTK_WINDOW (window); - GtkWidget *widget = GTK_WIDGET (window); - GtkWidget *hbox; - GtkWidget *label; - GtkStyleContext *context; - GdkRGBA fg, bg; - - const gchar *loading_text = _("Loading…"); - const gchar *fg_color_name = "info_fg_color"; - const gchar *bg_color_name = "info_bg_color"; - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - - window->spinner = gtk_spinner_new (); - gtk_box_pack_start (GTK_BOX (hbox), window->spinner, FALSE, FALSE, 0); - gtk_widget_show (window->spinner); - - label = gtk_label_new (loading_text); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_widget_show (label); - - gtk_container_add (GTK_CONTAINER (window), hbox); - gtk_widget_show (hbox); - - gtk_widget_set_app_paintable (widget, TRUE); - - gtk_container_set_border_width (GTK_CONTAINER (window), 10); - - gtk_window_set_type_hint (gtk_window, GDK_WINDOW_TYPE_HINT_NOTIFICATION); - gtk_window_set_accept_focus (gtk_window, FALSE); - gtk_window_set_decorated (gtk_window, FALSE); - gtk_window_set_resizable (gtk_window, FALSE); - - context = gtk_widget_get_style_context (widget); - if (!gtk_style_context_lookup_color (context, fg_color_name, &fg) || - !gtk_style_context_lookup_color (context, bg_color_name, &bg)) { - fg.red = 0.7; - fg.green = 0.67; - fg.blue = 0.63; - fg.alpha = 1.0; - - bg.red = 0.99; - bg.green = 0.99; - bg.blue = 0.71; - bg.alpha = 1.0; - } - - gtk_widget_override_background_color (widget, GTK_STATE_NORMAL, &bg); - gtk_widget_override_color (widget, GTK_STATE_NORMAL, &fg); -} - -static GObject * -ev_loading_window_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - EvLoadingWindow *window; - GtkWindow *gtk_window; - - object = G_OBJECT_CLASS (ev_loading_window_parent_class)->constructor (type, - n_construct_properties, - construct_params); - window = EV_LOADING_WINDOW (object); - gtk_window = GTK_WINDOW (window); - - gtk_window_set_transient_for (gtk_window, window->parent); - gtk_window_set_destroy_with_parent (gtk_window, TRUE); - - return object; -} - -static void -_cairo_rounded_rectangle (cairo_t *cr, - gint width, - gint height, - gdouble radius) -{ - cairo_move_to (cr, radius, 0); - cairo_line_to (cr, width - radius, 0); - cairo_curve_to (cr, - width, 0, - width, 0, - width, - radius); - cairo_line_to (cr, width, height - radius); - cairo_curve_to (cr, - width,height, - width, height, - width - radius, - height); - cairo_line_to (cr, radius, height); - cairo_curve_to (cr, - 0, height, - 0, height, - 0, height - radius); - cairo_line_to (cr, 0, radius); - cairo_curve_to (cr, - 0, 0, - 0, 0, - radius, 0); -} - -static void -ev_loading_window_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - EvLoadingWindow *window = EV_LOADING_WINDOW (widget); - cairo_surface_t *surface; - cairo_region_t *shape; - cairo_t *cr; - double r; - - GTK_WIDGET_CLASS (ev_loading_window_parent_class)->size_allocate (widget, allocation); - - if (allocation->width == window->width && allocation->height == window->height) - return; - - window->width = allocation->width; - window->height = allocation->height; - - surface = cairo_image_surface_create (CAIRO_FORMAT_A8, window->width, window->height); - cr = cairo_create (surface); - - cairo_save (cr); - cairo_rectangle (cr, 0, 0, window->width, window->height); - cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); - cairo_fill (cr); - cairo_restore (cr); - - cairo_set_source_rgb (cr, 1., 1., 1.); - r = MIN (window->width, window->height) / 2.; - _cairo_rounded_rectangle (cr, window->width, window->height, r); - cairo_fill (cr); - - cairo_destroy (cr); - - shape = gdk_cairo_region_create_from_surface (surface); - cairo_surface_destroy (surface); - - gtk_widget_shape_combine_region (widget, shape); - cairo_region_destroy (shape); -} - -static void -ev_loading_window_hide (GtkWidget *widget) -{ - EvLoadingWindow *window = EV_LOADING_WINDOW (widget); - - window->x = window->y = 0; - - gtk_spinner_stop (GTK_SPINNER (window->spinner)); - - GTK_WIDGET_CLASS (ev_loading_window_parent_class)->hide (widget); -} - -static void -ev_loading_window_show (GtkWidget *widget) -{ - EvLoadingWindow *window = EV_LOADING_WINDOW (widget); - - gtk_spinner_start (GTK_SPINNER (window->spinner)); - - GTK_WIDGET_CLASS (ev_loading_window_parent_class)->show (widget); -} - -static void -ev_loading_window_class_init (EvLoadingWindowClass *klass) -{ - GObjectClass *g_object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *gtk_widget_class = GTK_WIDGET_CLASS (klass); - - g_object_class->constructor = ev_loading_window_constructor; - g_object_class->set_property = ev_loading_window_set_property; - - gtk_widget_class->size_allocate = ev_loading_window_size_allocate; - gtk_widget_class->show = ev_loading_window_show; - gtk_widget_class->hide = ev_loading_window_hide; - - g_object_class_install_property (g_object_class, - PROP_PARENT, - g_param_spec_object ("parent", - "Parent", - "The parent window", - GTK_TYPE_WINDOW, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY)); -} - -/* Public methods */ -GtkWidget * -ev_loading_window_new (GtkWindow *parent) -{ - GtkWidget *window; - - g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL); - - window = g_object_new (EV_TYPE_LOADING_WINDOW, - "type", GTK_WINDOW_POPUP, - "parent", parent, - NULL); - return window; -} - -void -ev_loading_window_get_size (EvLoadingWindow *window, - gint *width, - gint *height) -{ - if (width) *width = window->width; - if (height) *height = window->height; -} - -void -ev_loading_window_move (EvLoadingWindow *window, - gint x, - gint y) -{ - if (x == window->x && y == window->y) - return; - - window->x = x; - window->y = y; - gtk_window_move (GTK_WINDOW (window), x, y); -} diff --git a/libview/ev-loading-window.h b/libview/ev-loading-window.h deleted file mode 100644 index aac13614..00000000 --- a/libview/ev-loading-window.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ev-loading-window.h - * this file is part of atril, a mate document viewer - * - * Copyright (C) 2010 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_WINDOW_H -#define EV_LOADING_WINDOW_H - -#include - -G_BEGIN_DECLS - -typedef struct _EvLoadingWindow EvLoadingWindow; -typedef struct _EvLoadingWindowClass EvLoadingWindowClass; - -#define EV_TYPE_LOADING_WINDOW (ev_loading_window_get_type()) -#define EV_LOADING_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_LOADING_WINDOW, EvLoadingWindow)) -#define EV_LOADING_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_LOADING_WINDOW, EvLoadingWindowClass)) -#define EV_IS_LOADING_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_LOADING_WINDOW)) -#define EV_IS_LOADING_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_LOADING_WINDOW)) -#define EV_LOADING_WINDOW_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_LOADING_WINDOW, EvLoadingWindowClass)) - -GType ev_loading_window_get_type (void) G_GNUC_CONST; -GtkWidget *ev_loading_window_new (GtkWindow *parent); -void ev_loading_window_get_size (EvLoadingWindow *window, - gint *width, - gint *height); -void ev_loading_window_move (EvLoadingWindow *window, - gint x, - gint y); - -G_END_DECLS - -#endif /* EV_LOADING_WINDOW_H */ diff --git a/libview/ev-view.c b/libview/ev-view.c index 6e02efce..a2f368d8 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -41,7 +41,6 @@ #include "ev-view-marshal.h" #include "ev-document-annotations.h" #include "ev-annotation-window.h" -#include "ev-loading-window.h" #include "ev-view.h" #include "ev-view-accessible.h" #include "ev-view-private.h" @@ -74,6 +73,7 @@ enum { enum { PROP_0, + PROP_IS_LOADING, PROP_HADJUSTMENT, PROP_VADJUSTMENT, PROP_HSCROLL_POLICY, @@ -189,12 +189,9 @@ static void draw_one_page (EvView GtkBorder *border, GdkRectangle *expose_area, gboolean *page_ready); -static void show_loading_window (EvView *view); -static void hide_loading_window (EvView *view); static void ev_view_reload_page (EvView *view, gint page, cairo_region_t *region); -static void ev_view_loading_window_move (EvView *view); /*** Callbacks ***/ static void ev_view_change_page (EvView *view, @@ -751,7 +748,7 @@ view_update_range_and_current_page (EvView *view) if (best_current_page >= 0 && view->current_page != best_current_page) { view->current_page = best_current_page; - hide_loading_window (view); + ev_view_set_loading (view, FALSE); ev_document_model_set_page (view->model, best_current_page); } } @@ -4046,13 +4043,6 @@ ev_view_draw (GtkWidget *widget, GdkRectangle *area = &clip_rect; gint i; - if (view->loading) { - show_loading_window (view); - } else if (view->loading_window && - gtk_widget_get_visible (view->loading_window)) { - ev_view_loading_window_move (view); - } - gtk_render_background (gtk_widget_get_style_context (widget), cr, 0, 0, @@ -5690,81 +5680,6 @@ highlight_forward_search_results (EvView *view, cairo_t *cr, int page) cairo_restore (cr); } -static void -ev_view_loading_window_move (EvView *view) -{ - GtkWidget *widget = GTK_WIDGET (view); - EvLoadingWindow *window = EV_LOADING_WINDOW (view->loading_window); - gint root_x, root_y; - gint window_width; - GtkAllocation allocation; - - gtk_widget_get_allocation (widget, &allocation); - gdk_window_get_origin (gtk_widget_get_window (widget), &root_x, &root_y); - ev_loading_window_get_size (window, &window_width, NULL); - - root_x += allocation.width - window_width - 10; - root_y += 10; - - ev_loading_window_move (window, root_x, root_y); -} - -static gboolean -show_loading_window_cb (EvView *view) -{ - if (!view->loading_window) { - GtkWindow *parent; - GdkScreen *screen; - - parent = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))); - view->loading_window = ev_loading_window_new (parent); - - /* Show the window off screen to get a valid size asap */ - screen = gtk_widget_get_screen (GTK_WIDGET (view)); - gtk_window_move (GTK_WINDOW (view->loading_window), - WidthOfScreen (gdk_x11_screen_get_xscreen (screen)) + 1, - HeightOfScreen (gdk_x11_screen_get_xscreen (screen)) + 1); - gtk_widget_show (view->loading_window); - } - - ev_view_loading_window_move (view); - - gtk_widget_show (view->loading_window); - - view->loading_timeout = 0; - - return FALSE; -} - -static void -show_loading_window (EvView *view) -{ - if (view->loading_window && gtk_widget_get_visible (view->loading_window)) { - ev_view_loading_window_move (view); - return; - } - - if (!view->loading_timeout) { - view->loading_timeout = - g_timeout_add_full (G_PRIORITY_LOW, - 0.5, (GSourceFunc)show_loading_window_cb, - view, NULL); - } -} - -static void -hide_loading_window (EvView *view) -{ - if (view->loading_timeout) { - g_source_remove (view->loading_timeout); - view->loading_timeout = 0; - } - - if (view->loading_window && gtk_widget_get_visible (view->loading_window)) { - gtk_widget_hide (view->loading_window); - } -} - static void draw_surface (cairo_t *cr, cairo_surface_t *surface, @@ -5894,7 +5809,7 @@ draw_one_page (EvView *view, if (!page_surface) { if (page == current_page) - show_loading_window (view); + ev_view_set_loading (view, TRUE); *page_ready = FALSE; @@ -5906,7 +5821,7 @@ draw_one_page (EvView *view, #endif if (page == current_page) - hide_loading_window (view); + ev_view_set_loading (view, FALSE); ev_view_get_page_size (view, page, &width, &height); offset_x = overlap.x - real_page_area.x; @@ -6027,11 +5942,6 @@ ev_view_dispose (GObject *object) view->cursor_blink_timeout_id = 0; } - if (view->loading_timeout) { - g_source_remove (view->loading_timeout); - view->loading_timeout = 0; - } - g_clear_object(&view->accessible); G_OBJECT_CLASS (ev_view_parent_class)->dispose (object); @@ -6046,6 +5956,9 @@ ev_view_get_property (GObject *object, EvView *view = EV_VIEW (object); switch (prop_id) { + case PROP_IS_LOADING: + g_value_set_boolean (value, view->loading); + break; case PROP_HADJUSTMENT: g_value_set_object (value, view->hadjustment); break; @@ -6073,6 +5986,9 @@ ev_view_set_property (GObject *object, EvView *view = EV_VIEW (object); switch (prop_id) { + case PROP_IS_LOADING: + ev_view_set_loading (view, g_value_get_boolean (value)); + break; case PROP_HADJUSTMENT: set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, (GtkAdjustment *) g_value_get_object (value)); @@ -6309,6 +6225,15 @@ ev_view_class_init (EvViewClass *class) class->scroll = ev_view_scroll_internal; class->move_cursor = ev_view_move_cursor; + g_object_class_install_property (object_class, + PROP_IS_LOADING, + g_param_spec_boolean ("is-loading", + "Is Loading", + "Whether the view is loading", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /* Scrollable interface */ g_object_class_override_property (object_class, PROP_HADJUSTMENT, "hadjustment"); g_object_class_override_property (object_class, PROP_VADJUSTMENT, "vadjustment"); @@ -6572,7 +6497,7 @@ ev_view_change_page (EvView *view, view->current_page = new_page; view->pending_scroll = SCROLL_TO_PAGE_POSITION; - hide_loading_window (view); + ev_view_set_loading (view, FALSE); ev_document_misc_get_pointer_position (GTK_WIDGET (view), &x, &y); ev_view_handle_cursor_over_xy (view, x, y); @@ -6743,10 +6668,17 @@ void ev_view_set_loading (EvView *view, gboolean loading) { - if (view->loading && !loading) - hide_loading_window (view); + if (view->loading == loading) + return; + view->loading = loading; - gtk_widget_queue_draw (GTK_WIDGET (view)); + g_object_notify (G_OBJECT (view), "is-loading"); +} + +gboolean +ev_view_is_loading (EvView *view) +{ + return view->loading; } static gboolean @@ -6841,7 +6773,7 @@ ev_view_document_changed_cb (EvDocumentModel *model, view->find_result = 0; if (view->document) { - view->loading = FALSE; + ev_view_set_loading (view, FALSE); g_object_ref (view->document); setup_caches (view); } diff --git a/libview/ev-view.h b/libview/ev-view.h index 802b8cb9..ac16211f 100644 --- a/libview/ev-view.h +++ b/libview/ev-view.h @@ -45,8 +45,10 @@ GType ev_view_get_type (void) G_GNUC_CONST; GtkWidget* ev_view_new (void); void ev_view_set_model (EvView *view, EvDocumentModel *model); +EV_DEPRECATED void ev_view_set_loading (EvView *view, gboolean loading); +gboolean ev_view_is_loading (EvView *view); void ev_view_reload (EvView *view); void ev_view_set_page_cache_size (EvView *view, gsize cache_size); diff --git a/previewer/ev-previewer-window.c b/previewer/ev-previewer-window.c index 3920d2db..df1cb7a1 100644 --- a/previewer/ev-previewer-window.c +++ b/previewer/ev-previewer-window.c @@ -392,7 +392,6 @@ ev_previewer_window_set_document (EvPreviewerWindow *window, g_signal_connect (model, "notify::sizing-mode", G_CALLBACK (view_sizing_mode_changed), window); - ev_view_set_loading (window->view, FALSE); gtk_action_group_set_sensitive (window->action_group, TRUE); gtk_action_group_set_sensitive (window->accels_group, TRUE); } @@ -603,7 +602,6 @@ ev_previewer_window_constructor (GType type, window, 0); ev_view_set_model (window->view, window->model); ev_document_model_set_continuous (window->model, FALSE); - ev_view_set_loading (window->view, TRUE); gtk_container_add (GTK_CONTAINER (window->swindow), GTK_WIDGET (window->view)); gtk_widget_show (GTK_WIDGET (window->view)); 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