X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=shell%2Fev-view.c;h=a3033ad896c4ff9b70ce7a43304f31c56f5eb61e;hb=1ffbf57cf1dc030f178be587e7408b1108a23dc5;hp=29c85f4682643f7ee42a5dd9921857a5acfcddf4;hpb=ce80b45c492900e204b314c27000d8fd99687130;p=evince.git diff --git a/shell/ev-view.c b/shell/ev-view.c index 29c85f46..a3033ad8 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include #include @@ -94,7 +95,7 @@ struct _EvView { gboolean pressed_button; gboolean has_selection; GdkPoint selection_start; - GdkRectangle selection; + EvRectangle selection; EvViewCursor cursor; GtkAdjustment *hadjustment; @@ -257,29 +258,76 @@ ev_view_get_offsets (EvView *view, int *x_offset, int *y_offset) } static void -view_rect_to_doc_rect (EvView *view, GdkRectangle *view_rect, GdkRectangle *doc_rect) +view_rect_to_doc_rect (EvView *view, GdkRectangle *view_rect, EvRectangle *doc_rect) { int x_offset, y_offset; ev_view_get_offsets (view, &x_offset, &y_offset); - doc_rect->x = (view_rect->x - x_offset) / view->scale; - doc_rect->y = (view_rect->y - y_offset) / view->scale; - doc_rect->width = view_rect->width / view->scale; - doc_rect->height = view_rect->height / view->scale; + doc_rect->x1 = (double) (view_rect->x - x_offset) / view->scale; + doc_rect->y1 = (double) (view_rect->y - y_offset) / view->scale; + doc_rect->x2 = doc_rect->x1 + (double) view_rect->width / view->scale; + doc_rect->y2 = doc_rect->y1 + (double) view_rect->height / view->scale; } static void -doc_rect_to_view_rect (EvView *view, GdkRectangle *doc_rect, GdkRectangle *view_rect) +doc_rect_to_view_rect (EvView *view, EvRectangle *doc_rect, GdkRectangle *view_rect) { int x_offset, y_offset; ev_view_get_offsets (view, &x_offset, &y_offset); - view_rect->x = doc_rect->x * view->scale + x_offset; - view_rect->y = doc_rect->y * view->scale + y_offset; - view_rect->width = doc_rect->width * view->scale; - view_rect->height = doc_rect->height * view->scale; + view_rect->x = floor (doc_rect->x1 * view->scale) + x_offset; + view_rect->y = floor (doc_rect->y1 * view->scale) + y_offset; + view_rect->width = ceil (doc_rect->x2 * view->scale) + x_offset - view_rect->x; + view_rect->height = ceil (doc_rect->y2 * view->scale) + y_offset - view_rect->y; } +static void +compute_zoom_factor (EvView *view) +{ + int doc_width, doc_height; + double scale, scale_w, scale_h; + GtkBorder border; + + if (view->width <= 0 && view->height <= 0) { + return; + } + + doc_width = doc_height = 0; + scale = scale_w = scale_h = 1.0; + ev_page_cache_get_size (view->page_cache, + view->current_page, + 1.0, + &doc_width, + &doc_height); + + /* FIXME: The border size isn't constant. Ugh. Still, if we have extra + * space, we just cut it from the border */ + ev_document_misc_get_page_border_size (doc_width, doc_height, &border); + + if (doc_width == 0 || doc_height == 0) { + return; + } + + if (view->width >= 0) { + int target_width; + + target_width = view->width - (view->spacing * 2 + border.left + border.right); + scale = scale_w = (double)target_width / doc_width; + } + + if (view->height >= 0) { + int target_height; + + target_height = view->height - (view->spacing * 2 + border.top + border.bottom); + scale = scale_h = (double)target_height / doc_height; + } + + if (view->width >= 0 && view->height >= 0) { + scale = (scale_w < scale_h) ? scale_w : scale_h; + } + + view->scale = scale; +} /* Called by size_request to make sure we have appropriate jobs running. */ @@ -300,6 +348,8 @@ ev_view_size_request (GtkWidget *widget, return; } + compute_zoom_factor (view); + ev_page_cache_get_size (view->page_cache, view->current_page, view->scale, @@ -436,9 +486,6 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window, GdkPixbuf *pixbuf; GdkColor *fill_color_gdk; guint fill_color; - int x_offset, y_offset; - - ev_view_get_offsets (EV_VIEW (widget), &x_offset, &y_offset); fill_color_gdk = gdk_color_copy (>K_WIDGET (widget)->style->base[GTK_STATE_SELECTED]); fill_color = ev_gdk_color_to_rgb (fill_color_gdk) << 8 | alpha; @@ -449,7 +496,7 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window, gdk_draw_pixbuf (window, NULL, pixbuf, 0, 0, - rect->x + x_offset, rect->y + y_offset, + rect->x, rect->y, rect->width, rect->height, GDK_RGB_DITHER_NONE, 0, 0); @@ -459,7 +506,7 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window, gc = gdk_gc_new (window); gdk_gc_set_rgb_fg_color (gc, fill_color_gdk); gdk_draw_rectangle (window, gc, FALSE, - rect->x + x_offset, rect->y + y_offset, + rect->x, rect->y, rect->width - 1, rect->height - 1); g_object_unref (gc); @@ -478,19 +525,22 @@ highlight_find_results (EvView *view) find = EV_DOCUMENT_FIND (view->document); g_mutex_lock (EV_DOC_MUTEX); - results = ev_document_find_get_n_results (find); + results = ev_document_find_get_n_results (find, view->current_page); g_mutex_unlock (EV_DOC_MUTEX); for (i = 0; i < results; i++) { - GdkRectangle rectangle; + EvRectangle rectangle; + GdkRectangle view_rectangle; guchar alpha; alpha = (i == view->find_result) ? 0x90 : 0x20; g_mutex_lock (EV_DOC_MUTEX); - ev_document_find_get_result (find, i, &rectangle); + ev_document_find_get_result (find, view->current_page, + i, &rectangle); g_mutex_unlock (EV_DOC_MUTEX); + doc_rect_to_view_rect (view, &rectangle, &view_rectangle); draw_rubberband (GTK_WIDGET (view), view->bin_window, - &rectangle, alpha); + &view_rectangle, alpha); } } @@ -617,12 +667,16 @@ void ev_view_copy (EvView *ev_view) { GtkClipboard *clipboard; - GdkRectangle selection; char *text; - doc_rect_to_view_rect (ev_view, &ev_view->selection, &selection); + if (!ev_document_can_get_text (ev_view->document)) { + return; + } + g_mutex_lock (EV_DOC_MUTEX); - text = ev_document_get_text (ev_view->document, &selection); + text = ev_document_get_text (ev_view->document, + ev_view->current_page, + &ev_view->selection); g_mutex_unlock (EV_DOC_MUTEX); clipboard = gtk_widget_get_clipboard (GTK_WIDGET (ev_view), @@ -638,12 +692,16 @@ ev_view_primary_get_cb (GtkClipboard *clipboard, gpointer data) { EvView *ev_view = EV_VIEW (data); - GdkRectangle selection; char *text; - doc_rect_to_view_rect (ev_view, &ev_view->selection, &selection); + if (!ev_document_can_get_text (ev_view->document)) { + return; + } + g_mutex_lock (EV_DOC_MUTEX); - text = ev_document_get_text (ev_view->document, &selection); + text = ev_document_get_text (ev_view->document, + ev_view->current_page, + &ev_view->selection); g_mutex_unlock (EV_DOC_MUTEX); gtk_selection_data_set_text (selection_data, text, -1); } @@ -968,10 +1026,10 @@ ev_view_set_scroll_adjustments (EvView *view, } static void -add_scroll_binding (GtkBindingSet *binding_set, - guint keyval, - GtkScrollType scroll, - gboolean horizontal) +add_scroll_binding_keypad (GtkBindingSet *binding_set, + guint keyval, + GtkScrollType scroll, + gboolean horizontal) { guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left; @@ -985,6 +1043,23 @@ add_scroll_binding (GtkBindingSet *binding_set, G_TYPE_BOOLEAN, horizontal); } +static void +add_scroll_binding_shifted (GtkBindingSet *binding_set, + guint keyval, + GtkScrollType scroll_normal, + GtkScrollType scroll_shifted, + gboolean horizontal) +{ + gtk_binding_entry_add_signal (binding_set, keyval, 0, + "scroll_view", 2, + GTK_TYPE_SCROLL_TYPE, scroll_normal, + G_TYPE_BOOLEAN, horizontal); + gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK, + "scroll_view", 2, + GTK_TYPE_SCROLL_TYPE, scroll_shifted, + G_TYPE_BOOLEAN, horizontal); +} + static void ev_view_jump (EvView *view, GtkScrollType scroll) @@ -1177,16 +1252,16 @@ ev_view_class_init (EvViewClass *class) binding_set = gtk_binding_set_by_class (class); - add_scroll_binding (binding_set, GDK_Left, GTK_SCROLL_STEP_BACKWARD, TRUE); - add_scroll_binding (binding_set, GDK_Right, GTK_SCROLL_STEP_FORWARD, TRUE); - add_scroll_binding (binding_set, GDK_Up, GTK_SCROLL_STEP_BACKWARD, FALSE); - add_scroll_binding (binding_set, GDK_Down, GTK_SCROLL_STEP_FORWARD, FALSE); + add_scroll_binding_keypad (binding_set, GDK_Left, GTK_SCROLL_STEP_BACKWARD, TRUE); + 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 (binding_set, GDK_Page_Up, GTK_SCROLL_PAGE_BACKWARD, FALSE); - add_scroll_binding (binding_set, GDK_Page_Down, GTK_SCROLL_PAGE_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); - add_scroll_binding (binding_set, GDK_space, EV_SCROLL_PAGE_FORWARD, FALSE); - add_scroll_binding (binding_set, GDK_BackSpace, EV_SCROLL_PAGE_BACKWARD, FALSE); + add_scroll_binding_shifted (binding_set, GDK_space, EV_SCROLL_PAGE_FORWARD, EV_SCROLL_PAGE_BACKWARD, FALSE); + add_scroll_binding_shifted (binding_set, GDK_BackSpace, EV_SCROLL_PAGE_BACKWARD, EV_SCROLL_PAGE_FORWARD, FALSE); } static void @@ -1207,12 +1282,13 @@ update_find_status_message (EvView *view) char *message; // g_mutex_lock (EV_DOC_MUTEX); - if (ev_document_get_page (view->document) == view->find_page) { + if (view->current_page == view->find_page) { int results; // g_mutex_lock (EV_DOC_MUTEX); results = ev_document_find_get_n_results - (EV_DOCUMENT_FIND (view->document)); + (EV_DOCUMENT_FIND (view->document), + view->current_page); // g_mutex_unlock (EV_DOC_MUTEX); /* TRANS: Sometimes this could be better translated as "%d hit(s) on this page". Therefore this string @@ -1280,20 +1356,22 @@ static void jump_to_find_result (EvView *view) { EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - GdkRectangle rect; + EvRectangle rect; + GdkRectangle view_rect; int n_results; g_mutex_lock (EV_DOC_MUTEX); - n_results = ev_document_find_get_n_results (find); + n_results = ev_document_find_get_n_results (find, view->current_page); g_mutex_unlock (EV_DOC_MUTEX); if (n_results > view->find_result) { g_mutex_lock (EV_DOC_MUTEX); ev_document_find_get_result - (find, view->find_result, &rect); + (find, view->current_page, view->find_result, &rect); g_mutex_unlock (EV_DOC_MUTEX); - ensure_rectangle_is_visible (view, &rect); + doc_rect_to_view_rect (view, &rect, &view_rect); + ensure_rectangle_is_visible (view, &view_rect); } } @@ -1334,12 +1412,8 @@ find_changed_cb (EvDocument *document, int page, EvView *view) jump_to_find_result (view); update_find_status_message (view); -#if 0 - /* FIXME: */ - if (ev_document_get_page (document) == page) { + if (view->current_page == page) gtk_widget_queue_draw (GTK_WIDGET (view)); - } -#endif } /*** Public API ***/ @@ -1385,6 +1459,8 @@ page_changed_cb (EvPageCache *page_cache, view->current_page = new_page; view->has_selection = FALSE; + compute_zoom_factor (view); + ev_pixbuf_cache_set_page_range (view->pixbuf_cache, view->current_page, view->current_page, @@ -1443,6 +1519,12 @@ ev_view_set_document (EvView *view, } } +int +ev_view_get_page (EvView *view) +{ + return view->current_page; +} + static void go_to_link (EvView *view, EvLink *link) { @@ -1487,83 +1569,34 @@ ev_view_zoom (EvView *view, scale = CLAMP (scale, MIN_SCALE, MAX_SCALE); view->scale = scale; + view->width = view->height = -1; gtk_widget_queue_resize (GTK_WIDGET (view)); } void ev_view_zoom_in (EvView *view) { - view->width = view->height = -1; ev_view_zoom (view, ZOOM_IN_FACTOR, TRUE); } void ev_view_zoom_out (EvView *view) { - view->width = view->height = -1; ev_view_zoom (view, ZOOM_OUT_FACTOR, TRUE); } -static double -size_to_zoom_factor (EvView *view, int width, int height) -{ - int doc_width, doc_height; - double scale, scale_w, scale_h; - GtkBorder border; - - doc_width = doc_height = 0; - scale = scale_w = scale_h = 1.0; - ev_page_cache_get_size (view->page_cache, - view->current_page, - view->scale, - &doc_width, - &doc_height); - - /* FIXME: The border size isn't constant. Ugh. Still, if we have extra - * space, we just cut it from the border */ - ev_document_misc_get_page_border_size (doc_width, doc_height, &border); - - if (doc_width == 0 && doc_height == 0) { - return 0; - } - - if (width >= 0) { - int target_width; - - target_width = width - (view->spacing * 2 + border.left + border.right); - scale = scale_w = (double)target_width * view->scale / doc_width; - } - - if (height >= 0) { - int target_height; - - target_height = height - (view->spacing * 2 + border.top + border.bottom); - scale = scale_h = (double)target_height * view->scale / doc_height; - } - - if (width >= 0 && height >= 0) { - scale = (scale_w < scale_h) ? scale_w : scale_h; - } - - return scale; -} - void ev_view_set_size (EvView *view, int width, int height) { - double factor; - - if (!view->document) + if (!view->document) { return; + } - if (view->width != width || - view->height != height) { + if (width != view->width || height != view->height) { view->width = width; view->height = height; - factor = size_to_zoom_factor (view, width, height); - ev_view_zoom (view, factor, FALSE); gtk_widget_queue_resize (GTK_WIDGET (view)); } } @@ -1584,6 +1617,22 @@ ev_view_get_find_status (EvView *view) return view->find_status; } +gboolean +ev_view_can_find_next (EvView *view) +{ + int n_results = 0; + + if (EV_IS_DOCUMENT_FIND (view->document)) { + EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); + + g_mutex_lock (EV_DOC_MUTEX); + n_results = ev_document_find_get_n_results (find, view->current_page); + g_mutex_unlock (EV_DOC_MUTEX); + } + + return n_results > 0; +} + void ev_view_find_next (EvView *view) { @@ -1593,7 +1642,7 @@ ev_view_find_next (EvView *view) page_cache = ev_document_get_page_cache (view->document); g_mutex_lock (EV_DOC_MUTEX); - n_results = ev_document_find_get_n_results (find); + n_results = ev_document_find_get_n_results (find, view->current_page); g_mutex_unlock (EV_DOC_MUTEX); n_pages = ev_page_cache_get_n_pages (page_cache); @@ -1625,7 +1674,7 @@ ev_view_find_previous (EvView *view) page_cache = ev_document_get_page_cache (view->document); g_mutex_lock (EV_DOC_MUTEX); - n_results = ev_document_find_get_n_results (find); + n_results = ev_document_find_get_n_results (find, view->current_page); g_mutex_unlock (EV_DOC_MUTEX); n_pages = ev_page_cache_get_n_pages (page_cache);