enum {
SIGNAL_BINDING_ACTIVATED,
SIGNAL_ZOOM_INVALID,
+ SIGNAL_EXTERNAL_LINK,
N_SIGNALS,
};
GtkScrollType scroll,
gboolean horizontal);
void (*zoom_invalid) (EvView *view);
+ void (*external_link) (EvView *view,
+ EvLink *link);
};
/*** Scrolling ***/
static void ev_view_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void ev_view_realize (GtkWidget *widget);
-static void ev_view_unrealize (GtkWidget *widget);
static gboolean ev_view_scroll_event (GtkWidget *widget,
GdkEventScroll *event);
static gboolean ev_view_expose_event (GtkWidget *widget,
int target_width,
int target_height,
int vsb_width);
+static double zoom_for_size_fit_height (int doc_width,
+ int doc_height,
+ int target_width,
+ int target_height,
+ int vsb_height);
static double zoom_for_size_best_fit (int doc_width,
int doc_height,
int target_width,
view->start_page = view->current_page;
if (view->current_page + 1 < ev_page_cache_get_n_pages (view->page_cache))
view->end_page = view->start_page + 1;
+ else
+ view->end_page = view->start_page;
} else {
view->start_page = view->current_page - 1;
view->end_page = view->current_page;
if (view->presentation) {
switch (scroll) {
case GTK_SCROLL_STEP_BACKWARD:
- ev_page_cache_prev_page (view->page_cache);
+ ev_view_previous_page (view);
break;
case GTK_SCROLL_STEP_FORWARD:
- ev_page_cache_next_page (view->page_cache);
+ ev_view_next_page (view);
break;
default:
break;
return FALSE;
}
+static int
+ev_view_get_width (EvView *view)
+{
+ return GTK_WIDGET (view)->allocation.width;
+}
+
+static int
+ev_view_get_height (EvView *view)
+{
+ return GTK_WIDGET (view)->allocation.height;
+}
+
/*** Hyperref ***/
static EvLink *
get_link_at_location (EvView *view,
return NULL;
}
+static void
+goto_fitr_link (EvView *view, EvLink *link)
+{
+ GdkPoint view_point;
+ EvPoint doc_point;
+ int doc_width, doc_height, page;
+ double zoom;
+
+ page = ev_link_get_page (link);
+ ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height);
+
+ doc_point.x = ev_link_get_left (link);
+ doc_point.y = ev_link_get_top (link);
+ doc_point_to_view_point (view, page, &doc_point, &view_point);
+
+ zoom = zoom_for_size_best_fit (ev_link_get_right (link) - ev_link_get_left (link),
+ ev_link_get_top (link) - ev_link_get_bottom (link),
+ ev_view_get_width (view),
+ ev_view_get_height (view), 0, 0);
+
+ ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ ev_view_set_zoom (view, zoom, FALSE);
+ ev_page_cache_set_current_page (view->page_cache, page);
+ gtk_adjustment_set_value (view->hadjustment, view_point.x);
+}
+
+static void
+goto_fitv_link (EvView *view, EvLink *link)
+{
+ GdkPoint view_point;
+ EvPoint doc_point;
+ int doc_width, doc_height, page;
+ double zoom;
+
+ page = ev_link_get_page (link);
+ ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height);
+
+ doc_point.x = ev_link_get_left (link);
+ doc_point.y = 0;
+ doc_point_to_view_point (view, page, &doc_point, &view_point);
+
+ zoom = zoom_for_size_fit_height (doc_width - doc_point.x , doc_height,
+ ev_view_get_width (view),
+ ev_view_get_height (view), 0);
+
+ ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ ev_view_set_zoom (view, zoom, FALSE);
+ ev_page_cache_set_current_page (view->page_cache, page);
+ gtk_adjustment_set_value (view->hadjustment, view_point.x);
+}
+
+static void
+goto_fith_link (EvView *view, EvLink *link)
+{
+ GdkPoint view_point;
+ EvPoint doc_point;
+ int doc_width, doc_height, page;
+ double zoom;
+
+ page = ev_link_get_page (link);
+ ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height);
+
+ doc_point.x = 0;
+ doc_point.y = doc_height - ev_link_get_top (link);
+ doc_point_to_view_point (view, page, &doc_point, &view_point);
+
+ zoom = zoom_for_size_fit_width (doc_width, ev_link_get_top (link),
+ ev_view_get_width (view),
+ ev_view_get_height (view), 0);
+
+ ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ ev_view_set_zoom (view, zoom, FALSE);
+ gtk_adjustment_set_value (view->vadjustment, view_point.y);
+}
+
+static void
+goto_fit_link (EvView *view, EvLink *link)
+{
+ double zoom;
+ int doc_width, doc_height;
+ int page;
+
+ page = ev_link_get_page (link);
+ ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height);
+
+ zoom = zoom_for_size_best_fit (doc_width, doc_height, ev_view_get_width (view),
+ ev_view_get_height (view), 0, 0);
+
+ ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ ev_view_set_zoom (view, zoom, FALSE);
+ ev_page_cache_set_current_page (view->page_cache, page);
+}
+
static void
goto_xyz_link (EvView *view, EvLink *link)
{
ev_view_goto_link (EvView *view, EvLink *link)
{
EvLinkType type;
- const char *uri;
int page;
type = ev_link_get_link_type (link);
page = ev_link_get_page (link);
ev_page_cache_set_current_page (view->page_cache, page);
break;
+ case EV_LINK_TYPE_PAGE_FIT:
+ goto_fit_link (view, link);
+ break;
+ case EV_LINK_TYPE_PAGE_FITH:
+ goto_fith_link (view, link);
+ break;
+ case EV_LINK_TYPE_PAGE_FITV:
+ goto_fitv_link (view, link);
+ break;
+ case EV_LINK_TYPE_PAGE_FITR:
+ goto_fitr_link (view, link);
+ break;
case EV_LINK_TYPE_PAGE_XYZ:
goto_xyz_link (view, link);
break;
case EV_LINK_TYPE_EXTERNAL_URI:
- uri = ev_link_get_uri (link);
- gnome_vfs_url_show (uri);
+ case EV_LINK_TYPE_LAUNCH:
+ g_signal_emit (view, signals[SIGNAL_EXTERNAL_LINK], 0, link);
break;
}
}
EvView *view = EV_VIEW (widget);
if (view->sizing_mode == EV_SIZING_FIT_WIDTH ||
- view->sizing_mode == EV_SIZING_BEST_FIT) {
+ view->sizing_mode == EV_SIZING_BEST_FIT) {
g_signal_emit (view, signals[SIGNAL_ZOOM_INVALID], 0);
gdk_window_set_background (widget->window, &widget->style->mid [GTK_STATE_NORMAL]);
}
-static void
-ev_view_unrealize (GtkWidget *widget)
-{
- GTK_WIDGET_CLASS (ev_view_parent_class)->unrealize (widget);
-}
-
static gboolean
ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event)
{
- EvView *view = EV_VIEW (widget);
+ EvView *view = EV_VIEW (widget);
+ guint state;
+
+ state = event->state & gtk_accelerator_get_default_mod_mask ();
- if ((event->state & GDK_CONTROL_MASK) != 0) {
+ if (state == GDK_CONTROL_MASK && view->presentation == FALSE) {
+ ev_view_set_sizing_mode (view, EV_SIZING_FREE);
- ev_view_set_sizing_mode (view, EV_SIZING_FREE);
+ if (event->direction == GDK_SCROLL_UP ||
+ event->direction == GDK_SCROLL_LEFT) {
+ if (ev_view_can_zoom_in (view)) {
+ ev_view_zoom_in (view);
+ }
+ } else {
+ if (ev_view_can_zoom_out (view)) {
+ ev_view_zoom_out (view);
+ }
+ }
- if (event->direction == GDK_SCROLL_UP ||
- event->direction == GDK_SCROLL_LEFT) {
- if (ev_view_can_zoom_in (view)) {
- ev_view_zoom_in (view);
- }
- } else {
- if (ev_view_can_zoom_out (view)) {
- ev_view_zoom_out (view);
- }
- }
- return TRUE;
+ return TRUE;
}
- if ((event->state & GDK_SHIFT_MASK) != 0) {
+ /* Shift+Wheel scrolls the in the perpendicular direction */
+ if (state & GDK_SHIFT_MASK) {
if (event->direction == GDK_SCROLL_UP)
event->direction = GDK_SCROLL_LEFT;
+ if (event->direction == GDK_SCROLL_LEFT)
+ event->direction = GDK_SCROLL_UP;
if (event->direction == GDK_SCROLL_DOWN)
event->direction = GDK_SCROLL_RIGHT;
+ if (event->direction == GDK_SCROLL_RIGHT)
+ event->direction = GDK_SCROLL_DOWN;
+
+ event->state &= ~GDK_SHIFT_MASK;
+ state &= ~GDK_SHIFT_MASK;
+ }
+
+ if (state == 0 && view->presentation) {
+ switch (event->direction) {
+ case GDK_SCROLL_DOWN:
+ case GDK_SCROLL_RIGHT:
+ ev_view_next_page (view);
+ break;
+ case GDK_SCROLL_UP:
+ case GDK_SCROLL_LEFT:
+ ev_view_previous_page (view);
+ break;
+ }
+
+ return TRUE;
}
return FALSE;
GdkEventButton *event)
{
EvView *view = EV_VIEW (widget);
+ EvLink *link;
if (view->pressed_button == 2) {
ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
}
+ if (view->document) {
+ link = get_link_at_location (view, event->x + view->scroll_x,
+ event->y + view->scroll_y);
+ } else {
+ link = NULL;
+ }
+
view->pressed_button = -1;
view->drag_info.in_drag = FALSE;
if (view->selection_info.selections) {
ev_view_update_primary_selection (view);
- } else if (view->document) {
- EvLink *link;
-
- link = get_link_at_location (view, event->x + view->scroll_x, event->y + view->scroll_y);
- if (link) {
- ev_view_goto_link (view, link);
+ } else if (link) {
+ ev_view_goto_link (view, link);
+ } else if (view->presentation) {
+ switch (event->button) {
+ case 1:
+ ev_view_next_page (view);
+ return TRUE;
+ case 3:
+ ev_view_previous_page (view);
+ return TRUE;
}
}
-
+
return FALSE;
}
widget_class->size_request = ev_view_size_request;
widget_class->size_allocate = ev_view_size_allocate;
widget_class->realize = ev_view_realize;
- widget_class->unrealize = ev_view_unrealize;
widget_class->scroll_event = ev_view_scroll_event;
widget_class->enter_notify_event = ev_view_enter_notify_event;
widget_class->leave_notify_event = ev_view_leave_notify_event;
NULL, NULL,
ev_marshal_VOID__VOID,
G_TYPE_NONE, 0, G_TYPE_NONE);
+ signals[SIGNAL_EXTERNAL_LINK] = g_signal_new ("external-link",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EvViewClass, external_link),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
g_object_class_install_property (object_class,
PROP_STATUS,
return scale;
}
+static double
+zoom_for_size_fit_height (int doc_width,
+ int doc_height,
+ int target_width,
+ int target_height,
+ int vsb_height)
+{
+ double scale;
+
+ scale = (double)target_height / doc_height;
+
+ if (doc_width * scale > target_width)
+ scale = (double) (target_height - vsb_height) / doc_height;
+
+ return scale;
+}
+
static double
zoom_for_size_best_fit (int doc_width,
int doc_height,
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);
+ int i, n_pages;
- n_results = ev_document_find_get_n_results (find, view->current_page);
+ n_pages = ev_page_cache_get_n_pages (view->page_cache);
+ for (i = 0; i < n_pages; i++) {
+ if (ev_document_find_get_n_results (find, i) > 0) {
+ return TRUE;
+ }
+ }
}
- return n_results > 0;
+ return FALSE;
}
void
ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL);
}
+gboolean
+ev_view_next_page (EvView *view)
+{
+ int page;
+
+ g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
+
+ page = ev_page_cache_get_current_page (view->page_cache);
+ page = ev_view_get_dual_page (view) ? page + 2 : page + 1;
+
+ if (page < ev_page_cache_get_n_pages (view->page_cache)) {
+ ev_page_cache_set_current_page (view->page_cache, page);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+gboolean
+ev_view_previous_page (EvView *view)
+{
+ int page;
+
+ g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
+
+ page = ev_page_cache_get_current_page (view->page_cache);
+ page = ev_view_get_dual_page (view) ? page - 2 : page - 1;
+
+ if (page >= 0) {
+ ev_page_cache_set_current_page (view->page_cache, page);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
/*** Enum description for usage in signal ***/
GType
}
return etype;
}
-