[evince] [libview] Add support for synctex in EvView



commit 065ca13c80f87bdf729f906d0c6c47b0b55a4fb1
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Mon Jun 28 11:43:06 2010 +0200

    [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

 libview/ev-view-private.h |    5 ++
 libview/ev-view.c         |  108 ++++++++++++++++++++++++++++++++++++++++++++-
 libview/ev-view.h         |    4 ++
 3 files changed, 115 insertions(+), 2 deletions(-)
---
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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]