gint page,
GdkRectangle *page_area,
GtkBorder *border,
- GdkRectangle *expose_area);
+ GdkRectangle *expose_area,
+ gboolean *page_ready);
static void draw_loading_text (EvView *view,
GdkRectangle *page_area,
GdkRectangle *expose_area);
factor = 1.0;
switch (view->pending_scroll) {
case SCROLL_TO_KEEP_POSITION:
+ case SCROLL_TO_FIND_LOCATION:
factor = (adjustment->value) / adjustment->upper;
break;
case SCROLL_TO_PAGE_POSITION:
*/
switch (view->pending_scroll) {
case SCROLL_TO_KEEP_POSITION:
+ case SCROLL_TO_FIND_LOCATION:
new_value = CLAMP (adjustment->upper * factor + 0.5, 0, adjustment->upper - adjustment->page_size);
gtk_adjustment_set_value (adjustment, (int)new_value);
break;
gint current_page;
gint best_current_page = -1;
- if (view->pending_scroll != SCROLL_TO_KEEP_POSITION)
- return;
-
/* Presentation trumps all other modes */
if (view->presentation) {
view->start_page = view->current_page;
best_current_page = MAX (best_current_page, view->start_page);
current_page = ev_page_cache_get_current_page (view->page_cache);
- if (current_page != best_current_page) {
+ if ((current_page != best_current_page) && (view->pending_scroll == SCROLL_TO_KEEP_POSITION)) {
view->current_page = best_current_page;
ev_page_cache_set_current_page (view->page_cache, best_current_page);
}
view->jump_to_find_result = FALSE;
- if (view->presentation) {
+ if (view->presentation || view->sizing_mode == EV_SIZING_BEST_FIT) {
switch (scroll) {
case EV_SCROLL_PAGE_BACKWARD:
case EV_SCROLL_STEP_BACKWARD:
GtkAdjustment *adjustment;
int value;
- view->pending_scroll = SCROLL_TO_KEEP_POSITION;
+ view->pending_scroll = SCROLL_TO_FIND_LOCATION;
adjustment = view->vadjustment;
widget->allocation.width + MARGIN);
gtk_adjustment_set_value (view->hadjustment, value);
}
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
/*** Geometry computations ***/
return FALSE;
}
+static gboolean
+get_doc_point_from_offset (EvView *view,
+ gint page,
+ gint x_offset,
+ gint y_offset,
+ gint *x_new,
+ gint *y_new)
+{
+ int width, height;
+ double x, y;
+
+ ev_page_cache_get_size (view->page_cache, page,
+ view->rotation,
+ 1.0,
+ &width, &height);
+
+ x_offset = x_offset / view->scale;
+ y_offset = y_offset / view->scale;
+
+ if (view->rotation == 0) {
+ x = x_offset;
+ y = y_offset;
+ } else if (view->rotation == 90) {
+ x = y_offset;
+ y = width - x_offset;
+ } else if (view->rotation == 180) {
+ x = width - x_offset;
+ y = height - y_offset;
+ } else if (view->rotation == 270) {
+ x = height - y_offset;
+ y = x_offset;
+ } else {
+ g_assert_not_reached ();
+ }
+
+ *x_new = x;
+ *y_new = y;
+
+ return TRUE;
+}
+
/*** Hyperref ***/
static EvLink *
ev_view_get_link_at_location (EvView *view,
{
gint page = -1;
gint x_offset = 0, y_offset = 0;
+ gint x_new = 0, y_new = 0;
GList *link_mapping;
x += view->scroll_x;
if (page == -1)
return NULL;
+
+ if (get_doc_point_from_offset (view, page, x_offset,
+ y_offset, &x_new, &y_new) == FALSE)
+ return NULL;
+
link_mapping = ev_pixbuf_cache_get_link_mapping (view->pixbuf_cache, page);
if (link_mapping)
- return ev_link_mapping_find (link_mapping, x_offset / view->scale, y_offset / view->scale);
+ return ev_link_mapping_find (link_mapping, x_new, y_new);
else
return NULL;
}
goto_fitr_dest (EvView *view, EvLinkDest *dest)
{
EvPoint doc_point;
- int page;
double zoom;
zoom = zoom_for_size_best_fit (ev_link_dest_get_right (dest) - ev_link_dest_get_left (dest),
- ev_link_dest_get_top (dest) - ev_link_dest_get_bottom (dest),
+ ev_link_dest_get_bottom (dest) - ev_link_dest_get_top (dest),
ev_view_get_width (view),
ev_view_get_height (view), 0, 0);
ev_view_set_sizing_mode (view, EV_SIZING_FREE);
ev_view_set_zoom (view, zoom, FALSE);
- page = ev_link_dest_get_page (dest);
doc_point.x = ev_link_dest_get_left (dest);
doc_point.y = ev_link_dest_get_top (dest);
- view->current_page = page;
+ view->current_page = ev_link_dest_get_page (dest);
view->pending_point = doc_point;
view->pending_scroll = SCROLL_TO_PAGE_POSITION;
ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height);
doc_point.x = 0;
- doc_point.y = doc_height - ev_link_dest_get_top (dest);
+ doc_point.y = ev_link_dest_get_top (dest);
zoom = zoom_for_size_fit_width (doc_width, ev_link_dest_get_top (dest),
ev_view_get_width (view),
ev_view_get_height (view), 0);
- ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ ev_view_set_sizing_mode (view, EV_SIZING_FIT_WIDTH);
ev_view_set_zoom (view, zoom, FALSE);
view->current_page = page;
zoom = zoom_for_size_best_fit (doc_width, doc_height, ev_view_get_width (view),
ev_view_get_height (view), 0, 0);
- ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ ev_view_set_sizing_mode (view, EV_SIZING_BEST_FIT);
ev_view_set_zoom (view, zoom, FALSE);
view->current_page = page;
goto_xyz_dest (EvView *view, EvLinkDest *dest)
{
EvPoint doc_point;
- int height, page;
+ gint page;
double zoom;
zoom = ev_link_dest_get_zoom (dest);
page = ev_link_dest_get_page (dest);
- ev_page_cache_get_size (view->page_cache, page, 0, 1.0, NULL, &height);
- if (zoom != 0) {
+ if (zoom > 1) {
ev_view_set_sizing_mode (view, EV_SIZING_FREE);
ev_view_set_zoom (view, zoom, FALSE);
}
doc_point.x = ev_link_dest_get_left (dest);
- doc_point.y = height - ev_link_dest_get_top (dest);
+ doc_point.y = ev_link_dest_get_top (dest);
view->current_page = page;
view->pending_point = doc_point;
case EV_LINK_DEST_TYPE_XYZ:
goto_xyz_dest (view, dest);
break;
+ case EV_LINK_DEST_TYPE_PAGE_LABEL:
+ ev_page_cache_set_page_label (view->page_cache, ev_link_dest_get_page_label (dest));
+ break;
default:
g_assert_not_reached ();
}
const gchar *name = ev_link_action_get_name (action);
if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
- return g_strdup (_("Got to fisrt page"));
+ return g_strdup (_("Go to first page"));
} else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
- return g_strdup (_("Got to previuos page"));
+ return g_strdup (_("Go to previous page"));
} else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
- return g_strdup (_("Got to next page"));
+ return g_strdup (_("Go to next page"));
} else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
- return g_strdup (_("Got to last page"));
+ return g_strdup (_("Go to last page"));
} else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
- return g_strdup (_("Got to page"));
+ return g_strdup (_("Go to page"));
} else if (g_ascii_strcasecmp (name, "Find") == 0) {
return g_strdup (_("Find"));
}
break;
case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
if (title) {
- msg = g_strdup_printf (_("Go to %s on file %s"), title,
+ msg = g_strdup_printf (_("Go to %s on file ā%sā"), title,
ev_link_action_get_filename (action));
} else {
- msg = g_strdup_printf (_("Go to file %s"),
+ msg = g_strdup_printf (_("Go to file ā%sā"),
ev_link_action_get_filename (action));
}
view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
- view->pending_scroll = SCROLL_TO_KEEP_POSITION;
- view->pending_resize = FALSE;
-
if (view->document)
view_update_range_and_current_page (view);
+ view->pending_scroll = SCROLL_TO_KEEP_POSITION;
+ view->pending_resize = FALSE;
+
GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
}
return NULL;
}
+static void
+draw_end_presentation_page (EvView *view,
+ GdkRectangle *page_area)
+{
+ PangoLayout *layout;
+ PangoFontDescription *font_desc;
+ gchar *markup;
+ const gchar *text = _("End of presentation, press Escape to exit.");
+
+ if (view->presentation_state != EV_PRESENTATION_END)
+ return;
+
+ layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL);
+ markup = g_strdup_printf ("<span foreground=\"white\">%s</span>", text);
+ pango_layout_set_markup (layout, markup, -1);
+ g_free (markup);
+
+ font_desc = pango_font_description_new ();
+ pango_font_description_set_size (font_desc, 16 * PANGO_SCALE);
+ pango_layout_set_font_description (layout, font_desc);
+
+ gtk_paint_layout (GTK_WIDGET (view)->style,
+ GTK_WIDGET (view)->window,
+ GTK_WIDGET_STATE (view),
+ FALSE,
+ page_area,
+ GTK_WIDGET (view),
+ NULL,
+ page_area->x + 15,
+ page_area->y + 15,
+ layout);
+
+ pango_font_description_free (font_desc);
+ g_object_unref (layout);
+}
+
static gboolean
ev_view_expose_event (GtkWidget *widget,
GdkEventExpose *event)
EvView *view = EV_VIEW (widget);
int i;
+ if (view->presentation) {
+ switch (view->presentation_state) {
+ case EV_PRESENTATION_END: {
+ GdkRectangle area = {0};
+
+ area.width = widget->allocation.width;
+ area.height = widget->allocation.height;
+
+ draw_end_presentation_page (view, &area);
+ }
+ return FALSE;
+ case EV_PRESENTATION_BLACK:
+ case EV_PRESENTATION_WHITE:
+ return FALSE;
+ case EV_PRESENTATION_NORMAL:
+ default:
+ break;
+ }
+ }
+
if (view->loading) {
GdkRectangle area = {0};
for (i = view->start_page; i <= view->end_page; i++) {
GdkRectangle page_area;
GtkBorder border;
+ gboolean page_ready = TRUE;
if (!get_page_extents (view, i, &page_area, &border))
continue;
page_area.x -= view->scroll_x;
page_area.y -= view->scroll_y;
- draw_one_page (view, i, &page_area, &border, &(event->area));
+ draw_one_page (view, i, &page_area, &border, &(event->area), &page_ready);
- if (EV_IS_DOCUMENT_FIND (view->document))
+ if (page_ready && EV_IS_DOCUMENT_FIND (view->document))
highlight_find_results (view, i);
}
return TRUE;
}
- /* For the Evince 0.4.x release, we limit links to un-rotated documents
- * only.
- */
- } else if (view->pressed_button <= 0 &&
- view->rotation == 0) {
+ } else if (view->pressed_button <= 0) {
handle_link_over_xy (view, x, y);
return TRUE;
}
ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
}
- if (view->document) {
+ if (view->document && view->pressed_button == 1) {
link = ev_view_get_link_at_location (view, event->x, event->y);
} else {
link = NULL;
return FALSE;
}
+static gboolean
+ev_view_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ EvView *view = EV_VIEW (widget);
+ EvPresentationState current;
+
+ if (!view->presentation ||
+ view->presentation_state == EV_PRESENTATION_END)
+ return FALSE;
+
+ current = view->presentation_state;
+
+ switch (event->keyval) {
+ case GDK_b:
+ case GDK_B:
+ view->presentation_state =
+ (view->presentation_state == EV_PRESENTATION_BLACK) ?
+ EV_PRESENTATION_NORMAL : EV_PRESENTATION_BLACK;
+ break;
+ case GDK_w:
+ case GDK_W:
+ view->presentation_state =
+ (view->presentation_state == EV_PRESENTATION_WHITE) ?
+ EV_PRESENTATION_NORMAL : EV_PRESENTATION_WHITE;
+ break;
+ default:
+ if (view->presentation_state == EV_PRESENTATION_BLACK ||
+ view->presentation_state == EV_PRESENTATION_WHITE) {
+ view->presentation_state = EV_PRESENTATION_NORMAL;
+ }
+ }
+
+ if (current == view->presentation_state)
+ return FALSE;
+
+ switch (view->presentation_state) {
+ case EV_PRESENTATION_NORMAL:
+ case EV_PRESENTATION_BLACK:
+ gdk_window_set_background (widget->window,
+ &widget->style->black);
+ break;
+ case EV_PRESENTATION_WHITE:
+ gdk_window_set_background (widget->window,
+ &widget->style->white);
+ break;
+ default:
+ return FALSE;
+ }
+
+ gtk_widget_queue_draw (widget);
+ return TRUE;
+}
+
static gint
ev_view_focus_in (GtkWidget *widget,
GdkEventFocus *event)
double real_scale;
int target_width;
+ /* Don't annoy users with loading messages during presentations.
+ * FIXME: Temporary "workaround" for
+ * http://bugzilla.gnome.org/show_bug.cgi?id=320352 */
+ if (view->presentation)
+ return;
+
const char *loading_text = _("Loading...");
layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text);
gint page,
GdkRectangle *page_area,
GtkBorder *border,
- GdkRectangle *expose_area)
+ GdkRectangle *expose_area,
+ gboolean *page_ready)
{
gint width, height;
GdkPixbuf *current_pixbuf;
gint current_page;
g_assert (view->document);
-
+
if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
return;
real_page_area.y += border->top;
real_page_area.width -= (border->left + border->right);
real_page_area.height -= (border->top + border->bottom);
+ *page_ready = TRUE;
ev_document_misc_paint_one_page (GTK_WIDGET(view)->window,
GTK_WIDGET (view),
draw_loading_text (view,
&real_page_area,
expose_area);
+ *page_ready = FALSE;
}
if (scaled_selection) {
if (view->link_tooltip) {
gtk_widget_destroy (view->link_tooltip);
+ view->link_tooltip = NULL;
}
if (view->selection_scroll_id) {
widget_class->button_press_event = ev_view_button_press_event;
widget_class->motion_notify_event = ev_view_motion_notify_event;
widget_class->button_release_event = ev_view_button_release_event;
+ widget_class->key_press_event = ev_view_key_press_event;
widget_class->focus_in_event = ev_view_focus_in;
widget_class->focus_out_event = ev_view_focus_out;
widget_class->get_accessible = ev_view_get_accessible;
view->continuous = TRUE;
view->dual_page = FALSE;
view->presentation = FALSE;
+ view->presentation_state = EV_PRESENTATION_NORMAL;
view->fullscreen = FALSE;
view->sizing_mode = EV_SIZING_FIT_WIDTH;
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
if (view->presentation == presentation)
return;
+ if (!presentation)
+ view->presentation_state = EV_PRESENTATION_NORMAL;
+
view->presentation = presentation;
view->pending_scroll = SCROLL_TO_PAGE_POSITION;
gtk_widget_queue_resize (GTK_WIDGET (view));
>K_WIDGET (view)->style->mid [GTK_STATE_NORMAL]);
}
-
g_object_notify (G_OBJECT (view), "presentation");
}
ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
}
+static void
+ev_view_reset_presentation_state (EvView *view)
+{
+ if (!view->presentation ||
+ view->presentation_state == EV_PRESENTATION_NORMAL)
+ return;
+
+ view->presentation_state = EV_PRESENTATION_NORMAL;
+ gdk_window_set_background (GTK_WIDGET (view)->window,
+ >K_WIDGET (view)->style->black);
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
gboolean
ev_view_next_page (EvView *view)
{
- int page;
+ int page, n_pages;
g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
if (!view->page_cache)
return FALSE;
+ ev_view_reset_presentation_state (view);
+
page = ev_page_cache_get_current_page (view->page_cache);
+ n_pages = ev_page_cache_get_n_pages (view->page_cache);
if (view->dual_page && !view->presentation)
page = page + 2;
else
page = page + 1;
- if (page < ev_page_cache_get_n_pages (view->page_cache)) {
+ if (page < n_pages) {
ev_page_cache_set_current_page (view->page_cache, page);
return TRUE;
- } else if (ev_view_get_dual_page (view) && page == ev_page_cache_get_n_pages (view->page_cache)) {
+ } else if (view->presentation && page == n_pages) {
+ view->presentation_state = EV_PRESENTATION_END;
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ return TRUE;
+ } else if (view->dual_page && page == n_pages) {
ev_page_cache_set_current_page (view->page_cache, page - 1);
return TRUE;
} else {
if (!view->page_cache)
return FALSE;
+ if (view->presentation &&
+ view->presentation_state == EV_PRESENTATION_END) {
+ ev_view_reset_presentation_state (view);
+ return TRUE;
+ }
+
+ ev_view_reset_presentation_state (view);
+
page = ev_page_cache_get_current_page (view->page_cache);
if (view->dual_page && !view->presentation)