#include "ev-view.h"
#include "ev-view-private.h"
#include "ev-utils.h"
-#include "ev-selection.h"
#include "ev-document-links.h"
#include "ev-document-images.h"
#include "ev-document-find.h"
#include "ev-job-queue.h"
#include "ev-page-cache.h"
#include "ev-pixbuf-cache.h"
+#if !GTK_CHECK_VERSION (2, 11, 7)
#include "ev-tooltip.h"
+#endif
#include "ev-application.h"
#define EV_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
int page);
static void draw_one_page (EvView *view,
gint page,
+ cairo_t *cr,
GdkRectangle *page_area,
GtkBorder *border,
GdkRectangle *expose_area,
/*** Selection ***/
static void compute_selections (EvView *view,
+ EvSelectionStyle style,
GdkPoint *start,
GdkPoint *stop);
static void clear_selection (EvView *view);
}
view->end_page = i;
- } else if (found) {
+ } else if (found && view->current_page <= view->end_page) {
break;
}
}
if (view->cursor == EV_VIEW_CURSOR_HIDDEN)
return;
+
+ if (view->drag_info.in_drag) {
+ if (view->cursor != EV_VIEW_CURSOR_DRAG)
+ ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG);
+ return;
+ }
link = ev_view_get_link_at_location (view, x, y);
-
+
+#if !GTK_CHECK_VERSION (2, 11, 7)
if (view->link_tooltip == NULL) {
view->link_tooltip = ev_tooltip_new (GTK_WIDGET (view));
}
view->hovered_link = link;
ev_tooltip_deactivate (EV_TOOLTIP (view->link_tooltip));
}
+#endif
if (link) {
+#if GTK_CHECK_VERSION (2, 11, 7)
+ g_object_set (view, "has-tooltip", TRUE, NULL);
+#else
char *msg = tip_from_link (view, link);
if (msg && g_utf8_validate (msg, -1, NULL)) {
ev_tooltip_activate (tooltip);
}
g_free (msg);
-
+#endif
ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK);
} else if ((field = ev_view_get_form_field_at_location (view, x, y))) {
if (field->is_read_only) {
ev_view_expose_event (GtkWidget *widget,
GdkEventExpose *event)
{
- EvView *view = EV_VIEW (widget);
- int i;
+ EvView *view = EV_VIEW (widget);
+ cairo_t *cr;
+ gint i;
if (view->presentation) {
switch (view->presentation_state) {
if (view->document == NULL)
return FALSE;
+ cr = gdk_cairo_create (view->layout.bin_window);
+
for (i = view->start_page; i <= view->end_page; i++) {
GdkRectangle page_area;
GtkBorder border;
page_area.x -= view->scroll_x;
page_area.y -= view->scroll_y;
- draw_one_page (view, i, &page_area, &border, &(event->area), &page_ready);
+ draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready);
- if (page_ready && EV_IS_DOCUMENT_FIND (view->document))
+ if (page_ready && EV_IS_DOCUMENT_FIND (view->document) && view->highlight_find_results)
highlight_find_results (view, i);
}
+ cairo_destroy (cr);
+
if (GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event)
(* GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event) (widget, event);
return ev_view_do_popup_menu (EV_VIEW (widget), x, y);
}
+#if GTK_CHECK_VERSION (2, 11, 7)
+static void
+get_link_area (EvView *view,
+ gint x,
+ gint y,
+ EvLink *link,
+ GdkRectangle *area)
+{
+ EvRectangle ev_rect;
+ GList *link_mapping;
+ gint page;
+ gint x_offset = 0, y_offset = 0;
+
+ x += view->scroll_x;
+ y += view->scroll_y;
+
+ find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
+
+ link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page);
+ ev_link_mapping_get_area (link_mapping, link, &ev_rect);
+
+ doc_rect_to_view_rect (view, page, &ev_rect, area);
+ area->y -= view->scroll_y ;
+}
+
+static gboolean
+ev_view_query_tooltip (GtkWidget *widget,
+ gint x,
+ gint y,
+ gboolean keyboard_tip,
+ GtkTooltip *tooltip)
+{
+ EvView *view = EV_VIEW (widget);
+ EvLink *link;
+ gchar *text;
+
+ link = ev_view_get_link_at_location (view, x, y);
+ if (!link)
+ return FALSE;
+
+ text = tip_from_link (view, link);
+ if (text && g_utf8_validate (text, -1, NULL)) {
+ GdkRectangle link_area;
+
+ get_link_area (view, x, y, link, &link_area);
+ gtk_tooltip_set_text (tooltip, text);
+ gtk_tooltip_set_tip_area (tooltip, &link_area);
+ }
+ g_free (text);
+
+ return TRUE;
+}
+#endif /* GTK_CHECK_VERSION (2, 11, 7) */
+
+static void
+start_selection_for_event (EvView *view,
+ GdkEventButton *event)
+{
+ EvSelectionStyle style;
+
+ clear_selection (view);
+
+ view->selection_info.start.x = event->x + view->scroll_x;
+ view->selection_info.start.y = event->y + view->scroll_y;
+
+ switch (event->type) {
+ case GDK_2BUTTON_PRESS:
+ style = EV_SELECTION_STYLE_WORD;
+ break;
+ case GDK_3BUTTON_PRESS:
+ style = EV_SELECTION_STYLE_LINE;
+ break;
+ default:
+ style = EV_SELECTION_STYLE_GLYPH;
+ break;
+ }
+
+ view->selection_info.style = style;
+}
+
static gboolean
ev_view_button_press_event (GtkWidget *widget,
GdkEventButton *event)
EvImage *image;
EvFormField *field;
- if (view->selection_info.selections) {
- if (location_in_selected_text (view,
+ if (EV_IS_SELECTION (view->document) && view->selection_info.selections) {
+ if (event->type == GDK_3BUTTON_PRESS) {
+ start_selection_for_event (view, event);
+ } else if (location_in_selected_text (view,
event->x + view->scroll_x,
event->y + view->scroll_y)) {
view->selection_info.in_drag = TRUE;
} else {
- clear_selection (view);
-
- view->selection_info.start.x = event->x + view->scroll_x;
- view->selection_info.start.y = event->y + view->scroll_y;
+ start_selection_for_event (view, event);
}
-
+
gtk_widget_queue_draw (widget);
} else if (!location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y) &&
(image = ev_view_get_image_at_location (view, event->x, event->y))) {
ev_view_handle_form_field (view, field, event->x, event->y);
} else {
ev_view_remove_all (view);
- view->selection_info.start.x = event->x + view->scroll_x;
- view->selection_info.start.y = event->y + view->scroll_y;
+
+ if (EV_IS_SELECTION (view->document))
+ start_selection_for_event (view, event);
}
}
return TRUE;
switch (info) {
case TARGET_DND_TEXT:
- if (view->selection_info.selections &&
- ev_document_can_get_text (view->document)) {
+ if (EV_IS_SELECTION (view->document) &&
+ view->selection_info.selections) {
gchar *text;
text = get_selected_text (view);
-
gtk_selection_data_set_text (selection_data,
text,
strlen (text));
-
g_free (text);
}
break;
static gboolean
selection_update_idle_cb (EvView *view)
{
- compute_selections (view, &view->selection_info.start, &view->motion);
+ compute_selections (view,
+ view->selection_info.style,
+ &view->selection_info.start,
+ &view->motion);
view->selection_update_id = 0;
return FALSE;
}
GdkEventButton *event)
{
EvView *view = EV_VIEW (widget);
- EvLink *link;
+ EvLink *link = NULL;
+
+ view->drag_info.in_drag = FALSE;
+ view->image_dnd_info.in_drag = FALSE;
if (view->pressed_button == 2) {
- ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
+ ev_view_handle_cursor_over_xy (view, event->x, event->y);
}
if (view->document && view->pressed_button != 3) {
link = ev_view_get_link_at_location (view, event->x, event->y);
- } else {
- link = NULL;
}
view->pressed_button = -1;
- view->drag_info.in_drag = FALSE;
- view->image_dnd_info.in_drag = FALSE;
if (view->selection_scroll_id) {
g_source_remove (view->selection_scroll_id);
view->selection_update_id = 0;
}
+ if (!view->selection_info.in_selection &&
+ view->selection_info.style != EV_SELECTION_STYLE_GLYPH) {
+ compute_selections (view,
+ view->selection_info.style,
+ &(view->selection_info.start),
+ &(view->selection_info.start));
+ }
+
if (view->selection_info.selections) {
ev_view_update_primary_selection (view);
ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
{
EvView *view = EV_VIEW (widget);
-
- if (view->cursor == EV_VIEW_CURSOR_LINK ||
- view->cursor == EV_VIEW_CURSOR_IBEAM)
+
+ if (view->cursor != EV_VIEW_CURSOR_NORMAL)
ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
+#if !GTK_CHECK_VERSION (2, 11, 7)
if (view->link_tooltip) {
view->hovered_link = NULL;
ev_tooltip_deactivate (EV_TOOLTIP (view->link_tooltip));
}
-
+#endif
+
return FALSE;
}
static void
draw_one_page (EvView *view,
gint page,
+ cairo_t *cr,
GdkRectangle *page_area,
GtkBorder *border,
GdkRectangle *expose_area,
cairo_surface_t *page_surface = NULL;
gint selection_width, selection_height;
cairo_surface_t *selection_surface = NULL;
- cairo_t *cr = NULL;
page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
view->scale,
&width, &height);
- cr = gdk_cairo_create (view->layout.bin_window);
-
- cairo_save (cr);
-
page_width = cairo_image_surface_get_width (page_surface);
page_height = cairo_image_surface_get_height (page_surface);
-
- cairo_rectangle (cr, overlap.x, overlap.y, overlap.width, overlap.height);
- cairo_clip (cr);
-
+
+ cairo_save (cr);
cairo_translate (cr, overlap.x, overlap.y);
if (width != page_width || height != page_height) {
cairo_surface_set_device_offset (page_surface,
overlap.x - real_page_area.x,
overlap.y - real_page_area.y);
-
cairo_set_source_surface (cr, page_surface, 0, 0);
cairo_paint (cr);
-
cairo_restore (cr);
/* Get the selection pixbuf iff we have something to draw */
}
if (!selection_surface) {
- cairo_destroy (cr);
return;
}
selection_width = cairo_image_surface_get_width (selection_surface);
selection_height = cairo_image_surface_get_height (selection_surface);
- cairo_rectangle (cr, overlap.x, overlap.y, overlap.width, overlap.height);
- cairo_clip (cr);
-
+ cairo_save (cr);
cairo_translate (cr, overlap.x, overlap.y);
if (width != selection_width || height != selection_height) {
cairo_surface_set_device_offset (selection_surface,
overlap.x - real_page_area.x,
overlap.y - real_page_area.y);
-
cairo_set_source_surface (cr, selection_surface, 0, 0);
cairo_paint (cr);
- cairo_destroy (cr);
+ cairo_restore (cr);
}
}
view->pixbuf_cache = NULL;
}
+#if !GTK_CHECK_VERSION (2, 11, 7)
if (view->link_tooltip) {
gtk_widget_destroy (view->link_tooltip);
view->link_tooltip = NULL;
}
-
+#endif
if (view->goto_window) {
gtk_widget_destroy (view->goto_window);
view->goto_window = NULL;
widget_class->drag_motion = ev_view_drag_motion;
widget_class->drag_data_received = ev_view_drag_data_received;
widget_class->popup_menu = ev_view_popup_menu;
+#if GTK_CHECK_VERSION (2, 11, 7)
+ widget_class->query_tooltip = ev_view_query_tooltip;
+#endif
gtk_object_class->destroy = ev_view_destroy;
view->sizing_mode = EV_SIZING_FIT_WIDTH;
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
view->jump_to_find_result = TRUE;
+ view->highlight_find_results = FALSE;
gtk_layout_set_hadjustment (GTK_LAYOUT (view), NULL);
gtk_layout_set_vadjustment (GTK_LAYOUT (view), NULL);
duration = ev_document_transition_get_page_duration (EV_DOCUMENT_TRANSITION (view->document),
view->current_page);
- if (duration > 0)
- view->trans_timeout_id = g_timeout_add (duration * 1000,
- (GSourceFunc) transition_next_page,
- view);
+ if (duration > 0) {
+#if GLIB_CHECK_VERSION (2, 13, 0)
+ view->trans_timeout_id =
+ g_timeout_add_seconds (duration,
+ (GSourceFunc) transition_next_page,
+ view);
+#else
+ view->trans_timeout_id =
+ g_timeout_add (duration * 1000,
+ (GSourceFunc) transition_next_page,
+ view);
+#endif
+ }
}
void
view->jump_to_find_result = TRUE;
}
+void ev_view_set_highlight_search (EvView *view, gboolean value)
+{
+ view->highlight_find_results = value;
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
/*** Selections ***/
/* compute_new_selection_rect/text calculates the area currently selected by
}
static GList *
-compute_new_selection_text (EvView *view,
- GdkPoint *start,
- GdkPoint *stop)
+compute_new_selection_text (EvView *view,
+ EvSelectionStyle style,
+ GdkPoint *start,
+ GdkPoint *stop)
{
int n_pages, i, first, last;
GList *list = NULL;
selection = g_new0 (EvViewSelection, 1);
selection->page = i;
+ selection->style = style;
selection->rect.x1 = selection->rect.y1 = 0;
selection->rect.x2 = width;
selection->rect.y2 = height;
}
static void
-compute_selections (EvView *view,
- GdkPoint *start,
- GdkPoint *stop)
+compute_selections (EvView *view,
+ EvSelectionStyle style,
+ GdkPoint *start,
+ GdkPoint *stop)
{
GList *list;
if (view->selection_mode == EV_VIEW_SELECTION_RECTANGLE)
list = compute_new_selection_rect (view, start, stop);
else
- list = compute_new_selection_text (view, start, stop);
+ list = compute_new_selection_text (view, style, start, stop);
merge_selection_region (view, list);
}
g_object_notify (G_OBJECT (view), "has-selection");
}
-
void
ev_view_select_all (EvView *view)
{
+ GList *selections = NULL;
int n_pages, i;
/* Disable selection on rotated pages for the 0.4.0 series */
return;
clear_selection (view);
-
+
n_pages = ev_page_cache_get_n_pages (view->page_cache);
for (i = 0; i < n_pages; i++) {
int width, height;
selection = g_new0 (EvViewSelection, 1);
selection->page = i;
+ selection->style = EV_SELECTION_STYLE_GLYPH;
selection->rect.x1 = selection->rect.y1 = 0;
selection->rect.x2 = width;
selection->rect.y2 = height;
- view->selection_info.selections = g_list_append (view->selection_info.selections, selection);
+ selections = g_list_append (selections, selection);
}
- ev_pixbuf_cache_set_selection_list (view->pixbuf_cache, view->selection_info.selections);
- g_object_notify (G_OBJECT (view), "has-selection");
+ merge_selection_region (view, selections);
gtk_widget_queue_draw (GTK_WIDGET (view));
}
}
static char *
-get_selected_text (EvView *ev_view)
+get_selected_text (EvView *view)
{
GString *text;
GList *l;
gchar *normalized_text;
+ EvRenderContext *rc;
text = g_string_new (NULL);
+ rc = ev_render_context_new (view->rotation, 1, view->scale);
ev_document_doc_mutex_lock ();
- for (l = ev_view->selection_info.selections; l != NULL; l = l->next) {
+ for (l = view->selection_info.selections; l != NULL; l = l->next) {
EvViewSelection *selection = (EvViewSelection *)l->data;
- char *tmp;
+ gchar *tmp;
+
+ ev_render_context_set_page (rc, selection->page);
+ tmp = ev_selection_get_selected_text (EV_SELECTION (view->document),
+ rc, selection->style,
+ &(selection->rect));
- tmp = ev_document_get_text (ev_view->document,
- selection->page,
- &selection->rect);
g_string_append (text, tmp);
g_free (tmp);
}
ev_document_doc_mutex_unlock ();
+ g_object_unref (rc);
+
normalized_text = g_utf8_normalize (text->str, text->len, G_NORMALIZE_NFKC);
g_string_free (text, TRUE);
return normalized_text;
GtkClipboard *clipboard;
char *text;
- if (!ev_document_can_get_text (ev_view->document)) {
+ if (!EV_IS_SELECTION (ev_view->document))
return;
- }
text = get_selected_text (ev_view);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view),
EvView *ev_view = EV_VIEW (data);
char *text;
- if (!ev_document_can_get_text (ev_view->document)) {
+ if (!EV_IS_SELECTION (ev_view->document))
return;
- }
text = get_selected_text (ev_view);
if (text) {