#define SCROLL_TIME 150
/*** Scrolling ***/
-static void scroll_to_current_page (EvView *view,
- GtkOrientation orientation);
static void ev_view_set_scroll_adjustments (GtkLayout *layout,
GtkAdjustment *hadjustment,
GtkAdjustment *vadjustment);
gint *page,
gint *x_offset,
gint *y_offset);
-static gboolean doc_point_to_view_point (EvView *view,
+static void doc_point_to_view_point (EvView *view,
int page,
EvPoint *doc_point,
GdkPoint *view_point);
GdkRegion *region);
/*** Callbacks ***/
+static void ev_view_change_page (EvView *view,
+ gint new_page,
+ gboolean start_transition);
static void job_finished_cb (EvPixbufCache *pixbuf_cache,
GdkRegion *region,
EvView *view);
}
static void
-scroll_to_current_page (EvView *view, GtkOrientation orientation)
+scroll_to_point (EvView *view,
+ gdouble x,
+ gdouble y,
+ GtkOrientation orientation)
{
- GdkPoint view_point;
-
- if (view->document == NULL) {
- return;
- }
-
- doc_point_to_view_point (view, view->current_page, &view->pending_point, &view_point);
-
- if (orientation == GTK_ORIENTATION_VERTICAL) {
- view->pending_point.y = 0;
- } else {
- view->pending_point.x = 0;
- }
-
if (orientation == GTK_ORIENTATION_VERTICAL) {
if (view->continuous) {
gtk_adjustment_clamp_page (view->vadjustment,
- view_point.y - view->spacing / 2,
- view_point.y + view->vadjustment->page_size);
+ y - view->spacing / 2,
+ y + view->vadjustment->page_size);
} else {
gtk_adjustment_set_value (view->vadjustment,
- CLAMP (view_point.y,
+ CLAMP (y,
view->vadjustment->lower,
view->vadjustment->upper -
view->vadjustment->page_size));
}
} else {
if (view->dual_page) {
- gtk_adjustment_clamp_page (view->hadjustment,
- view_point.x,
- view_point.x + view->hadjustment->page_size);
+ gtk_adjustment_clamp_page (view->hadjustment, x,
+ x + view->hadjustment->page_size);
} else {
gtk_adjustment_set_value (view->hadjustment,
- CLAMP (view_point.x,
+ CLAMP (x,
view->hadjustment->lower,
view->hadjustment->upper -
view->hadjustment->page_size));
}
}
+static void
+ev_view_scroll_to_page_position (EvView *view, GtkOrientation orientation)
+{
+ gdouble x, y;
+
+ if (!view->document)
+ return;
+
+ if ((orientation == GTK_ORIENTATION_VERTICAL && view->pending_point.y == 0) ||
+ (orientation == GTK_ORIENTATION_HORIZONTAL && view->pending_point.x == 0)) {
+ GdkRectangle page_area;
+ GtkBorder border;
+
+ get_page_extents (view, view->current_page, &page_area, &border);
+ x = page_area.x;
+ y = page_area.y;
+ } else {
+ GdkPoint view_point;
+
+ doc_point_to_view_point (view, view->current_page,
+ &view->pending_point, &view_point);
+ x = view_point.x;
+ y = view_point.y;
+ }
+
+ scroll_to_point (view, x, y, orientation);
+}
+
static void
view_set_adjustment_values (EvView *view,
GtkOrientation orientation)
gtk_adjustment_set_value (adjustment, (int)new_value);
break;
case SCROLL_TO_PAGE_POSITION:
- scroll_to_current_page (view, orientation);
+ ev_view_scroll_to_page_position (view, orientation);
break;
case SCROLL_TO_CENTER:
new_value = CLAMP (adjustment->upper * factor - adjustment->page_size * 0.5 + 0.5,
G_TYPE_BOOLEAN, horizontal);
}
+static gdouble
+compute_scroll_increment (EvView *view,
+ GtkScrollType scroll)
+{
+ GtkWidget *widget = GTK_WIDGET (view);
+ GtkAdjustment *adjustment = view->vadjustment;
+ GdkRegion *text_region, *region;
+ gint page;
+ GdkRectangle rect;
+ EvRectangle doc_rect;
+ GdkRectangle page_area;
+ GtkBorder border;
+ GdkRectangle *recs;
+ gint n_recs;
+ gdouble fraction = 1.0;
+
+ if (scroll != GTK_SCROLL_PAGE_BACKWARD && scroll != GTK_SCROLL_PAGE_FORWARD)
+ return adjustment->page_size;
+
+ page = scroll == GTK_SCROLL_PAGE_BACKWARD ? view->start_page : view->end_page;
+
+ text_region = ev_pixbuf_cache_get_text_mapping (view->pixbuf_cache, page);
+ if (!text_region || gdk_region_empty (text_region))
+ return adjustment->page_size;
+
+ get_page_extents (view, page, &page_area, &border);
+ rect.x = page_area.x + view->scroll_x;
+ rect.y = view->scroll_y + (scroll == GTK_SCROLL_PAGE_BACKWARD ? 5 : widget->allocation.height - 5);
+ rect.width = page_area.width;
+ rect.height = 1;
+ view_rect_to_doc_rect (view, &rect, &page_area, &doc_rect);
+
+ /* Convert the doc rectangle into a GdkRectangle */
+ rect.x = doc_rect.x1;
+ rect.y = doc_rect.y1;
+ rect.width = doc_rect.x2 - doc_rect.x1;
+ rect.height = MAX (1, doc_rect.y2 - doc_rect.y1);
+ region = gdk_region_rectangle (&rect);
+
+ gdk_region_intersect (region, text_region);
+ gdk_region_get_rectangles (region, &recs, &n_recs);
+ gdk_region_destroy (region);
+ if (n_recs > 0) {
+ EvRenderContext *rc;
+ EvPage *ev_page;
+
+ ev_page = ev_document_get_page (view->document, page);
+ rc = ev_render_context_new (ev_page, view->rotation, view->scale);
+ g_object_unref (ev_page);
+ /* Get the selection region to know the height of the line */
+ doc_rect.x1 = doc_rect.x2 = recs[0].x + 0.5;
+ doc_rect.y1 = doc_rect.y2 = recs[0].y + 0.5;
+
+ ev_document_doc_mutex_lock ();
+ region = ev_selection_get_selection_region (EV_SELECTION (view->document),
+ rc, EV_SELECTION_STYLE_LINE,
+ &doc_rect);
+ ev_document_doc_mutex_unlock ();
+
+ g_object_unref (rc);
+ g_free (recs);
+ gdk_region_get_rectangles (region, &recs, &n_recs);
+ gdk_region_destroy (region);
+ if (n_recs > 0) {
+ fraction = 1 - (recs[0].height / adjustment->page_size);
+ }
+ g_free (recs);
+ }
+
+ return adjustment->page_size * fraction;
+
+}
+
void
ev_view_scroll (EvView *view,
GtkScrollType scroll,
/* Assign values for increment and vertical adjustment */
adjustment = horizontal ? view->hadjustment : view->vadjustment;
- increment = adjustment->page_size * 0.75;
value = adjustment->value;
/* Assign boolean for first and last page */
ev_view_previous_page (view);
/* Jump to the top */
} else {
+ increment = compute_scroll_increment (view, GTK_SCROLL_PAGE_BACKWARD);
value = MAX (value - increment, adjustment->lower);
}
break;
ev_view_next_page (view);
/* Jump to the bottom */
} else {
+ increment = compute_scroll_increment (view, GTK_SCROLL_PAGE_FORWARD);
value = MIN (value + increment, adjustment->upper - adjustment->page_size);
}
break;
doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale;
}
-static gboolean
+static void
doc_point_to_view_point (EvView *view,
int page,
EvPoint *doc_point,
get_page_extents (view, page, &page_area, &border);
- view_x = x * view->scale;
- view_y = y * view->scale;
+ view_x = CLAMP (x * view->scale, 0, page_area.width);
+ view_y = CLAMP (y * view->scale, 0, page_area.height);
view_point->x = view_x + page_area.x;
view_point->y = view_y + page_area.y;
-
- return (view_x > 0 && view_x <= page_area.width &&
- view_y > 0 && view_y <= page_area.height);
}
static void
doc_point.x = change_left ? left : 0;
doc_point.y = change_top ? top : 0;
-
- view->current_page = ev_link_dest_get_page (dest);
- if (change_left || change_top)
- view->pending_point = doc_point;
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+ view->pending_point = doc_point;
- gtk_widget_queue_resize (GTK_WIDGET (view));
+ ev_view_change_page (view, ev_link_dest_get_page (dest), TRUE);
}
static void
ev_document_model_set_sizing_mode (view->model, EV_SIZING_FREE);
ev_document_model_set_scale (view->model, zoom);
- view->current_page = page;
- if (change_left)
- view->pending_point = doc_point;
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+ view->pending_point = doc_point;
- gtk_widget_queue_resize (GTK_WIDGET (view));
+ ev_view_change_page (view, page, TRUE);
}
static void
ev_document_model_set_sizing_mode (view->model, EV_SIZING_FIT_WIDTH);
ev_document_model_set_scale (view->model, zoom);
- view->current_page = page;
- if (change_top)
- view->pending_point = doc_point;
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+ view->pending_point = doc_point;
- gtk_widget_queue_resize (GTK_WIDGET (view));
+ ev_view_change_page (view, page, TRUE);
}
static void
ev_document_model_set_sizing_mode (view->model, EV_SIZING_BEST_FIT);
ev_document_model_set_scale (view->model, zoom);
- view->current_page = page;
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
-
- gtk_widget_queue_resize (GTK_WIDGET (view));
+ ev_view_change_page (view, page, TRUE);
}
static void
doc_point.x = change_left ? left : 0;
doc_point.y = change_top ? top : 0;
+ view->pending_point = doc_point;
- view->current_page = page;
- if (change_left || change_top)
- view->pending_point = doc_point;
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
-
- gtk_widget_queue_resize (GTK_WIDGET (view));
+ ev_view_change_page (view, page, TRUE);
}
static void
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
view->pending_resize = FALSE;
+ view->pending_point.x = 0;
+ view->pending_point.y = 0;
children = gtk_container_get_children (GTK_CONTAINER (widget));
for (l = children; l && l->data; l = g_list_next (l)) {
gdk_window_set_background (view->layout.bin_window, &widget->style->black);
else
gdk_window_set_background (view->layout.bin_window, &widget->style->mid [GTK_STATE_NORMAL]);
+
+ on_adjustment_value_changed (NULL, view);
}
static gboolean
if (view->pixbuf_cache) {
ev_pixbuf_cache_clear (view->pixbuf_cache);
+ if (!ev_document_is_page_size_uniform (view->document))
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
gtk_widget_queue_resize (GTK_WIDGET (view));
}
+ ev_view_remove_all (view);
+
if (rotation != 0)
clear_selection (view);
}
gtk_widget_queue_resize (GTK_WIDGET (view));
}
+static void
+ev_view_continuous_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvView *view)
+{
+ gboolean continuous = ev_document_model_get_continuous (model);
+
+ ev_view_set_continuous (view, continuous);
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+ gtk_widget_queue_resize (GTK_WIDGET (view));
+}
+
+static void
+ev_view_dual_page_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvView *view)
+{
+ gboolean dual_page = ev_document_model_get_dual_page (model);
+
+ ev_view_set_dual_page (view, dual_page);
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+ /* FIXME: if we're keeping the pixbuf cache around, we should extend the
+ * preload_cache_size to be 2 if dual_page is set.
+ */
+ gtk_widget_queue_resize (GTK_WIDGET (view));
+}
+
+static void
+ev_view_fullscreen_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvView *view)
+{
+ gboolean fullscreen = ev_document_model_get_fullscreen (model);
+
+ ev_view_set_fullscreen (view, fullscreen);
+ gtk_widget_queue_resize (GTK_WIDGET (view));
+}
+
void
ev_view_set_model (EvView *view,
EvDocumentModel *model)
g_signal_connect (view->model, "notify::scale",
G_CALLBACK (ev_view_scale_changed_cb),
view);
+ g_signal_connect (view->model, "notify::continuous",
+ G_CALLBACK (ev_view_continuous_changed_cb),
+ view);
+ g_signal_connect (view->model, "notify::dual-page",
+ G_CALLBACK (ev_view_dual_page_changed_cb),
+ view);
+ g_signal_connect (view->model, "notify::fullscreen",
+ G_CALLBACK (ev_view_fullscreen_changed_cb),
+ view);
g_signal_connect (view->model, "page-changed",
G_CALLBACK (ev_view_page_changed_cb),
view);
return view->scale;
}
-void
-ev_view_set_screen_dpi (EvView *view,
- gdouble dpi)
-{
- g_return_if_fail (EV_IS_VIEW (view));
- g_return_if_fail (dpi > 0);
-
- view->dpi = dpi;
-}
-
gboolean
ev_view_get_continuous (EvView *view)
{
{
g_return_if_fail (EV_IS_VIEW (view));
- continuous = continuous != FALSE;
-
- if (view->continuous != continuous) {
- view->continuous = continuous;
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
- gtk_widget_queue_resize (GTK_WIDGET (view));
- }
+ view->continuous = continuous;
g_object_notify (G_OBJECT (view), "continuous");
}
{
g_return_if_fail (EV_IS_VIEW (view));
- dual_page = dual_page != FALSE;
-
- if (view->dual_page == dual_page)
- return;
-
- view->pending_scroll = SCROLL_TO_PAGE_POSITION;
view->dual_page = dual_page;
- /* FIXME: if we're keeping the pixbuf cache around, we should extend the
- * preload_cache_size to be 2 if dual_page is set.
- */
- gtk_widget_queue_resize (GTK_WIDGET (view));
g_object_notify (G_OBJECT (view), "dual-page");
}
{
g_return_if_fail (EV_IS_VIEW (view));
- fullscreen = fullscreen != FALSE;
-
- if (view->fullscreen == fullscreen)
- return;
-
view->fullscreen = fullscreen;
- gtk_widget_queue_resize (GTK_WIDGET (view));
-
+
g_object_notify (G_OBJECT (view), "fullscreen");
}