PROP_SIZING_MODE,
};
+enum {
+ SIGNAL_SCROLL_VIEW,
+ SIGNAL_ZOOM_INVALID,
+ N_SIGNALS,
+};
+
enum {
TARGET_STRING,
TARGET_TEXT,
{ "UTF8_STRING", 0, TARGET_UTF8_STRING },
};
+static guint signals[N_SIGNALS];
+
typedef enum {
EV_VIEW_CURSOR_NORMAL,
EV_VIEW_CURSOR_LINK,
EvSizingMode sizing_mode;
PendingScroll pending_scroll;
+ gboolean pending_resize;
};
struct _EvViewClass {
void (*scroll_view) (EvView *view,
GtkScrollType scroll,
gboolean horizontal);
+ void (*zoom_invalid) (EvView *view);
};
/*** Scrolling ***/
static void ev_view_init (EvView *view);
/*** Zoom and sizing ***/
-static double zoom_for_size_fit_width (int doc_width,
- int doc_height,
- int target_width,
- int target_height);
-static double zoom_for_size_best_fit (int doc_width,
- int doc_height,
- int target_width,
- int target_height);
-static void ev_view_zoom_for_size_presentation (EvView *view,
- int width,
- int height);
-static void ev_view_zoom_for_size_continuous_dual_page (EvView *view,
- int width,
- int height);
-static void ev_view_zoom_for_size_continuous (EvView *view,
- int width,
- int height);
-static void ev_view_zoom_for_size_dual_page (EvView *view,
- int width,
- int height);
-static void ev_view_zoom_for_size_single_page (EvView *view,
- int width,
- int height);
-static void ev_view_set_zoom_for_size (EvView *view,
- int width,
- int height);
-
+static double zoom_for_size_fit_width (int doc_width,
+ int doc_height,
+ int target_width,
+ int target_height,
+ int vsb_width);
+static double zoom_for_size_best_fit (int doc_width,
+ int doc_height,
+ int target_width,
+ int target_height,
+ int vsb_width,
+ int hsb_width);
+static void ev_view_zoom_for_size_presentation (EvView *view,
+ int width,
+ int height);
+static void ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
+ int width,
+ int height,
+ int vsb_width,
+ int hsb_height);
+static void ev_view_zoom_for_size_continuous (EvView *view,
+ int width,
+ int height,
+ int vsb_width,
+ int hsb_height);
+static void ev_view_zoom_for_size_dual_page (EvView *view,
+ int width,
+ int height,
+ int vsb_width,
+ int hsb_height);
+static void ev_view_zoom_for_size_single_page (EvView *view,
+ int width,
+ int height,
+ int vsb_width,
+ int hsb_height);
/*** Cursors ***/
static GdkCursor* ev_view_create_invisible_cursor (void);
static void ev_view_set_cursor (EvView *view,
static void
view_update_adjustments (EvView *view)
{
- if (view->hadjustment)
+ int dx = 0, dy = 0;
+
+ if (! GTK_WIDGET_REALIZED (view))
+ return;
+
+ if (view->hadjustment) {
+ dx = view->scroll_x - view->hadjustment->value;
view->scroll_x = view->hadjustment->value;
- else
+ } else {
view->scroll_x = 0;
+ }
- if (view->vadjustment)
+ if (view->vadjustment) {
+ dy = view->scroll_y - view->vadjustment->value;
view->scroll_y = view->vadjustment->value;
- else
+ } else {
view->scroll_y = 0;
-
- gtk_widget_queue_draw (GTK_WIDGET (view));
+ }
+
+
+ if (view->pending_resize)
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ else
+ gdk_window_scroll (GTK_WIDGET (view)->window, dx, dy);
+
if (view->document)
view_update_range_and_current_page (view);
EvPageCache *page_cache = view->page_cache;
int old_width, old_height;
int new_width, new_height;
- int max_height, n_rows;
+ int max_height, max_width, n_rows;
ev_page_cache_get_size (page_cache,
view->current_page,
else
gtk_widget_queue_draw (GTK_WIDGET (view));
- if (view->continuous) {
+ get_bounding_box_size (view, &max_width, &max_height);
+
+ if (view->continuous && view->vadjustment) {
n_rows = view->dual_page ? new_page / 2 : new_page;
-
- get_bounding_box_size (view, NULL, &max_height);
gtk_adjustment_clamp_page(view->vadjustment,
(max_height + view->spacing) * n_rows,
gtk_adjustment_set_value (view->vadjustment,
view->vadjustment->lower);
}
+
+ if (view->dual_page && view->hadjustment) {
+ if (new_page % 2 == 0) {
+ gtk_adjustment_set_value (view->hadjustment,
+ view->hadjustment->lower);
+ } else {
+ gtk_adjustment_clamp_page (view->hadjustment,
+ view->hadjustment->lower +
+ max_width + view->spacing,
+ view->hadjustment->lower +
+ max_width + view->spacing +
+ view->hadjustment->page_size);
+ }
+ }
view->current_page = new_page;
view_update_range_and_current_page (view);
GtkScrollType scroll,
gboolean horizontal)
{
- if (scroll == GTK_SCROLL_PAGE_BACKWARD) {
- ev_page_cache_prev_page (view->page_cache);
- } else if (scroll == GTK_SCROLL_PAGE_FORWARD) {
- ev_page_cache_next_page (view->page_cache);
- } else {
- GtkAdjustment *adjustment;
- double value;
+ GtkAdjustment *adjustment;
+ double value;
- if (horizontal) {
- adjustment = view->hadjustment;
- } else {
- adjustment = view->vadjustment;
- }
+ if (horizontal) {
+ adjustment = view->hadjustment;
+ } else {
+ adjustment = view->vadjustment;
+ }
- value = adjustment->value;
+ value = adjustment->value;
- switch (scroll) {
- case GTK_SCROLL_STEP_BACKWARD:
- value -= adjustment->step_increment;
- break;
- case GTK_SCROLL_STEP_FORWARD:
- value += adjustment->step_increment;
- break;
- default:
- break;
- }
+ switch (scroll) {
+ case GTK_SCROLL_STEP_BACKWARD:
+ value -= adjustment->step_increment;
+ break;
+ case GTK_SCROLL_STEP_FORWARD:
+ value += adjustment->step_increment;
+ break;
+ default:
+ break;
+ }
- value = CLAMP (value, adjustment->lower,
- adjustment->upper - adjustment->page_size);
+ value = CLAMP (value, adjustment->lower,
+ adjustment->upper - adjustment->page_size);
- gtk_adjustment_set_value (adjustment, value);
- }
+ gtk_adjustment_set_value (adjustment, value);
}
#define MARGIN 5
{
EvView *view = EV_VIEW (widget);
- if (!GTK_WIDGET_REALIZED (widget))
- return;
-
if (view->document == NULL) {
requisition->width = 1;
requisition->height = 1;
if (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
view->sizing_mode == EV_SIZING_BEST_FIT) {
-
- ev_view_set_zoom_for_size (view, allocation->width, allocation->height);
- ev_view_size_request (widget, &widget->requisition);
- }
-
+ g_signal_emit (view, signals[SIGNAL_ZOOM_INVALID], 0);
+
+ ev_view_size_request (widget, &widget->requisition);
+ }
+
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);
gdk_window_set_background (widget->window, &widget->style->black);
else
gdk_window_set_background (widget->window, &widget->style->mid [GTK_STATE_NORMAL]);
-
- if (view->document) {
- /* We can't get page size without a target, so we have to
- * queue a size request at realization. Could be fixed
- * with EvDocument changes to allow setting a GdkScreen
- * without setting a target.
- */
- gtk_widget_queue_resize (widget);
- }
}
static void
GTK_TYPE_ADJUSTMENT,
GTK_TYPE_ADJUSTMENT);
- g_signal_new ("scroll_view",
+ signals[SIGNAL_SCROLL_VIEW] = g_signal_new ("scroll-view",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (EvViewClass, scroll_view),
GTK_TYPE_SCROLL_TYPE,
G_TYPE_BOOLEAN);
+ signals[SIGNAL_ZOOM_INVALID] = g_signal_new ("zoom-invalid",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EvViewClass, zoom_invalid),
+ NULL, NULL,
+ ev_marshal_VOID__VOID,
+ G_TYPE_NONE, 0, G_TYPE_NONE);
+
g_object_class_install_property (object_class,
PROP_STATUS,
g_param_spec_string ("status",
add_scroll_binding_keypad (binding_set, GDK_Right, GTK_SCROLL_STEP_FORWARD, TRUE);
add_scroll_binding_keypad (binding_set, GDK_Up, GTK_SCROLL_STEP_BACKWARD, FALSE);
add_scroll_binding_keypad (binding_set, GDK_Down, GTK_SCROLL_STEP_FORWARD, FALSE);
-
- add_scroll_binding_keypad (binding_set, GDK_Page_Up, GTK_SCROLL_PAGE_BACKWARD, FALSE);
- add_scroll_binding_keypad (binding_set, GDK_Page_Down, GTK_SCROLL_PAGE_FORWARD, FALSE);
}
static void
{
if (view->current_page != new_page) {
- view_scroll_to_page (view, new_page);
+ if (view->pending_scroll != SCROLL_TO_CURRENT_PAGE) {
+ /* Should scroll right now */
+ view_scroll_to_page (view, new_page);
+ } else {
+ /* We'll scroll to new page on allocate */
+ view->current_page = new_page;
+ }
if (EV_IS_DOCUMENT_FIND (view->document)) {
view->find_page = new_page;
if (ABS (view->scale - scale) < EPSILON)
return;
view->scale = scale;
+ view->pending_resize = TRUE;
gtk_widget_queue_resize (GTK_WIDGET (view));
}
ev_view_set_zoom (view, ZOOM_OUT_FACTOR, TRUE);
}
-
-
static double
zoom_for_size_fit_width (int doc_width,
int doc_height,
int target_width,
- int target_height)
+ int target_height,
+ int vsb_width)
{
double scale;
scale = (double)target_width / doc_width;
if (doc_height * scale > target_height)
- scale = (double) (target_width) / doc_width;
+ scale = (double) (target_width - vsb_width) / doc_width;
return scale;
}
zoom_for_size_best_fit (int doc_width,
int doc_height,
int target_width,
- int target_height)
+ int target_height,
+ int vsb_width,
+ int hsb_width)
{
double w_scale;
double h_scale;
h_scale = (double)target_height / doc_height;
if (doc_height * w_scale > target_height)
- w_scale = (double) target_width / doc_width;
+ w_scale = (double) (target_width - vsb_width) / doc_width;
if (doc_width * h_scale > target_width)
- h_scale = (double) target_height / doc_height;
+ h_scale = (double) (target_height - hsb_width) / doc_height;
return MIN (w_scale, h_scale);
}
1.0,
&doc_width,
&doc_height);
- scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
+ scale = zoom_for_size_best_fit (doc_width, doc_height, width, height, 0, 0);
ev_view_set_zoom (view, scale, FALSE);
}
static void
-ev_view_zoom_for_size_continuous_dual_page (EvView *view,
+ev_view_zoom_for_size_continuous_and_dual_page (EvView *view,
int width,
- int height)
+ int height,
+ int vsb_width,
+ int hsb_height)
{
int doc_width, doc_height;
GtkBorder border;
* page height. We assume there's always a vertical scrollbar for
* now. We need to fix this. */
if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
- scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
+ scale = zoom_for_size_fit_width (doc_width, doc_height, width - vsb_width, height, 0);
else if (view->sizing_mode == EV_SIZING_BEST_FIT)
- scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
+ scale = zoom_for_size_best_fit (doc_width, doc_height, width - vsb_width, height, 0, hsb_height);
else
g_assert_not_reached ();
static void
ev_view_zoom_for_size_continuous (EvView *view,
int width,
- int height)
+ int height,
+ int vsb_width,
+ int hsb_height)
{
int doc_width, doc_height;
GtkBorder border;
* page height. We assume there's always a vertical scrollbar for
* now. We need to fix this. */
if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
- scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
+ scale = zoom_for_size_fit_width (doc_width, doc_height, width - vsb_width, height, 0);
else if (view->sizing_mode == EV_SIZING_BEST_FIT)
- scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
+ scale = zoom_for_size_best_fit (doc_width, doc_height, width - vsb_width, height, 0, hsb_height);
else
g_assert_not_reached ();
static void
ev_view_zoom_for_size_dual_page (EvView *view,
int width,
- int height)
+ int height,
+ int vsb_width,
+ int hsb_height)
{
GtkBorder border;
gint doc_width, doc_height;
height -= (border.top + border.bottom + 2 * view->spacing);
if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
- scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
+ scale = zoom_for_size_fit_width (doc_width, doc_height, width, height, vsb_width);
else if (view->sizing_mode == EV_SIZING_BEST_FIT)
- scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
+ scale = zoom_for_size_best_fit (doc_width, doc_height, width, height, vsb_width, hsb_height);
else
g_assert_not_reached ();
static void
ev_view_zoom_for_size_single_page (EvView *view,
int width,
- int height)
+ int height,
+ int vsb_width,
+ int hsb_height)
{
int doc_width, doc_height;
GtkBorder border;
height -= (border.top + border.bottom + 2 * view->spacing);
if (view->sizing_mode == EV_SIZING_FIT_WIDTH)
- scale = zoom_for_size_fit_width (doc_width, doc_height, width, height);
+ scale = zoom_for_size_fit_width (doc_width, doc_height, width, height, vsb_width);
else if (view->sizing_mode == EV_SIZING_BEST_FIT)
- scale = zoom_for_size_best_fit (doc_width, doc_height, width, height);
+ scale = zoom_for_size_best_fit (doc_width, doc_height, width, height, vsb_width, hsb_height);
else
g_assert_not_reached ();
void
ev_view_set_zoom_for_size (EvView *view,
int width,
- int height)
-{
+ int height,
+ int vsb_width,
+ int hsb_height)
+{
g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
view->sizing_mode == EV_SIZING_BEST_FIT);
g_return_if_fail (width >= 0);
if (view->presentation)
ev_view_zoom_for_size_presentation (view, width, height);
else if (view->continuous && view->dual_page)
- ev_view_zoom_for_size_continuous_dual_page (view, width, height);
+ ev_view_zoom_for_size_continuous_and_dual_page (view, width, height, vsb_width, hsb_height);
else if (view->continuous)
- ev_view_zoom_for_size_continuous (view, width, height);
+ ev_view_zoom_for_size_continuous (view, width, height, vsb_width, hsb_height);
else if (view->dual_page)
- ev_view_zoom_for_size_dual_page (view, width, height);
+ ev_view_zoom_for_size_dual_page (view, width, height, vsb_width, hsb_height);
else
- ev_view_zoom_for_size_single_page (view, width, height);
+ ev_view_zoom_for_size_single_page (view, width, height, vsb_width, hsb_height);
}
/*** Status text messages ***/