SIGNAL_BINDING_ACTIVATED,
SIGNAL_ZOOM_INVALID,
SIGNAL_EXTERNAL_LINK,
+ SIGNAL_POPUP_MENU,
N_SIGNALS,
};
gint *page,
gint *x_offset,
gint *y_offset);
-
+static gboolean doc_point_to_view_point (EvView *view,
+ int page,
+ EvPoint *doc_point,
+ GdkPoint *view_point);
/*** Hyperrefs ***/
-static EvLink* get_link_at_location (EvView *view,
- gdouble x,
- gdouble y);
+static EvLink * ev_view_get_link_at_location (EvView *view,
+ gdouble x,
+ gdouble y);
static char* tip_from_link (EvView *view,
EvLink *link);
static void handle_link_over_xy (EvView *view,
GdkEventScroll *event);
static gboolean ev_view_expose_event (GtkWidget *widget,
GdkEventExpose *event);
+static gboolean ev_view_popup_menu (GtkWidget *widget);
static gboolean ev_view_button_press_event (GtkWidget *widget,
GdkEventButton *event);
static gboolean ev_view_motion_notify_event (GtkWidget *widget,
static void
scroll_to_current_page (EvView *view, GtkOrientation orientation)
{
- GdkRectangle page_area;
- GtkBorder border;
+ GdkPoint view_point;
if (view->document == NULL) {
return;
}
- get_page_extents (view, view->current_page, &page_area, &border);
+ doc_point_to_view_point (view, view->current_page, &view->pending_point, &view_point);
+
+ if (orientation == GTK_ORIENTATION_VERTICAL) {
+ view->pending_point.y = 0;
+ } else {
+ view->pending_point.x = 0;
+ }
if (orientation == GTK_ORIENTATION_VERTICAL) {
if (view->continuous) {
gtk_adjustment_clamp_page (view->vadjustment,
- page_area.y - view->spacing,
- page_area.y + view->vadjustment->page_size);
+ view_point.y - view->spacing / 2,
+ view_point.y + view->vadjustment->page_size);
} else {
gtk_adjustment_set_value (view->vadjustment,
- view->vadjustment->lower);
+ CLAMP (view_point.y,
+ view->vadjustment->lower,
+ view->vadjustment->upper -
+ view->vadjustment->page_size));
}
} else {
if (view->dual_page) {
gtk_adjustment_clamp_page (view->hadjustment,
- page_area.x,
- page_area.x + view->hadjustment->page_size);
+ view_point.x,
+ view_point.x + view->hadjustment->page_size);
} else {
gtk_adjustment_set_value (view->hadjustment,
- CLAMP (view->hadjustment->value,
+ CLAMP (view_point.x,
view->hadjustment->lower,
view->hadjustment->upper -
view->hadjustment->page_size));
case SCROLL_TO_KEEP_POSITION:
factor = (adjustment->value) / adjustment->upper;
break;
- case SCROLL_TO_CURRENT_PAGE:
+ case SCROLL_TO_PAGE_POSITION:
break;
case SCROLL_TO_CENTER:
factor = (adjustment->value + adjustment->page_size * 0.5) / adjustment->upper;
new_value = CLAMP (adjustment->upper * factor + 0.5, 0, adjustment->upper - adjustment->page_size);
gtk_adjustment_set_value (adjustment, (int)new_value);
break;
- case SCROLL_TO_CURRENT_PAGE:
+ case SCROLL_TO_PAGE_POSITION:
scroll_to_current_page (view, orientation);
break;
case SCROLL_TO_CENTER:
static void
view_update_range_and_current_page (EvView *view)
{
+ gint current_page;
+
if (view->pending_scroll != SCROLL_TO_KEEP_POSITION)
return;
} else if (view->continuous) {
GdkRectangle current_area, unused, page_area;
GtkBorder border;
- gint current_page;
gboolean found = FALSE;
int i;
}
}
- current_page = ev_page_cache_get_current_page (view->page_cache);
-
- if (current_page < view->start_page || current_page > view->end_page) {
- view->current_page = view->start_page;
- ev_page_cache_set_current_page (view->page_cache, view->start_page);
- }
} else {
if (view->dual_page) {
- if (view->current_page % 2 == 0) {
+ if (view->current_page % 2 == DUAL_EVEN_LEFT) {
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;
+ if (view->current_page - 1 < 0)
+ view->start_page = view->current_page;
+ else
+ view->start_page = view->current_page - 1;
view->end_page = view->current_page;
}
} else {
view->start_page = view->current_page;
view->end_page = view->current_page;
}
+
+ }
+
+ current_page = ev_page_cache_get_current_page (view->page_cache);
+
+ if (current_page < view->start_page || current_page > view->end_page) {
+ view->current_page = view->start_page;
+ ev_page_cache_set_current_page (view->page_cache, view->start_page);
}
ev_pixbuf_cache_set_page_range (view->pixbuf_cache,
/* At the top of a page, assign the upper bound limit of previous page */
} else if (value == (adjustment->lower)) {
value = adjustment->upper - adjustment->page_size;
- ev_page_cache_set_current_page (view->page_cache, view->current_page - 1);
+ ev_view_previous_page (view);
/* Jump to the top */
} else {
value = MAX (value - increment, adjustment->lower);
/* At the bottom of a page, assign the lower bound limit of next page */
} else if (value == (adjustment->upper - adjustment->page_size)) {
value = 0;
- ev_page_cache_set_current_page (view->page_cache, view->current_page + 1);
+ ev_view_next_page (view);
/* Jump to the bottom */
} else {
value = MIN (value + increment, adjustment->upper - adjustment->page_size);
if (view->dual_page) {
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);
+ offset += ((page + DUAL_EVEN_LEFT) / 2 + 1) * view->spacing + ((page + DUAL_EVEN_LEFT) / 2 ) * (border.top + border.bottom);
} else {
ev_page_cache_get_height_to_page (view->page_cache, page,
view->rotation, zoom, &offset, 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) * (max_width + view->spacing);
+ x = view->spacing + ((page % 2 == DUAL_EVEN_LEFT) ? 0 : 1) * (max_width + view->spacing);
x = x + MAX (0, widget->allocation.width - (max_width * 2 + view->spacing * 3)) / 2;
- if (page % 2 == 0)
+ if (page % 2 == DUAL_EVEN_LEFT)
x = x + (max_width - width - border->left - border->right);
} else {
x = view->spacing;
GtkBorder overall_border;
gint other_page;
- other_page = page ^ 1;
+ other_page = (page % 2 == DUAL_EVEN_LEFT) ? page + 1: page - 1;
/* First, we get the bounding box of the two pages */
- if (other_page < ev_page_cache_get_n_pages (view->page_cache)) {
+ if (other_page < ev_page_cache_get_n_pages (view->page_cache)
+ && (0 <= other_page)) {
ev_page_cache_get_size (view->page_cache,
other_page,
view->rotation,
y = view->spacing;
/* Adjust for being the left or right page */
- if (page % 2 == 0)
+ if (page % 2 == DUAL_EVEN_LEFT)
x = x + max_width - width;
else
x = x + (max_width + overall_border.left + overall_border.right) + view->spacing;
/*** Hyperref ***/
static EvLink *
-get_link_at_location (EvView *view,
- gdouble x,
- gdouble y)
+ev_view_get_link_at_location (EvView *view,
+ gdouble x,
+ gdouble y)
{
gint page = -1;
gint x_offset = 0, y_offset = 0;
GList *link_mapping;
+
+ x += view->scroll_x;
+ y += view->scroll_y;
find_page_at_location (view, x, y, &page, &x_offset, &y_offset);
static void
goto_fitr_link (EvView *view, EvLink *link)
{
- GdkPoint view_point;
EvPoint doc_point;
- int doc_width, doc_height, page;
+ int 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);
-
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_set_sizing_mode (view, EV_SIZING_FREE);
ev_view_set_zoom (view, zoom, FALSE);
- ev_page_cache_set_current_page (view->page_cache, page);
- if (doc_point_to_view_point (view, page, &doc_point, &view_point)) {
- gtk_adjustment_set_value (view->hadjustment, view_point.x);
- gtk_adjustment_set_value (view->vadjustment, view_point.y);
- }
+ page = ev_link_get_page (link);
+ doc_point.x = ev_link_get_left (link);
+ doc_point.y = ev_link_get_top (link);
+
+ view->current_page = page;
+ view->pending_point = doc_point;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
static void
goto_fitv_link (EvView *view, EvLink *link)
{
- GdkPoint view_point;
EvPoint doc_point;
int doc_width, doc_height, page;
double zoom;
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);
- if (doc_point_to_view_point (view, page, &doc_point, &view_point)) {
- gtk_adjustment_set_value (view->hadjustment, view_point.x);
- }
+ view->current_page = page;
+ view->pending_point = doc_point;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
static void
goto_fith_link (EvView *view, EvLink *link)
{
- GdkPoint view_point;
EvPoint doc_point;
int doc_width, doc_height, page;
double zoom;
ev_view_set_sizing_mode (view, EV_SIZING_FREE);
ev_view_set_zoom (view, zoom, FALSE);
- if (doc_point_to_view_point (view, page, &doc_point, &view_point)) {
- gtk_adjustment_set_value (view->vadjustment, view_point.y);
- } else {
- ev_page_cache_set_current_page (view->page_cache, page);
- }
+ view->current_page = page;
+ view->pending_point = doc_point;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
static void
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);
+
+ view->current_page = page;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
static void
goto_xyz_link (EvView *view, EvLink *link)
{
- GdkPoint view_point;
EvPoint doc_point;
int height, page;
double zoom;
page = ev_link_get_page (link);
ev_page_cache_get_size (view->page_cache, page, 0, 1.0, NULL, &height);
- ev_view_set_sizing_mode (view, EV_SIZING_FREE);
if (zoom != 0) {
+ ev_view_set_sizing_mode (view, EV_SIZING_FREE);
ev_view_set_zoom (view, zoom, FALSE);
}
doc_point.x = ev_link_get_left (link);
doc_point.y = height - ev_link_get_top (link);
- if (doc_point_to_view_point (view, page, &doc_point, &view_point)) {
- gtk_adjustment_set_value (view->hadjustment, view_point.x);
- gtk_adjustment_set_value (view->vadjustment, view_point.y);
- } else {
- ev_page_cache_set_current_page (view->page_cache, page);
- }
+ view->current_page = page;
+ view->pending_point = doc_point;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
}
void
{
EvLink *link;
- link = get_link_at_location (view, x + view->scroll_x, y + view->scroll_y);
+ link = ev_view_get_link_at_location (view, x, y);
if (view->link_tooltip == NULL) {
view->link_tooltip = ev_tooltip_new (GTK_WIDGET (view));
return FALSE;
}
+static gboolean
+ev_view_popup_menu (GtkWidget *widget)
+{
+ gint x, y;
+ EvLink *link;
+ EvView *view = EV_VIEW (widget);
+
+ gtk_widget_get_pointer (widget, &x, &y);
+ link = ev_view_get_link_at_location (view, x, y);
+ g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, link);
+ return TRUE;
+}
+
static gboolean
ev_view_button_press_event (GtkWidget *widget,
GdkEventButton *event)
{
EvView *view = EV_VIEW (widget);
+ EvLink *link;
if (!GTK_WIDGET_HAS_FOCUS (widget)) {
gtk_widget_grab_focus (widget);
ev_view_set_cursor (view, EV_VIEW_CURSOR_DRAG);
+ return TRUE;
+ case 3:
+ link = ev_view_get_link_at_location (view, event->x, event->y);
+ g_signal_emit (view, signals[SIGNAL_POPUP_MENU], 0, link);
return TRUE;
}
static gboolean
selection_scroll_timeout_cb (EvView *view)
{
- gint y, shift = 0;
+ gint x, y, shift = 0;
GtkWidget *widget = GTK_WIDGET (view);
- gtk_widget_get_pointer (widget, NULL, &y);
+ gtk_widget_get_pointer (widget, &x, &y);
if (y > widget->allocation.height) {
shift = (y - widget->allocation.height) / 2;
view->vadjustment->lower,
view->vadjustment->upper -
view->vadjustment->page_size));
+
+ if (x > widget->allocation.width) {
+ shift = (x - widget->allocation.width) / 2;
+ } else if (x < 0) {
+ shift = x / 2;
+ }
+
+ if (shift)
+ gtk_adjustment_set_value (view->hadjustment,
+ CLAMP (view->hadjustment->value + shift,
+ view->hadjustment->lower,
+ view->hadjustment->upper -
+ view->hadjustment->page_size));
+
return TRUE;
}
}
if (view->document) {
- link = get_link_at_location (view, event->x + view->scroll_x,
- event->y + view->scroll_y);
+ link = ev_view_get_link_at_location (view, event->x, event->y);
} else {
link = NULL;
}
widget_class->leave_notify_event = ev_view_leave_notify_event;
widget_class->style_set = ev_view_style_set;
widget_class->drag_data_get = ev_view_drag_data_get;
+ widget_class->popup_menu = ev_view_popup_menu;
gtk_object_class->destroy = ev_view_destroy;
class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
+ signals[SIGNAL_POPUP_MENU] = g_signal_new ("popup",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EvViewClass, popup_menu),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
g_object_class_install_property (object_class,
PROP_STATUS,
if (view->current_page != new_page) {
view->current_page = new_page;
- view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
gtk_widget_queue_resize (GTK_WIDGET (view));
if (EV_IS_DOCUMENT_FIND (view->document)) {
if (view->continuous != continuous) {
view->continuous = continuous;
- view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
gtk_widget_queue_resize (GTK_WIDGET (view));
}
if (view->dual_page == dual_page)
return;
- view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
view->dual_page = dual_page;
/* FIXME: if we're keeping the pixbuf cache around, we should extend the
* preload_cache_size to be 2 if dual_page is set.
return;
view->presentation = presentation;
- view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
+ view->pending_scroll = SCROLL_TO_PAGE_POSITION;
gtk_widget_queue_resize (GTK_WIDGET (view));
if (GTK_WIDGET_REALIZED (view)) {
if (page < ev_page_cache_get_n_pages (view->page_cache)) {
ev_page_cache_set_current_page (view->page_cache, page);
return TRUE;
+ } else if (ev_view_get_dual_page (view) && page == ev_page_cache_get_n_pages (view->page_cache)) {
+ ev_page_cache_set_current_page (view->page_cache, page - 1);
+ return TRUE;
} else {
return FALSE;
}
if (page >= 0) {
ev_page_cache_set_current_page (view->page_cache, page);
return TRUE;
- } else {
+ } else if (ev_view_get_dual_page (view) && page == -1) {
+ ev_page_cache_set_current_page (view->page_cache, 0);
+ return TRUE;
+ } else {
return FALSE;
}
}