From 065ca13c80f87bdf729f906d0c6c47b0b55a4fb1 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Mon, 28 Jun 2010 09:43:06 +0000 Subject: [libview] Add support for synctex in EvView - A signal with a source link is emitted on CTRL + click - A new public method has been added to highlight the view rectangle corresponding to a source link --- diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index 0362bcd..79e6cdb 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -184,6 +184,9 @@ struct _EvView { /* Annotations */ GList *window_children; EvViewWindowChild *window_child_focus; + + /* Synctex */ + EvMapping *synctex_result; }; struct _EvViewClass { @@ -199,6 +202,8 @@ struct _EvViewClass { void (*popup_menu) (EvView *view, GList *items); void (*selection_changed) (EvView *view); + void (*sync_source) (EvView *view, + EvSourceLink *link); }; void _get_page_size_for_scale_and_rotation (EvDocument *document, diff --git a/libview/ev-view.c b/libview/ev-view.c index d1b6f33..a473d0a 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -54,6 +54,7 @@ enum { SIGNAL_EXTERNAL_LINK, SIGNAL_POPUP_MENU, SIGNAL_SELECTION_CHANGED, + SIGNAL_SYNC_SOURCE, N_SIGNALS }; @@ -175,6 +176,8 @@ static AtkObject *ev_view_get_accessible (GtkWidget *widget) /*** Drawing ***/ static void highlight_find_results (EvView *view, int page); +static void highlight_forward_search_results (EvView *view, + int page); static void draw_one_page (EvView *view, gint page, cairo_t *cr, @@ -253,7 +256,6 @@ static void jump_to_find_result (EvView static void jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift); - /*** Selection ***/ static void compute_selections (EvView *view, EvSelectionStyle style, @@ -2735,6 +2737,32 @@ ev_view_handle_annotation (EvView *view, } } +static gboolean +ev_view_synctex_backward_search (EvView *view, + gdouble x, + gdouble y) +{ + gint page = -1; + gint x_new = 0, y_new = 0; + EvSourceLink *link; + + if (!ev_document_has_synctex (view->document)) + return FALSE; + + if (!get_doc_point_from_location (view, x, y, &page, &x_new, &y_new)) + return FALSE; + + link = ev_document_synctex_backward_search (view->document, page, x_new, y_new); + if (link) { + g_signal_emit (view, signals[SIGNAL_SYNC_SOURCE], 0, link); + g_free (link); + + return TRUE; + } + + return FALSE; +} + /*** GtkWidget implementation ***/ static void @@ -3138,6 +3166,8 @@ ev_view_expose_event (GtkWidget *widget, highlight_find_results (view, i); if (page_ready && EV_IS_DOCUMENT_ANNOTATIONS (view->document)) show_annotation_windows (view, i); + if (page_ready && view->synctex_result) + highlight_forward_search_results (view, i); } cairo_destroy (cr); @@ -3334,6 +3364,9 @@ ev_view_button_press_event (GtkWidget *widget, EvAnnotation *annot; EvFormField *field; + if (event->state & GDK_CONTROL_MASK) + return ev_view_synctex_backward_search (view, event->x , event->y); + if (EV_IS_SELECTION (view->document) && view->selection_info.selections) { if (event->type == GDK_3BUTTON_PRESS) { start_selection_for_event (view, event); @@ -3362,7 +3395,13 @@ ev_view_button_press_event (GtkWidget *widget, view->image_dnd_info.start.y = event->y + view->scroll_y; } else { ev_view_remove_all (view); - + + if (view->synctex_result) { + g_free (view->synctex_result); + view->synctex_result = NULL; + gtk_widget_queue_draw (widget); + } + if (EV_IS_SELECTION (view->document)) start_selection_for_event (view, event); } @@ -3981,6 +4020,30 @@ highlight_find_results (EvView *view, int page) } static void +highlight_forward_search_results (EvView *view, int page) +{ + GdkWindow *bin_window; + GdkRectangle rect; + cairo_t *cr; + EvMapping *mapping = view->synctex_result; + + if (GPOINTER_TO_INT (mapping->data) != page) + return; + + bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (view)); + doc_rect_to_view_rect (view, page, &mapping->area, &rect); + + cr = gdk_cairo_create (bin_window); + cairo_set_source_rgb (cr, 1., 0., 0.); + cairo_rectangle (cr, + rect.x - view->scroll_x, + rect.y - view->scroll_y, + rect.width, rect.height); + cairo_stroke (cr); + cairo_destroy (cr); +} + +static void ev_view_loading_window_move (EvView *view) { GtkWidget *widget = GTK_WIDGET (view); @@ -4184,6 +4247,11 @@ ev_view_finalize (GObject *object) clear_selection (view); clear_link_selected (view); + if (view->synctex_result) { + g_free (view->synctex_result); + view->synctex_result = NULL; + } + if (view->image_dnd_info.image) g_object_unref (view->image_dnd_info.image); view->image_dnd_info.image = NULL; @@ -4362,6 +4430,14 @@ ev_view_class_init (EvViewClass *class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + signals[SIGNAL_SYNC_SOURCE] = g_signal_new ("sync-source", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvViewClass, sync_source), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); binding_set = gtk_binding_set_by_class (class); @@ -5274,6 +5350,34 @@ ev_view_find_cancel (EvView *view) view->find_pages = NULL; } +/*** Synctex ***/ +void +ev_view_highlight_forward_search (EvView *view, + EvSourceLink *link) +{ + EvMapping *mapping; + gint page; + GdkRectangle view_rect; + + if (!ev_document_has_synctex (view->document)) + return; + + mapping = ev_document_synctex_forward_search (view->document, link); + if (!mapping) + return; + + if (view->synctex_result) + g_free (view->synctex_result); + view->synctex_result = mapping; + + page = GPOINTER_TO_INT (mapping->data); + ev_document_model_set_page (view->model, page); + + doc_rect_to_view_rect (view, page, &mapping->area, &view_rect); + ensure_rectangle_is_visible (view, &view_rect); + gtk_widget_queue_draw (GTK_WIDGET (view)); +} + /*** Selections ***/ /* compute_new_selection_rect/text calculates the area currently selected by diff --git a/libview/ev-view.h b/libview/ev-view.h index 307793a..d4ee577 100644 --- a/libview/ev-view.h +++ b/libview/ev-view.h @@ -79,6 +79,10 @@ void ev_view_find_changed (EvView *view, gint page); void ev_view_find_cancel (EvView *view); +/* Synctex */ +void ev_view_highlight_forward_search (EvView *view, + EvSourceLink *link); + /* Cursor */ void ev_view_hide_cursor (EvView *view); void ev_view_show_cursor (EvView *view); -- cgit v0.9.1