X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=shell%2Fev-view.c;h=6bc088b43a4013751db3018c8b10c5cf972bc495;hb=9695105e94d879997669c2e3765ebbafce41f401;hp=c9eb4d2ee0233277bc778f4625e4d396e6e4cf42;hpb=df1b45e49e809c90e5f79e36c2da95b342d063d6;p=evince.git diff --git a/shell/ev-view.c b/shell/ev-view.c index c9eb4d2e..6bc088b4 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -78,6 +78,7 @@ static guint signals[N_SIGNALS]; typedef enum { EV_VIEW_CURSOR_NORMAL, + EV_VIEW_CURSOR_IBEAM, EV_VIEW_CURSOR_LINK, EV_VIEW_CURSOR_WAIT, EV_VIEW_CURSOR_HIDDEN, @@ -148,6 +149,7 @@ struct _EvView { int find_result; int spacing; + int rotation; double scale; gboolean continuous; @@ -257,6 +259,8 @@ static gboolean ev_view_motion_notify_event (GtkWidget GdkEventMotion *event); static gboolean ev_view_button_release_event (GtkWidget *widget, GdkEventButton *event); +static gboolean ev_view_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event); /*** Drawing ***/ static guint32 ev_gdk_color_to_rgb (const GdkColor *color); @@ -371,6 +375,10 @@ scroll_to_current_page (EvView *view, GtkOrientation orientation) GdkRectangle page_area; GtkBorder border; + if (view->document == NULL) { + return; + } + get_page_extents (view, view->current_page, &page_area, &border); if (orientation == GTK_ORIENTATION_VERTICAL) { @@ -524,6 +532,7 @@ view_update_range_and_current_page (EvView *view) ev_pixbuf_cache_set_page_range (view->pixbuf_cache, view->start_page, view->end_page, + view->rotation, view->scale, view->selection_info.selections); } @@ -698,6 +707,8 @@ ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect) GtkAdjustment *adjustment; int value; + view->pending_scroll = SCROLL_TO_KEEP_POSITION; + adjustment = view->vadjustment; if (rect->y < adjustment->value) { @@ -738,25 +749,25 @@ compute_border (EvView *view, int width, int height, GtkBorder *border) } } -static void get_page_y_offset (EvView *view, - int page, - double zoom, - int *y_offset) +static void +get_page_y_offset (EvView *view, int page, double zoom, int *y_offset) { int max_width, offset; GtkBorder border; g_return_if_fail (y_offset != NULL); - ev_page_cache_get_max_width (view->page_cache, zoom, &max_width); + ev_page_cache_get_max_width (view->page_cache, view->rotation, zoom, &max_width); compute_border (view, max_width, max_width, &border); if (view->dual_page) { - ev_page_cache_get_height_to_page (view->page_cache, page, zoom, NULL, &offset); + ev_page_cache_get_height_to_page (view->page_cache, page, + view->rotation, zoom, NULL, &offset); offset += (page / 2 + 1) * view->spacing + (page / 2) * (border.top + border.bottom); } else { - ev_page_cache_get_height_to_page (view->page_cache, page, zoom, &offset, NULL); + ev_page_cache_get_height_to_page (view->page_cache, page, + view->rotation, zoom, &offset, NULL); offset += (page + 1) * view->spacing + page * (border.top + border.bottom); } @@ -777,6 +788,7 @@ get_page_extents (EvView *view, /* Get the size of the page */ ev_page_cache_get_size (view->page_cache, page, + view->rotation, view->scale, &width, &height); compute_border (view, width, height, border); @@ -790,7 +802,8 @@ get_page_extents (EvView *view, gint max_width; gint x, y; - ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width); + ev_page_cache_get_max_width (view->page_cache, view->scale, + view->rotation, &max_width); max_width = max_width + border->left + border->right; /* Get the location of the bounding box */ if (view->dual_page) { @@ -822,6 +835,7 @@ get_page_extents (EvView *view, if (other_page < ev_page_cache_get_n_pages (view->page_cache)) { ev_page_cache_get_size (view->page_cache, other_page, + view->rotation, view->scale, &width_2, &height_2); if (width_2 > width) @@ -894,16 +908,44 @@ doc_rect_to_view_rect (EvView *view, { GdkRectangle page_area; GtkBorder border; + double x, y, w, h; int width, height; + ev_page_cache_get_size (view->page_cache, page, + view->rotation, + 1.0, + &width, &height); + + if (view->rotation == 0) { + x = doc_rect->x1; + y = doc_rect->y1; + w = doc_rect->x2 - doc_rect->x1; + h = doc_rect->y2 - doc_rect->y1; + } else if (view->rotation == 90) { + x = width - doc_rect->y2; + y = doc_rect->x1; + w = doc_rect->y2 - doc_rect->y1; + h = doc_rect->x2 - doc_rect->x1; + } else if (view->rotation == 180) { + x = width - doc_rect->x2; + y = height - doc_rect->y2; + w = doc_rect->x2 - doc_rect->x1; + h = doc_rect->y2 - doc_rect->y1; + } else if (view->rotation == 270) { + x = doc_rect->y1; + y = height - doc_rect->x2; + w = doc_rect->y2 - doc_rect->y1; + h = doc_rect->x2 - doc_rect->x1; + } else { + g_assert_not_reached (); + } + get_page_extents (view, page, &page_area, &border); - width = doc_rect->x2 - doc_rect->x1; - height = doc_rect->y2 - doc_rect->y1; - view_rect->x = floor (doc_rect->x1 * view->scale) + page_area.x; - view_rect->y = floor (doc_rect->y1 * view->scale) + page_area.y; - view_rect->width = ceil (width * view->scale); - view_rect->height = ceil (height * view->scale); + view_rect->x = x * view->scale + page_area.x; + view_rect->y = y * view->scale + page_area.y; + view_rect->width = w * view->scale; + view_rect->height = h * view->scale; } static void @@ -944,6 +986,28 @@ find_page_at_location (EvView *view, *page = -1; } +static gboolean +location_in_text (EvView *view, + gdouble x, + gdouble y) +{ + GdkRegion *region; + gint page = -1; + gint x_offset = 0, y_offset = 0; + + find_page_at_location (view, x, y, &page, &x_offset, &y_offset); + + if (page == -1) + return FALSE; + + region = ev_pixbuf_cache_get_text_mapping (view->pixbuf_cache, page); + + if (region) + return gdk_region_point_in (region, x_offset / view->scale, y_offset / view->scale); + else + return FALSE; +} + /*** Hyperref ***/ static EvLink * get_link_at_location (EvView *view, @@ -1031,7 +1095,8 @@ ev_view_size_request_continuous_dual_page (EvView *view, gint n_pages; GtkBorder border; - ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width); + ev_page_cache_get_max_width (view->page_cache, view->rotation, + view->scale, &max_width); compute_border (view, max_width, max_width, &border); n_pages = ev_page_cache_get_n_pages (view->page_cache) + 1; @@ -1058,7 +1123,8 @@ ev_view_size_request_continuous (EvView *view, GtkBorder border; - ev_page_cache_get_max_width (view->page_cache, view->scale, &max_width); + ev_page_cache_get_max_width (view->page_cache, view->rotation, + view->scale, &max_width); n_pages = ev_page_cache_get_n_pages (view->page_cache); compute_border (view, max_width, max_width, &border); @@ -1085,12 +1151,14 @@ ev_view_size_request_dual_page (EvView *view, /* Find the largest of the two. */ ev_page_cache_get_size (view->page_cache, view->current_page, + view->rotation, view->scale, &width, &height); if (view->current_page + 1 < ev_page_cache_get_n_pages (view->page_cache)) { gint width_2, height_2; ev_page_cache_get_size (view->page_cache, view->current_page + 1, + view->rotation, view->scale, &width_2, &height_2); if (width_2 > width) { @@ -1122,6 +1190,7 @@ ev_view_size_request_single_page (EvView *view, ev_page_cache_get_size (view->page_cache, view->current_page, + view->rotation, view->scale, &width, &height); compute_border (view, width, height, &border); @@ -1337,7 +1406,7 @@ ev_view_button_press_event (GtkWidget *widget, } view->selection_info.start.x = event->x + view->scroll_x; - view->selection_info.start.y = event->y + view->scroll_x; + view->selection_info.start.y = event->y + view->scroll_y; return TRUE; case 2: /* use root coordinates as reference point because @@ -1420,11 +1489,13 @@ ev_view_motion_notify_event (GtkWidget *widget, ev_view_set_status (view, msg); ev_view_set_cursor (view, EV_VIEW_CURSOR_LINK); g_free (msg); + } else if (location_in_text (view, event->x + view->scroll_x, event->y + view->scroll_y)) { + ev_view_set_cursor (view, EV_VIEW_CURSOR_IBEAM); } else { ev_view_set_status (view, NULL); - if (view->cursor == EV_VIEW_CURSOR_LINK) { + if (view->cursor == EV_VIEW_CURSOR_LINK || + view->cursor == EV_VIEW_CURSOR_IBEAM) ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); - } } return TRUE; } @@ -1459,6 +1530,20 @@ ev_view_button_release_event (GtkWidget *widget, return FALSE; } +static gboolean +ev_view_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event) +{ + EvView *view = EV_VIEW (widget); + + ev_view_set_status (view, NULL); + + if (view->cursor == EV_VIEW_CURSOR_LINK || + view->cursor == EV_VIEW_CURSOR_IBEAM) + ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); + + return FALSE; +} + /*** Drawing ***/ static guint32 @@ -1558,7 +1643,8 @@ draw_one_page (EvView *view, selection = find_selection_for_page (view, page); ev_page_cache_get_size (view->page_cache, - page, view->scale, + page, view->rotation, + view->scale, &width, &height); /* Render the document itself */ real_page_area = *page_area; @@ -1765,6 +1851,7 @@ ev_view_class_init (EvViewClass *class) widget_class->realize = ev_view_realize; widget_class->unrealize = ev_view_unrealize; widget_class->scroll_event = ev_view_scroll_event; + widget_class->leave_notify_event = ev_view_leave_notify_event; gtk_object_class->destroy = ev_view_destroy; class->set_scroll_adjustments = ev_view_set_scroll_adjustments; @@ -1993,8 +2080,9 @@ clear_caches (EvView *view) view->pixbuf_cache = NULL; } - if (view->document) { - ev_page_cache_clear (view->document); + if (view->page_cache) { + g_object_unref (view->page_cache); + view->page_cache = NULL; } } @@ -2070,6 +2158,14 @@ ev_view_get_zoom (EvView *view) return view->scale; } +gboolean +ev_view_get_continuous (EvView *view) +{ + g_return_val_if_fail (EV_IS_VIEW (view), FALSE); + + return view->continuous; +} + void ev_view_set_continuous (EvView *view, gboolean continuous) @@ -2087,6 +2183,14 @@ ev_view_set_continuous (EvView *view, g_object_notify (G_OBJECT (view), "continuous"); } +gboolean +ev_view_get_dual_page (EvView *view) +{ + g_return_val_if_fail (EV_IS_VIEW (view), FALSE); + + return view->dual_page; +} + void ev_view_set_dual_page (EvView *view, gboolean dual_page) @@ -2116,11 +2220,12 @@ ev_view_set_fullscreen (EvView *view, fullscreen = fullscreen != FALSE; - if (view->fullscreen != fullscreen) { - view->fullscreen = fullscreen; - gtk_widget_queue_resize (GTK_WIDGET (view)); - } - + if (view->fullscreen == fullscreen) + return; + + view->fullscreen = fullscreen; + gtk_widget_queue_resize (GTK_WIDGET (view)); + g_object_notify (G_OBJECT (view), "fullscreen"); } @@ -2144,7 +2249,9 @@ ev_view_set_presentation (EvView *view, return; view->presentation = presentation; + view->pending_scroll = SCROLL_TO_CURRENT_PAGE; gtk_widget_queue_resize (GTK_WIDGET (view)); + if (GTK_WIDGET_REALIZED (view)) { if (view->presentation) gdk_window_set_background (GTK_WIDGET(view)->window, @@ -2220,13 +2327,9 @@ ev_view_zoom_out (EvView *view) } static void -ev_view_set_orientation (EvView *view, - EvOrientation orientation) +ev_view_set_rotation (EvView *view, int rotation) { - ev_document_set_orientation (view->document, orientation); - - clear_caches (view); - setup_caches (view); + view->rotation = rotation; gtk_widget_queue_resize (GTK_WIDGET (view)); } @@ -2234,37 +2337,25 @@ ev_view_set_orientation (EvView *view, void ev_view_rotate_right (EvView *view) { - EvOrientation orientation, new_orientation; + int rotation = view->rotation + 90; - orientation = ev_document_get_orientation (view->document); - if (orientation == EV_ORIENTATION_PORTRAIT) { - new_orientation = EV_ORIENTATION_LANDSCAPE; - } else if (orientation == EV_ORIENTATION_LANDSCAPE) { - new_orientation = EV_ORIENTATION_UPSIDEDOWN; - } else if (orientation == EV_ORIENTATION_UPSIDEDOWN) { - new_orientation = EV_ORIENTATION_SEASCAPE; - } else { - new_orientation = EV_ORIENTATION_PORTRAIT; + if (rotation >= 360) { + rotation -= 360; } - ev_view_set_orientation (view, new_orientation); + + ev_view_set_rotation (view, rotation); } void ev_view_rotate_left (EvView *view) { - EvOrientation orientation, new_orientation; + int rotation = view->rotation - 90; - orientation = ev_document_get_orientation (view->document); - if (orientation == EV_ORIENTATION_PORTRAIT) { - new_orientation = EV_ORIENTATION_SEASCAPE; - } else if (orientation == EV_ORIENTATION_SEASCAPE) { - new_orientation = EV_ORIENTATION_UPSIDEDOWN; - } else if (orientation == EV_ORIENTATION_UPSIDEDOWN) { - new_orientation = EV_ORIENTATION_LANDSCAPE; - } else { - new_orientation = EV_ORIENTATION_PORTRAIT; + if (rotation < 0) { + rotation += 360; } - ev_view_set_orientation (view, new_orientation); + + ev_view_set_rotation (view, rotation); } static double @@ -2317,6 +2408,7 @@ ev_view_zoom_for_size_presentation (EvView *view, ev_page_cache_get_size (view->page_cache, view->current_page, + view->rotation, 1.0, &doc_width, &doc_height); @@ -2336,9 +2428,11 @@ ev_view_zoom_for_size_continuous_and_dual_page (EvView *view, gdouble scale; ev_page_cache_get_max_width (view->page_cache, + view->rotation, 1.0, &doc_width); ev_page_cache_get_max_height (view->page_cache, + view->rotation, 1.0, &doc_height); compute_border (view, doc_width, doc_height, &border); @@ -2372,9 +2466,11 @@ ev_view_zoom_for_size_continuous (EvView *view, gdouble scale; ev_page_cache_get_max_width (view->page_cache, + view->rotation, 1.0, &doc_width); ev_page_cache_get_max_height (view->page_cache, + view->rotation, 1.0, &doc_height); compute_border (view, doc_width, doc_height, &border); @@ -2412,6 +2508,7 @@ ev_view_zoom_for_size_dual_page (EvView *view, /* Find the largest of the two. */ ev_page_cache_get_size (view->page_cache, view->current_page, + view->rotation, 1.0, &doc_width, &doc_height); @@ -2419,6 +2516,7 @@ ev_view_zoom_for_size_dual_page (EvView *view, gint width_2, height_2; ev_page_cache_get_size (view->page_cache, other_page, + view->rotation, 1.0, &width_2, &height_2); if (width_2 > doc_width) @@ -2455,6 +2553,7 @@ ev_view_zoom_for_size_single_page (EvView *view, ev_page_cache_get_size (view->page_cache, view->current_page, + view->rotation, 1.0, &doc_width, &doc_height); @@ -2799,6 +2898,7 @@ compute_new_selection_text (EvView *view, GdkPoint *point; ev_page_cache_get_size (view->page_cache, i, + view->rotation, 1.0, &width, &height); selection = g_new0 (EvViewSelection, 1); @@ -2896,6 +2996,7 @@ ev_view_select_all (EvView *view) EvViewSelection *selection; ev_page_cache_get_size (view->page_cache, + view->rotation, i, 1.0, &width, &height); selection = g_new0 (EvViewSelection, 1); @@ -3036,6 +3137,9 @@ ev_view_set_cursor (EvView *view, EvViewCursor new_cursor) case EV_VIEW_CURSOR_NORMAL: gdk_window_set_cursor (widget->window, NULL); break; + case EV_VIEW_CURSOR_IBEAM: + cursor = gdk_cursor_new_for_display (display, GDK_XTERM); + break; case EV_VIEW_CURSOR_LINK: cursor = gdk_cursor_new_for_display (display, GDK_HAND2); break;