[evince] libview: Make page layout a mode



commit 42f6d4b3a24e4524bc0b4295bae4c3ab744c5b20
Author: William Jon McCann <jmccann redhat com>
Date:   Thu Jan 10 18:35:04 2013 +0100

    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

 help/reference/libview/libevview.types |    1 +
 libview/ev-document-model.c            |   72 ++++++++++++++--
 libview/ev-document-model.h            |   20 ++++-
 libview/ev-view-private.h              |    2 +-
 libview/ev-view.c                      |  146 +++++++++++++++++++++++---------
 5 files changed, 188 insertions(+), 53 deletions(-)
---
diff --git a/help/reference/libview/libevview.types b/help/reference/libview/libevview.types
index 668b715..311e9c7 100644
--- a/help/reference/libview/libevview.types
+++ b/help/reference/libview/libevview.types
@@ -24,6 +24,7 @@ ev_job_thumbnail_get_type
 ev_page_cache_get_type
 ev_print_operation_get_type
 ev_sizing_mode_get_type
+ev_page_layout_get_type
 ev_view_get_type
 ev_view_presentation_get_type
 ev_view_selection_mode_get_type
diff --git a/libview/ev-document-model.c b/libview/ev-document-model.c
index 1a21338..5e22d3f 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;
@@ -68,7 +69,8 @@ enum {
 	PROP_DUAL_PAGE_ODD_LEFT,
 	PROP_FULLSCREEN,
 	PROP_MIN_SCALE,
-	PROP_MAX_SCALE
+	PROP_MAX_SCALE,
+	PROP_PAGE_LAYOUT
 };
 
 enum
@@ -133,6 +135,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;
@@ -183,6 +188,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;
@@ -273,6 +281,15 @@ ev_document_model_class_init (EvDocumentModelClass *klass)
 							    G_PARAM_READWRITE |
                                                             G_PARAM_STATIC_STRINGS));
 	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",
 							       "Continuous",
@@ -519,6 +536,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)
@@ -596,16 +654,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 b371d8b..1d12b4a 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);
@@ -77,9 +86,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);
@@ -87,6 +93,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 75cac9a..9313a0d 100644
--- a/libview/ev-view-private.h
+++ b/libview/ev-view-private.h
@@ -163,10 +163,10 @@ struct _EvView {
 	gboolean can_zoom_in;
 	gboolean can_zoom_out;
 	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 7aa2c73..cc676ec 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -497,6 +497,54 @@ 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;
+		double        scale;
+		double        doc_width;
+		double        doc_height;
+		GtkAllocation allocation;
+		int n_pages;
+
+		screen = gtk_widget_get_screen (GTK_WIDGET (view));
+		scale = ev_document_misc_get_screen_dpi (screen) / 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,
@@ -524,7 +572,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 {
@@ -647,6 +695,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))
@@ -689,7 +738,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.
 					 */
@@ -709,8 +758,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;
@@ -1096,15 +1145,16 @@ get_page_y_offset (EvView *view, int page, int *y_offset)
 {
 	int offset = 0;
 	GtkBorder border;
+	gboolean odd_left;
 
 	g_return_if_fail (y_offset != NULL);
 
 	compute_border (view, &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);
@@ -1136,14 +1186,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;
@@ -1156,14 +1207,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)
@@ -1182,7 +1235,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;
@@ -3155,6 +3208,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;
@@ -3180,11 +3234,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);
@@ -4935,10 +4990,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;
@@ -5327,6 +5382,23 @@ update_can_zoom (EvView *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,
@@ -5376,19 +5448,6 @@ ev_view_continuous_changed_cb (EvDocumentModel *model,
 }
 
 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)
@@ -5430,7 +5489,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);
 
@@ -5446,6 +5505,9 @@ 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);
@@ -5458,9 +5520,6 @@ ev_view_set_model (EvView          *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);
@@ -5771,6 +5830,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 ||
@@ -5781,11 +5842,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);
@@ -6061,7 +6123,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 {
@@ -6537,6 +6599,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);
 	
@@ -6546,7 +6609,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;
@@ -6554,7 +6618,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 {
@@ -6566,6 +6630,7 @@ gboolean
 ev_view_previous_page (EvView *view)
 {
 	int page;
+	gboolean dual_page;
 
 	g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
 
@@ -6574,7 +6639,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;
@@ -6582,7 +6648,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 {	



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]