From 2fb770b3245c3066cd9c556f12793f4ed69ee52d Mon Sep 17 00:00:00 2001 From: William Jon McCann Date: Thu, 10 Jan 2013 18:35:04 +0100 Subject: libview: Make page layout a mode Instead of having a few different mutually exclusive booleans it makes sense to have it be a mode with the following options: automatic, single, dual. This allows us to have a way to automatically determine if dual page mode should be used when the window is large enough. https://bugzilla.gnome.org/show_bug.cgi?id=689468 origin commit: https://git.gnome.org/browse/evince/commit/?h=gnome-3-10&id=42f6d4b --- libview/ev-document-model.c | 72 ++++++++++++++++--- libview/ev-document-model.h | 20 +++++- libview/ev-view-private.h | 2 +- libview/ev-view.c | 164 ++++++++++++++++++++++++++++++++------------ 4 files changed, 201 insertions(+), 57 deletions(-) diff --git a/libview/ev-document-model.c b/libview/ev-document-model.c index 856ee36e..d5d97f62 100644 --- a/libview/ev-document-model.c +++ b/libview/ev-document-model.c @@ -35,6 +35,7 @@ struct _EvDocumentModel gint rotation; gdouble scale; EvSizingMode sizing_mode; + EvPageLayout page_layout; guint continuous : 1; guint dual_page : 1; guint dual_page_odd_left : 1; @@ -66,7 +67,8 @@ enum { PROP_CONTINUOUS, PROP_DUAL_PAGE, PROP_DUAL_PAGE_ODD_LEFT, - PROP_FULLSCREEN + PROP_FULLSCREEN, + PROP_PAGE_LAYOUT }; enum @@ -122,6 +124,9 @@ ev_document_model_set_property (GObject *object, case PROP_CONTINUOUS: ev_document_model_set_continuous (model, g_value_get_boolean (value)); break; + case PROP_PAGE_LAYOUT: + ev_document_model_set_page_layout (model, g_value_get_enum (value)); + break; case PROP_DUAL_PAGE: ev_document_model_set_dual_page (model, g_value_get_boolean (value)); break; @@ -166,6 +171,9 @@ ev_document_model_get_property (GObject *object, case PROP_CONTINUOUS: g_value_set_boolean (value, ev_document_model_get_continuous (model)); break; + case PROP_PAGE_LAYOUT: + g_value_set_enum (value, model->page_layout); + break; case PROP_DUAL_PAGE: g_value_set_boolean (value, ev_document_model_get_dual_page (model)); break; @@ -233,6 +241,15 @@ ev_document_model_class_init (EvDocumentModelClass *klass) EV_TYPE_SIZING_MODE, EV_SIZING_FIT_WIDTH, G_PARAM_READWRITE)); + g_object_class_install_property (g_object_class, + PROP_PAGE_LAYOUT, + g_param_spec_enum ("page-layout", + "Page Layout", + "Current page layout", + EV_TYPE_PAGE_LAYOUT, + EV_PAGE_LAYOUT_SINGLE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (g_object_class, PROP_CONTINUOUS, g_param_spec_boolean ("continuous", @@ -472,6 +489,47 @@ ev_document_model_get_sizing_mode (EvDocumentModel *model) return model->sizing_mode; } +static void +_ev_document_model_set_dual_page_internal (EvDocumentModel *model, + gboolean dual_page) +{ + g_return_if_fail (EV_IS_DOCUMENT_MODEL (model)); + + dual_page = dual_page != FALSE; + + if (dual_page == model->dual_page) + return; + + model->dual_page = dual_page; + + g_object_notify (G_OBJECT (model), "dual-page"); +} + +void +ev_document_model_set_page_layout (EvDocumentModel *model, + EvPageLayout layout) +{ + g_return_if_fail (EV_IS_DOCUMENT_MODEL (model)); + + if (layout == model->page_layout) + return; + + model->page_layout = layout; + + g_object_notify (G_OBJECT (model), "page-layout"); + + /* set deprecated property as well */ + _ev_document_model_set_dual_page_internal (model, layout == EV_PAGE_LAYOUT_DUAL); +} + +EvPageLayout +ev_document_model_get_page_layout (EvDocumentModel *model) +{ + g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), EV_PAGE_LAYOUT_SINGLE); + + return model->page_layout; +} + void ev_document_model_set_rotation (EvDocumentModel *model, gint rotation) @@ -549,16 +607,12 @@ void ev_document_model_set_dual_page (EvDocumentModel *model, gboolean dual_page) { - g_return_if_fail (EV_IS_DOCUMENT_MODEL (model)); - - dual_page = dual_page != FALSE; - - if (dual_page == model->dual_page) - return; + EvPageLayout layout; - model->dual_page = dual_page; + g_return_if_fail (EV_IS_DOCUMENT_MODEL (model)); - g_object_notify (G_OBJECT (model), "dual-page"); + layout = dual_page ? EV_PAGE_LAYOUT_DUAL : EV_PAGE_LAYOUT_SINGLE; + ev_document_model_set_page_layout (model, layout); } gboolean diff --git a/libview/ev-document-model.h b/libview/ev-document-model.h index fdec1433..4dda24cb 100644 --- a/libview/ev-document-model.h +++ b/libview/ev-document-model.h @@ -41,6 +41,12 @@ typedef enum { EV_SIZING_AUTOMATIC, } EvSizingMode; +typedef enum { + EV_PAGE_LAYOUT_SINGLE, + EV_PAGE_LAYOUT_DUAL, + EV_PAGE_LAYOUT_AUTOMATIC, +} EvPageLayout; + typedef struct _EvDocumentModel EvDocumentModel; typedef struct _EvDocumentModelClass EvDocumentModelClass; @@ -68,6 +74,9 @@ gdouble ev_document_model_get_min_scale (EvDocumentModel *model); void ev_document_model_set_sizing_mode (EvDocumentModel *model, EvSizingMode mode); EvSizingMode ev_document_model_get_sizing_mode (EvDocumentModel *model); +void ev_document_model_set_page_layout (EvDocumentModel *model, + EvPageLayout layout); +EvPageLayout ev_document_model_get_page_layout (EvDocumentModel *model); void ev_document_model_set_rotation (EvDocumentModel *model, gint rotation); gint ev_document_model_get_rotation (EvDocumentModel *model); @@ -79,9 +88,6 @@ gboolean ev_document_model_get_inverted_colors (EvDocumentModel *model); void ev_document_model_set_continuous (EvDocumentModel *model, gboolean continuous); gboolean ev_document_model_get_continuous (EvDocumentModel *model); -void ev_document_model_set_dual_page (EvDocumentModel *model, - gboolean dual_page); -gboolean ev_document_model_get_dual_page (EvDocumentModel *model); void ev_document_model_set_dual_page_odd_pages_left (EvDocumentModel *model, gboolean odd_left); gboolean ev_document_model_get_dual_page_odd_pages_left (EvDocumentModel *model); @@ -89,6 +95,14 @@ void ev_document_model_set_fullscreen (EvDocumentModel *model, gboolean fullscreen); gboolean ev_document_model_get_fullscreen (EvDocumentModel *model); +/* deprecated */ + +EV_DEPRECATED_FOR(ev_document_model_set_page_layout) +void ev_document_model_set_dual_page (EvDocumentModel *model, + gboolean dual_page); +EV_DEPRECATED_FOR(ev_document_model_get_page_layout) +gboolean ev_document_model_get_dual_page (EvDocumentModel *model); + G_END_DECLS #endif /* __EV_DOCUMENT_MODEL_H__ */ diff --git a/libview/ev-view-private.h b/libview/ev-view-private.h index 02219641..c93b0f90 100644 --- a/libview/ev-view-private.h +++ b/libview/ev-view-private.h @@ -168,10 +168,10 @@ struct _EvView { gboolean loading; gboolean continuous; - gboolean dual_page; gboolean dual_even_left; gboolean fullscreen; EvSizingMode sizing_mode; + EvPageLayout page_layout; GtkWidget *loading_window; guint loading_timeout; diff --git a/libview/ev-view.c b/libview/ev-view.c index 0b05b4a9..9125e361 100644 --- a/libview/ev-view.c +++ b/libview/ev-view.c @@ -480,6 +480,65 @@ ev_view_get_scrollbar_size (EvView *view, return (orientation == GTK_ORIENTATION_VERTICAL ? req.width : req.height) + spacing; } +static gboolean +is_dual_page (EvView *view, + gboolean *odd_left_out) +{ + gboolean dual = FALSE; + gboolean odd_left = FALSE; + + switch (view->page_layout) { + case EV_PAGE_LAYOUT_AUTOMATIC: { + GdkScreen *screen; +#if GTK_CHECK_VERSION (3, 22, 0) + GdkMonitor *monitor; + GdkDisplay *display; +#else + gint monitor; +#endif + double scale; + double doc_width; + double doc_height; + GtkAllocation allocation; + + screen = gtk_widget_get_screen (GTK_WIDGET (view)); +#if GTK_CHECK_VERSION (3, 22, 0) + display = gdk_screen_get_display (screen); + monitor = gdk_display_get_primary_monitor (display); +#else + monitor = gdk_screen_get_primary_monitor (screen); +#endif + scale = ev_document_misc_get_screen_dpi (screen, monitor) / 72.0; + + ev_document_get_max_page_size (view->document, &doc_width, &doc_height); + gtk_widget_get_allocation (GTK_WIDGET (view), &allocation); + + /* If the width is ok and the height is pretty close, try to fit it in */ + if (ev_document_get_n_pages (view->document) > 1 && + doc_width < doc_height && + allocation.width > (2 * doc_width * scale) && + allocation.height > (doc_height * scale * 0.9)) { + odd_left = !view->dual_even_left; + dual = TRUE; + } + } + break; + case EV_PAGE_LAYOUT_DUAL: + odd_left = !view->dual_even_left; + dual = TRUE; + break; + case EV_PAGE_LAYOUT_SINGLE: + break; + default: + g_assert_not_reached (); + } + + if (odd_left_out) + *odd_left_out = odd_left; + + return dual; +} + static void scroll_to_point (EvView *view, gdouble x, @@ -507,7 +566,7 @@ scroll_to_point (EvView *view, upper = gtk_adjustment_get_upper (view->hadjustment); lower = gtk_adjustment_get_lower (view->hadjustment); - if (view->dual_page) { + if (is_dual_page (view, NULL)) { gtk_adjustment_clamp_page (view->hadjustment, x, x + page_size); } else { @@ -638,6 +697,7 @@ view_update_range_and_current_page (EvView *view) { gint start = view->start_page; gint end = view->end_page; + gboolean odd_left; if (ev_document_get_n_pages (view->document) <= 0 || !ev_document_check_dimensions (view->document)) @@ -680,7 +740,7 @@ view_update_range_and_current_page (EvView *view) view->end_page = i; j = 0; } else if (found && view->current_page <= view->end_page) { - if (view->dual_page && j < 1) { + if (is_dual_page (view, NULL) && j < 1) { /* In dual mode we stop searching * after two consecutive non-visible pages. */ @@ -700,8 +760,8 @@ view_update_range_and_current_page (EvView *view) ev_document_model_set_page (view->model, best_current_page); } } - } else if (view->dual_page) { - if (view->current_page % 2 == view->dual_even_left) { + } else if (is_dual_page (view, &odd_left)) { + if (view->current_page % 2 == !odd_left) { view->start_page = view->current_page; if (view->current_page + 1 < ev_document_get_n_pages (view->document)) view->end_page = view->start_page + 1; @@ -1081,16 +1141,17 @@ get_page_y_offset (EvView *view, int page, int *y_offset) { int max_width, offset = 0; GtkBorder border; + gboolean odd_left; g_return_if_fail (y_offset != NULL); ev_view_get_max_page_size (view, &max_width, NULL); compute_border (view, max_width, max_width, &border); - if (view->dual_page) { + if (is_dual_page (view, &odd_left)) { ev_view_get_height_to_page (view, page, NULL, &offset); - offset += ((page + view->dual_even_left) / 2 + 1) * view->spacing + - ((page + view->dual_even_left) / 2 ) * (border.top + border.bottom); + offset += ((page + !odd_left) / 2 + 1) * view->spacing + + ((page + !odd_left) / 2 ) * (border.top + border.bottom); } else { ev_view_get_height_to_page (view, page, &offset, NULL); offset += (page + 1) * view->spacing + page * (border.top + border.bottom); @@ -1122,14 +1183,15 @@ ev_view_get_page_extents (EvView *view, if (view->continuous) { gint max_width; gint x, y; + gboolean odd_left; ev_view_get_max_page_size (view, &max_width, NULL); max_width = max_width + border->left + border->right; /* Get the location of the bounding box */ - if (view->dual_page) { - x = view->spacing + ((page % 2 == view->dual_even_left) ? 0 : 1) * (max_width + view->spacing); + if (is_dual_page (view, &odd_left)) { + x = view->spacing + ((page % 2 == !odd_left) ? 0 : 1) * (max_width + view->spacing); x = x + MAX (0, allocation.width - (max_width * 2 + view->spacing * 3)) / 2; - if (page % 2 == view->dual_even_left) + if (page % 2 == !odd_left) x = x + (max_width - width - border->left - border->right); } else { x = view->spacing; @@ -1142,14 +1204,16 @@ ev_view_get_page_extents (EvView *view, page_area->y = y; } else { gint x, y; - if (view->dual_page) { + gboolean odd_left; + + if (is_dual_page (view, &odd_left)) { gint width_2, height_2; gint max_width = width; gint max_height = height; GtkBorder overall_border; gint other_page; - other_page = (page % 2 == view->dual_even_left) ? page + 1: page - 1; + other_page = (page % 2 == !odd_left) ? page + 1: page - 1; /* First, we get the bounding box of the two pages */ if (other_page < ev_document_get_n_pages (view->document) @@ -1168,7 +1232,7 @@ ev_view_get_page_extents (EvView *view, y = view->spacing; /* Adjust for being the left or right page */ - if (page % 2 == view->dual_even_left) + if (page % 2 == !odd_left) x = x + max_width - width; else x = x + (max_width + overall_border.left + overall_border.right) + view->spacing; @@ -3288,6 +3352,7 @@ ev_view_size_request (GtkWidget *widget, GtkRequisition *requisition) { EvView *view = EV_VIEW (widget); + gboolean dual_page; if (view->document == NULL) { view->requisition.width = 1; @@ -3313,11 +3378,12 @@ ev_view_size_request (GtkWidget *widget, allocation.height); } - if (view->continuous && view->dual_page) + dual_page = is_dual_page (view, NULL); + if (view->continuous && dual_page) ev_view_size_request_continuous_dual_page (view, &view->requisition); else if (view->continuous) ev_view_size_request_continuous (view, &view->requisition); - else if (view->dual_page) + else if (dual_page) ev_view_size_request_dual_page (view, &view->requisition); else ev_view_size_request_single_page (view, &view->requisition); @@ -5318,10 +5384,10 @@ ev_view_init (EvView *view) view->selection_info.in_drag = FALSE; view->selection_mode = EV_VIEW_SELECTION_TEXT; view->continuous = TRUE; - view->dual_page = FALSE; view->dual_even_left = TRUE; view->fullscreen = FALSE; view->sizing_mode = EV_SIZING_FIT_WIDTH; + view->page_layout = EV_PAGE_LAYOUT_SINGLE; view->pending_scroll = SCROLL_TO_KEEP_POSITION; view->jump_to_find_result = TRUE; view->highlight_find_results = FALSE; @@ -5682,6 +5748,23 @@ ev_view_sizing_mode_changed_cb (EvDocumentModel *model, gtk_widget_queue_resize (GTK_WIDGET (view)); } +static void +ev_view_page_layout_changed_cb (EvDocumentModel *model, + GParamSpec *pspec, + EvView *view) +{ + EvPageLayout layout = ev_document_model_get_page_layout (model); + + view->page_layout = layout; + + view->pending_scroll = SCROLL_TO_PAGE_POSITION; + gtk_widget_queue_resize (GTK_WIDGET (view)); + + /* FIXME: if we're keeping the pixbuf cache around, we should extend the + * preload_cache_size to be 2 if dual_page is set. + */ +} + #define EPSILON 0.0000001 static void ev_view_scale_changed_cb (EvDocumentModel *model, @@ -5712,26 +5795,12 @@ ev_view_continuous_changed_cb (EvDocumentModel *model, gtk_widget_queue_resize (GTK_WIDGET (view)); } -static void -ev_view_dual_page_changed_cb (EvDocumentModel *model, - GParamSpec *pspec, - EvView *view) -{ - view->dual_page = ev_document_model_get_dual_page (model); - 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_dual_odd_left_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvView *view) { view->dual_even_left = !ev_document_model_get_dual_page_odd_pages_left (model); - view->pending_scroll = SCROLL_TO_PAGE_POSITION; gtk_widget_queue_resize (GTK_WIDGET (view)); } @@ -5773,7 +5842,7 @@ ev_view_set_model (EvView *view, view->sizing_mode = ev_document_model_get_sizing_mode (view->model); view->scale = ev_document_model_get_scale (view->model); view->continuous = ev_document_model_get_continuous (view->model); - view->dual_page = ev_document_model_get_dual_page (view->model); + view->page_layout = ev_document_model_get_page_layout (view->model); view->fullscreen = ev_document_model_get_fullscreen (view->model); ev_view_document_changed_cb (view->model, NULL, view); @@ -5789,15 +5858,15 @@ ev_view_set_model (EvView *view, g_signal_connect (view->model, "notify::sizing-mode", G_CALLBACK (ev_view_sizing_mode_changed_cb), view); + g_signal_connect (view->model, "notify::page-layout", + G_CALLBACK (ev_view_page_layout_changed_cb), + view); 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::dual-odd-left", G_CALLBACK (ev_view_dual_odd_left_changed_cb), view); @@ -6120,6 +6189,8 @@ ev_view_zoom_for_size (EvView *view, int width, int height) { + gboolean dual_page; + g_return_if_fail (EV_IS_VIEW (view)); g_return_if_fail (view->sizing_mode == EV_SIZING_FIT_WIDTH || view->sizing_mode == EV_SIZING_FIT_PAGE || @@ -6130,11 +6201,12 @@ ev_view_zoom_for_size (EvView *view, if (view->document == NULL) return; - if (view->continuous && view->dual_page) + dual_page = is_dual_page (view, NULL); + if (view->continuous && dual_page) ev_view_zoom_for_size_continuous_and_dual_page (view, width, height); else if (view->continuous) ev_view_zoom_for_size_continuous (view, width, height); - else if (view->dual_page) + else if (dual_page) ev_view_zoom_for_size_dual_page (view, width, height); else ev_view_zoom_for_size_single_page (view, width, height); @@ -6432,7 +6504,7 @@ compute_new_selection_text (EvView *view, if (view->continuous) { start_page = 0; end_page = n_pages; - } else if (view->dual_page) { + } else if (is_dual_page (view, NULL)) { start_page = view->start_page; end_page = view->end_page + 1; } else { @@ -6897,6 +6969,7 @@ gboolean ev_view_next_page (EvView *view) { int page, n_pages; + gboolean dual_page; g_return_val_if_fail (EV_IS_VIEW (view), FALSE); @@ -6906,7 +6979,8 @@ ev_view_next_page (EvView *view) page = ev_document_model_get_page (view->model); n_pages = ev_document_get_n_pages (view->document); - if (view->dual_page) + dual_page = is_dual_page (view, NULL); + if (dual_page) page = page + 2; else page = page + 1; @@ -6914,7 +6988,7 @@ ev_view_next_page (EvView *view) if (page < n_pages) { ev_document_model_set_page (view->model, page); return TRUE; - } else if (view->dual_page && page == n_pages) { + } else if (dual_page && page == n_pages) { ev_document_model_set_page (view->model, page - 1); return TRUE; } else { @@ -6926,6 +7000,7 @@ gboolean ev_view_previous_page (EvView *view) { int page; + gboolean dual_page; g_return_val_if_fail (EV_IS_VIEW (view), FALSE); @@ -6934,7 +7009,8 @@ ev_view_previous_page (EvView *view) page = ev_document_model_get_page (view->model); - if (view->dual_page) + dual_page = is_dual_page (view, NULL); + if (dual_page) page = page - 2; else page = page - 1; @@ -6942,7 +7018,7 @@ ev_view_previous_page (EvView *view) if (page >= 0) { ev_document_model_set_page (view->model, page); return TRUE; - } else if (view->dual_page && page == -1) { + } else if (dual_page && page == -1) { ev_document_model_set_page (view->model, 0); return TRUE; } else { @@ -6970,13 +7046,13 @@ ev_view_disconnect_handlers(EvView *view) G_CALLBACK (ev_view_sizing_mode_changed_cb), view); g_signal_handlers_disconnect_by_func(view->model, - G_CALLBACK (ev_view_scale_changed_cb), + G_CALLBACK (ev_view_page_layout_changed_cb), view); g_signal_handlers_disconnect_by_func(view->model, - G_CALLBACK (ev_view_continuous_changed_cb), + G_CALLBACK (ev_view_scale_changed_cb), view); g_signal_handlers_disconnect_by_func(view->model, - G_CALLBACK (ev_view_dual_page_changed_cb), + G_CALLBACK (ev_view_continuous_changed_cb), view); g_signal_handlers_disconnect_by_func(view->model, G_CALLBACK (ev_view_fullscreen_changed_cb), -- cgit v1.2.1