X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=libview%2Fev-view-presentation.c;h=bbbfd4f9435737518b17078540e6e8cf4bf6e035;hb=f3731bd3bdbcdc18c53e0f74bdaac93311046352;hp=9cc74af710b1c1b446c60250cf04ceb83eb87985;hpb=afa18f6b0d2d1851d5b89aba42b2ab263c00710b;p=evince.git diff --git a/libview/ev-view-presentation.c b/libview/ev-view-presentation.c index 9cc74af7..bbbfd4f9 100644 --- a/libview/ev-view-presentation.c +++ b/libview/ev-view-presentation.c @@ -30,6 +30,7 @@ #include "ev-transition-animation.h" #include "ev-view-cursor.h" #include "ev-page-cache.h" +#include "ev-view-marshal.h" enum { PROP_0, @@ -40,8 +41,10 @@ enum { }; enum { + PAGE_CHANGED, CHANGE_PAGE, FINISHED, + SIGNAL_EXTERNAL_LINK, N_SIGNALS }; @@ -56,6 +59,8 @@ struct _EvViewPresentation { GtkWidget base; + guint is_constructing : 1; + guint current_page; cairo_surface_t *current_surface; EvDocument *document; @@ -94,15 +99,18 @@ struct _EvViewPresentationClass GtkWidgetClass base_class; /* signals */ - void (* change_page) (EvViewPresentation *pview, - GtkScrollType scroll); - void (* finished) (EvViewPresentation *pview); + void (* page_changed) (EvViewPresentation *pview, + gint old_page, + gint new_page); + void (* change_page) (EvViewPresentation *pview, + GtkScrollType scroll); + void (* finished) (EvViewPresentation *pview); + void (* external_link) (EvViewPresentation *pview, + EvLinkAction *action); }; static guint signals[N_SIGNALS] = { 0 }; -static void ev_view_presentation_next_page (EvViewPresentation *pview); -static void ev_view_presentation_previous_page (EvViewPresentation *pview); static void ev_view_presentation_set_cursor_for_location (EvViewPresentation *pview, gdouble x, gdouble y); @@ -378,6 +386,25 @@ ev_view_presentation_delete_job (EvViewPresentation *pview, g_object_unref (job); } +static void +ev_view_presentation_reset_jobs (EvViewPresentation *pview) +{ + if (pview->curr_job) { + ev_view_presentation_delete_job (pview, pview->curr_job); + pview->curr_job = NULL; + } + + if (pview->prev_job) { + ev_view_presentation_delete_job (pview, pview->prev_job); + pview->prev_job = NULL; + } + + if (pview->next_job) { + ev_view_presentation_delete_job (pview, pview->next_job); + pview->next_job = NULL; + } +} + static void ev_view_presentation_update_current_page (EvViewPresentation *pview, guint page) @@ -466,6 +493,8 @@ ev_view_presentation_update_current_page (EvViewPresentation *pview, } } + g_signal_emit (pview, signals[PAGE_CHANGED], 0, pview->current_page); + pview->current_page = page; if (pview->page_cache) @@ -482,7 +511,20 @@ ev_view_presentation_update_current_page (EvViewPresentation *pview, gtk_widget_queue_draw (GTK_WIDGET (pview)); } -static void +void +ev_view_presentation_set_page (EvViewPresentation *pview, gint new_page) +{ + guint n_pages; + + n_pages = ev_document_get_n_pages (pview->document); + + if (new_page >= n_pages) + ev_view_presentation_set_end (pview); + else + ev_view_presentation_update_current_page (pview, new_page); +} + +void ev_view_presentation_next_page (EvViewPresentation *pview) { guint n_pages; @@ -507,7 +549,7 @@ ev_view_presentation_next_page (EvViewPresentation *pview) ev_view_presentation_update_current_page (pview, new_page); } -static void +void ev_view_presentation_previous_page (EvViewPresentation *pview) { gint new_page = 0; @@ -627,9 +669,9 @@ ev_view_presentation_goto_window_create (EvViewPresentation *pview) GtkWindow *toplevel, *goto_window; toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (pview))); - goto_window = GTK_WINDOW (pview->goto_window); if (pview->goto_window) { + goto_window = GTK_WINDOW (pview->goto_window); if (gtk_window_has_group (toplevel)) gtk_window_group_add_window (gtk_window_get_group (toplevel), goto_window); else if (gtk_window_has_group (goto_window)) @@ -639,6 +681,7 @@ ev_view_presentation_goto_window_create (EvViewPresentation *pview) } pview->goto_window = gtk_window_new (GTK_WINDOW_POPUP); + goto_window = GTK_WINDOW (pview->goto_window); gtk_window_set_screen (goto_window, gtk_widget_get_screen (GTK_WIDGET (pview))); if (gtk_window_has_group (toplevel)) @@ -732,6 +775,9 @@ ev_view_presentation_link_is_supported (EvViewPresentation *pview, case EV_LINK_ACTION_TYPE_GOTO_DEST: return ev_link_action_get_dest (action) != NULL; case EV_LINK_ACTION_TYPE_NAMED: + case EV_LINK_ACTION_TYPE_GOTO_REMOTE: + case EV_LINK_ACTION_TYPE_EXTERNAL_URI: + case EV_LINK_ACTION_TYPE_LAUNCH: return TRUE; default: return FALSE; @@ -790,14 +836,15 @@ ev_view_presentation_get_link_at_location (EvViewPresentation *pview, } static void -ev_vew_presentation_goto_link_dest (EvViewPresentation *pview, - EvLink *link) +ev_vew_presentation_handle_link (EvViewPresentation *pview, + EvLink *link) { EvLinkAction *action; action = ev_link_get_action (link); - if (ev_link_action_get_action_type (action) == EV_LINK_ACTION_TYPE_NAMED) { + switch (ev_link_action_get_action_type (action)) { + case EV_LINK_ACTION_TYPE_NAMED: { const gchar *name = ev_link_action_get_name (action); if (g_ascii_strcasecmp (name, "FirstPage") == 0) { @@ -812,13 +859,25 @@ ev_vew_presentation_goto_link_dest (EvViewPresentation *pview, n_pages = ev_document_get_n_pages (pview->document); ev_view_presentation_update_current_page (pview, n_pages - 1); } - } else { + } + break; + + case EV_LINK_ACTION_TYPE_GOTO_DEST: { EvLinkDest *dest; gint page; dest = ev_link_action_get_dest (action); page = ev_document_links_get_dest_page (EV_DOCUMENT_LINKS (pview->document), dest); ev_view_presentation_update_current_page (pview, page); + } + break; + case EV_LINK_ACTION_TYPE_GOTO_REMOTE: + case EV_LINK_ACTION_TYPE_EXTERNAL_URI: + case EV_LINK_ACTION_TYPE_LAUNCH: + g_signal_emit (pview, signals[SIGNAL_EXTERNAL_LINK], 0, action); + break; + default: + break; } } @@ -843,7 +902,7 @@ ev_view_presentation_set_cursor (EvViewPresentation *pview, gdk_window_set_cursor (gtk_widget_get_window (widget), cursor); gdk_flush (); if (cursor) - gdk_cursor_unref (cursor); + g_object_unref (cursor); } static void @@ -910,21 +969,7 @@ ev_view_presentation_dispose (GObject *object) ev_view_presentation_animation_cancel (pview); ev_view_presentation_transition_stop (pview); ev_view_presentation_hide_cursor_timeout_stop (pview); - - if (pview->curr_job) { - ev_view_presentation_delete_job (pview, pview->curr_job); - pview->curr_job = NULL; - } - - if (pview->prev_job) { - ev_view_presentation_delete_job (pview, pview->prev_job); - pview->prev_job = NULL; - } - - if (pview->next_job) { - ev_view_presentation_delete_job (pview, pview->next_job); - pview->next_job = NULL; - } + ev_view_presentation_reset_jobs (pview); if (pview->current_surface) { cairo_surface_destroy (pview->current_surface); @@ -1154,7 +1199,7 @@ ev_view_presentation_button_release_event (GtkWidget *widget, event->x, event->y); if (link) - ev_vew_presentation_goto_link_dest (pview, link); + ev_vew_presentation_handle_link (pview, link); else ev_view_presentation_next_page (pview); } @@ -1247,8 +1292,8 @@ ev_view_presentation_realize (GtkWidget *widget) gdk_window_set_user_data (window, widget); gtk_widget_set_window (widget, window); - - gdk_window_set_background_rgba (window, &black); + gtk_style_context_set_background (gtk_widget_get_style_context (widget), + window); g_idle_add ((GSourceFunc)init_presentation, widget); } @@ -1328,7 +1373,7 @@ ev_view_presentation_set_property (GObject *object, pview->current_page = g_value_get_uint (value); break; case PROP_ROTATION: - pview->rotation = g_value_get_uint (value); + ev_view_presentation_set_rotation (pview, g_value_get_uint (value)); break; case PROP_INVERTED_COLORS: pview->inverted_colors = g_value_get_boolean (value); @@ -1338,10 +1383,27 @@ ev_view_presentation_set_property (GObject *object, } } +static void +ev_view_presentation_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EvViewPresentation *pview = EV_VIEW_PRESENTATION (object); + + switch (prop_id) { + case PROP_ROTATION: + g_value_set_uint (value, ev_view_presentation_get_rotation (pview)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + static GObject * ev_view_presentation_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) + guint n_construct_properties, + GObjectConstructParam *construct_params) { GObject *object; EvViewPresentation *pview; @@ -1350,6 +1412,7 @@ ev_view_presentation_constructor (GType type, n_construct_properties, construct_params); pview = EV_VIEW_PRESENTATION (object); + pview->is_constructing = FALSE; if (EV_IS_DOCUMENT_LINKS (pview->document)) { pview->page_cache = ev_page_cache_new (pview->document); @@ -1365,6 +1428,7 @@ ev_view_presentation_class_init (EvViewPresentationClass *klass) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkBindingSet *binding_set; + GtkCssProvider *provider; klass->change_page = ev_view_presentation_change_page; @@ -1382,6 +1446,7 @@ ev_view_presentation_class_init (EvViewPresentationClass *klass) gobject_class->constructor = ev_view_presentation_constructor; gobject_class->set_property = ev_view_presentation_set_property; + gobject_class->get_property = ev_view_presentation_get_property; g_object_class_install_property (gobject_class, PROP_DOCUMENT, @@ -1405,8 +1470,8 @@ ev_view_presentation_class_init (EvViewPresentationClass *klass) "Rotation", "Current rotation angle", 0, 360, 0, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); g_object_class_install_property (gobject_class, PROP_INVERTED_COLORS, g_param_spec_boolean ("inverted_colors", @@ -1425,6 +1490,15 @@ ev_view_presentation_class_init (EvViewPresentationClass *klass) g_cclosure_marshal_VOID__ENUM, G_TYPE_NONE, 1, GTK_TYPE_SCROLL_TYPE); + signals [PAGE_CHANGED] = + g_signal_new ("page-changed", + EV_TYPE_VIEW_PRESENTATION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EvViewPresentationClass, page_changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_INT); signals[FINISHED] = g_signal_new ("finished", G_OBJECT_CLASS_TYPE (gobject_class), @@ -1434,6 +1508,15 @@ ev_view_presentation_class_init (EvViewPresentationClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + signals[SIGNAL_EXTERNAL_LINK] = + g_signal_new ("external-link", + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvViewPresentationClass, external_link), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); binding_set = gtk_binding_set_by_class (klass); add_change_page_binding_keypad (binding_set, GDK_KEY_Left, 0, GTK_SCROLL_PAGE_BACKWARD); @@ -1464,12 +1547,23 @@ ev_view_presentation_class_init (EvViewPresentationClass *klass) gtk_binding_entry_add_signal (binding_set, GDK_KEY_K, 0, "change_page", 1, GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_BACKWARD); + + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, + "EvViewPresentation {\n" + " background-color: black; }", + -1, NULL); + gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + g_object_unref (provider); } static void ev_view_presentation_init (EvViewPresentation *pview) { gtk_widget_set_can_focus (GTK_WIDGET (pview), TRUE); + pview->is_constructing = TRUE; } GtkWidget * @@ -1494,3 +1588,31 @@ ev_view_presentation_get_current_page (EvViewPresentation *pview) { return pview->current_page; } + +void +ev_view_presentation_set_rotation (EvViewPresentation *pview, + gint rotation) +{ + if (rotation >= 360) + rotation -= 360; + else if (rotation < 0) + rotation += 360; + + if (pview->rotation == rotation) + return; + + pview->rotation = rotation; + g_object_notify (G_OBJECT (pview), "rotation"); + if (pview->is_constructing) + return; + + pview->scale = 0; + ev_view_presentation_reset_jobs (pview); + ev_view_presentation_update_current_page (pview, pview->current_page); +} + +guint +ev_view_presentation_get_rotation (EvViewPresentation *pview) +{ + return pview->rotation; +}