GtkAdjustment *vadjustment);
static void add_scroll_binding_keypad (GtkBindingSet *binding_set,
guint keyval,
- GtkScrollType scroll,
- gboolean horizontal);
-static void ev_view_binding_activated (EvView *view,
- GtkScrollType scroll,
+ GdkModifierType modifiers,
+ EvScrollType scroll,
gboolean horizontal);
static void ensure_rectangle_is_visible (EvView *view,
GdkRectangle *rect);
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,
GdkRectangle *page_area,
GtkBorder *border,
GdkRectangle *expose_area);
+static void draw_loading_text (EvView *view,
+ GdkRectangle *page_area,
+ GdkRectangle *expose_area);
/*** Callbacks ***/
static void find_changed_cb (EvDocument *document,
/*** Status messages ***/
static void ev_view_set_status (EvView *view,
const char *message);
-static void update_find_status_message (EvView *view);
+static void update_find_status_message (EvView *view,
+ gboolean this_page);
static void ev_view_set_find_status (EvView *view,
const char *message);
/*** Find ***/
static void jump_to_find_result (EvView *view);
static void jump_to_find_page (EvView *view,
- EvViewFindDirection direction);
+ EvViewFindDirection direction,
+ gint shift);
/*** Selection ***/
static void compute_selections (EvView *view,
if (orientation == GTK_ORIENTATION_VERTICAL) {
if (view->continuous) {
gtk_adjustment_clamp_page (view->vadjustment,
- view_point.y - view->spacing,
+ view_point.y - view->spacing / 2,
view_point.y + view->vadjustment->page_size);
} else {
gtk_adjustment_set_value (view->vadjustment,
- view_point.y);
+ CLAMP (view_point.y,
+ view->vadjustment->lower,
+ view->vadjustment->upper -
+ view->vadjustment->page_size));
}
} else {
if (view->dual_page) {
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 == ev_page_cache_get_dual_even_left (view->page_cache)) {
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)
+ 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,
static void
add_scroll_binding_keypad (GtkBindingSet *binding_set,
guint keyval,
- GtkScrollType scroll,
+ GdkModifierType modifiers,
+ EvScrollType scroll,
gboolean horizontal)
{
guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left;
- gtk_binding_entry_add_signal (binding_set, keyval, 0,
+ gtk_binding_entry_add_signal (binding_set, keyval, modifiers,
"binding_activated", 2,
- GTK_TYPE_SCROLL_TYPE, scroll,
+ EV_TYPE_SCROLL_TYPE, scroll,
G_TYPE_BOOLEAN, horizontal);
- gtk_binding_entry_add_signal (binding_set, keypad_keyval, 0,
+ gtk_binding_entry_add_signal (binding_set, keypad_keyval, modifiers,
"binding_activated", 2,
- GTK_TYPE_SCROLL_TYPE, scroll,
+ EV_TYPE_SCROLL_TYPE, scroll,
G_TYPE_BOOLEAN, horizontal);
}
void
ev_view_scroll (EvView *view,
- EvScrollType scroll)
+ EvScrollType scroll,
+ gboolean horizontal)
{
GtkAdjustment *adjustment;
double value, increment;
gboolean first_page = FALSE;
gboolean last_page = FALSE;
+ view->jump_to_find_result = FALSE;
+
+ if (view->presentation) {
+ switch (scroll) {
+ case EV_SCROLL_STEP_BACKWARD:
+ ev_view_previous_page (view);
+ break;
+ case EV_SCROLL_STEP_FORWARD:
+ ev_view_next_page (view);
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
/* Assign values for increment and vertical adjustment */
- adjustment = view->vadjustment;
+ adjustment = horizontal ? view->hadjustment : view->vadjustment;
increment = adjustment->page_size * 0.75;
value = adjustment->value;
/* 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);
}
break;
- default:
- break;
- }
-
- gtk_adjustment_set_value (adjustment, value);
-}
-
-static void
-ev_view_binding_activated (EvView *view,
- GtkScrollType scroll,
- gboolean horizontal)
-{
- GtkAdjustment *adjustment;
- double value;
-
- if (view->presentation) {
- switch (scroll) {
- case GTK_SCROLL_STEP_BACKWARD:
- ev_view_previous_page (view);
- break;
- case GTK_SCROLL_STEP_FORWARD:
- ev_view_next_page (view);
- break;
- default:
- break;
- }
- return;
- }
-
- if (horizontal) {
- adjustment = view->hadjustment;
- } else {
- adjustment = view->vadjustment;
- }
-
- value = adjustment->value;
-
- switch (scroll) {
- case GTK_SCROLL_STEP_BACKWARD:
+ case EV_SCROLL_STEP_BACKWARD:
value -= adjustment->step_increment;
break;
- case GTK_SCROLL_STEP_FORWARD:
+ case EV_SCROLL_STEP_FORWARD:
value += adjustment->step_increment;
break;
- default:
+ case EV_SCROLL_STEP_DOWN:
+ value -= adjustment->step_increment / 10;
+ break;
+ case EV_SCROLL_STEP_UP:
+ value += adjustment->step_increment / 10;
+ break;
+ default:
break;
}
value = CLAMP (value, adjustment->lower,
- adjustment->upper - adjustment->page_size);
+ adjustment->upper - adjustment->page_size);
gtk_adjustment_set_value (adjustment, value);
+
}
#define MARGIN 5
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 + ev_page_cache_get_dual_even_left (view->page_cache)) / 2 + 1) * view->spacing + ((page + ev_page_cache_get_dual_even_left (view->page_cache)) / 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 == ev_page_cache_get_dual_even_left (view->page_cache)) ? 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 == ev_page_cache_get_dual_even_left (view->page_cache))
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 == ev_page_cache_get_dual_even_left (view->page_cache)) ? 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 == ev_page_cache_get_dual_even_left (view->page_cache))
x = x + max_width - width;
else
x = x + (max_width + overall_border.left + overall_border.right) + view->spacing;
return TRUE;
}
+ view->jump_to_find_result = FALSE;
/* Shift+Wheel scrolls the in the perpendicular direction */
if (state & GDK_SHIFT_MASK) {
if (event->direction == GDK_SCROLL_UP)
EvView *view = EV_VIEW (widget);
int i;
+ if (view->loading) {
+ draw_loading_text (view,
+ &(widget->allocation),
+ &(event->area));
+ }
+
if (view->document == NULL)
return FALSE;
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)
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;
}
GdkRectangle view_rectangle;
guchar alpha;
- if (i == view->find_result && page == view->find_page) {
+ if (i == view->find_result && page == view->current_page) {
alpha = 0x90;
} else {
alpha = 0x20;
GdkRectangle overlap;
GdkRectangle real_page_area;
EvViewSelection *selection;
+ gint current_page;
g_assert (view->document);
+
if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
return;
-
+
+ current_page = ev_page_cache_get_current_page (view->page_cache);
selection = find_selection_for_page (view, page);
ev_page_cache_get_size (view->page_cache,
page, view->rotation,
ev_document_misc_paint_one_page (GTK_WIDGET(view)->window,
GTK_WIDGET (view),
- page_area, border);
+ page_area, border,
+ page == current_page);
if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
GdkPixbuf *selection_pixbuf = 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;
- class->binding_activated = ev_view_binding_activated;
+ class->binding_activated = ev_view_scroll;
widget_class->set_scroll_adjustments_signal =
g_signal_new ("set-scroll-adjustments",
binding_set = gtk_binding_set_by_class (class);
- 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_keypad (binding_set, GDK_Left, 0, EV_SCROLL_STEP_BACKWARD, TRUE);
+ add_scroll_binding_keypad (binding_set, GDK_Right, 0, EV_SCROLL_STEP_FORWARD, TRUE);
+ add_scroll_binding_keypad (binding_set, GDK_Left, GDK_MOD1_MASK, EV_SCROLL_STEP_DOWN, TRUE);
+ add_scroll_binding_keypad (binding_set, GDK_Right, GDK_MOD1_MASK, EV_SCROLL_STEP_UP, TRUE);
+ add_scroll_binding_keypad (binding_set, GDK_Up, 0, EV_SCROLL_STEP_BACKWARD, FALSE);
+ add_scroll_binding_keypad (binding_set, GDK_Down, 0, EV_SCROLL_STEP_FORWARD, FALSE);
+ add_scroll_binding_keypad (binding_set, GDK_Up, GDK_MOD1_MASK, EV_SCROLL_STEP_DOWN, FALSE);
+ add_scroll_binding_keypad (binding_set, GDK_Down, GDK_MOD1_MASK, EV_SCROLL_STEP_UP, FALSE);
}
static void
view->fullscreen = FALSE;
view->sizing_mode = EV_SIZING_FIT_WIDTH;
view->pending_scroll = SCROLL_TO_KEEP_POSITION;
+ view->jump_to_find_result = TRUE;
}
/*** Callbacks ***/
static void
find_changed_cb (EvDocument *document, int page, EvView *view)
{
- jump_to_find_page (view, EV_VIEW_FIND_NEXT);
- jump_to_find_result (view);
- update_find_status_message (view);
+ double percent;
+ int n_pages;
+ percent = ev_document_find_get_progress
+ (EV_DOCUMENT_FIND (view->document));
+ n_pages = ev_page_cache_get_n_pages (view->page_cache);
+
+ if (view->jump_to_find_result == TRUE) {
+ jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
+ jump_to_find_result (view);
+ }
+ update_find_status_message (view, percent * n_pages >= n_pages - 1 );
if (view->current_page == page)
gtk_widget_queue_draw (GTK_WIDGET (view));
}
EvView *view)
{
if (view->current_page != new_page) {
-
view->current_page = new_page;
view->pending_scroll = SCROLL_TO_PAGE_POSITION;
gtk_widget_queue_resize (GTK_WIDGET (view));
+ } else {
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ }
- if (EV_IS_DOCUMENT_FIND (view->document)) {
- view->find_page = new_page;
- view->find_result = 0;
- update_find_status_message (view);
- }
+ if (EV_IS_DOCUMENT_FIND (view->document)) {
+ view->find_result = 0;
+ update_find_status_message (view, TRUE);
}
}
}
}
+void
+ev_view_set_loading (EvView *view,
+ gboolean loading)
+{
+ view->loading = loading;
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+}
+
void
ev_view_set_document (EvView *view,
EvDocument *document)
{
g_return_if_fail (EV_IS_VIEW (view));
+ view->loading = FALSE;
+
if (document != view->document) {
clear_caches (view);
}
view->document = document;
- view->find_page = 0;
view->find_result = 0;
if (view->document) {
}
static void
-update_find_status_message (EvView *view)
+update_find_status_message (EvView *view, gboolean this_page)
{
char *message;
- if (view->current_page == view->find_page) {
+ if (this_page) {
int results;
results = ev_document_find_get_n_results
percent = ev_document_find_get_progress
(EV_DOCUMENT_FIND (view->document));
- if (percent >= (1.0 - 1e-10)) {
- message = g_strdup (_("Not found"));
- } else {
- message = g_strdup_printf (_("%3d%% remaining to search"),
- (int) ((1.0 - percent) * 100));
- }
-
+ message = g_strdup_printf (_("%3d%% remaining to search"),
+ (int) ((1.0 - percent) * 100));
+
}
ev_view_set_find_status (view, message);
g_free (message);
EvRectangle rect;
GdkRectangle view_rect;
int n_results;
- int page = view->find_page;
+ int page = view->current_page;
n_results = ev_document_find_get_n_results (find, page);
}
}
+/**
+ * jump_to_find_page
+ * @view: #EvView instance
+ * @direction: Direction to look
+ * @shift: Shift from current page
+ *
+ * Jumps to the first page that has occurences of searched word.
+ * Uses a direction where to look and a shift from current page.
+ *
+ */
static void
-jump_to_find_page (EvView *view, EvViewFindDirection direction)
+jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
{
int n_pages, i;
int page;
if (direction == EV_VIEW_FIND_NEXT)
- page = view->find_page + i;
+ page = view->current_page + i;
else
- page = view->find_page - i;
-
-
+ page = view->current_page - i;
+ page += shift;
+
if (page >= n_pages) {
page = page - n_pages;
}
has_results = ev_document_find_page_has_results
(EV_DOCUMENT_FIND (view->document), page);
if (has_results == -1) {
- view->find_page = page;
break;
} else if (has_results == 1) {
ev_page_cache_set_current_page (view->page_cache, page);
if (view->find_result >= n_results) {
view->find_result = 0;
- view->find_page++;
- if (view->find_page >= n_pages) {
- view->find_page = 0;
- }
-
- jump_to_find_page (view, EV_VIEW_FIND_NEXT);
+ jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1);
jump_to_find_result (view);
} else {
jump_to_find_result (view);
if (view->find_result < 0) {
- view->find_page--;
- if (view->find_page < 0) {
- view->find_page = n_pages - 1;
- }
-
- jump_to_find_page (view, EV_VIEW_FIND_PREV);
+ jump_to_find_page (view, EV_VIEW_FIND_PREV, -1);
view->find_result = ev_document_find_get_n_results (find, view->current_page) - 1;
jump_to_find_result (view);
} else {
}
}
+void ev_view_search_changed (EvView *view)
+{
+ /* search string has changed, focus on new search result */
+ view->jump_to_find_result = TRUE;
+}
+
/*** Selections ***/
/* compute_new_selection_rect/text calculates the area currently selected by
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 (view->dual_page && !view->presentation)
+ page = page + 2;
+ else
+ page = 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 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;
}
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 (view->dual_page && !view->presentation)
+ page = page - 2;
+ else
+ page = page - 1;
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;
}
}
}
return etype;
}
+
+GType
+ev_scroll_type_get_type (void)
+{
+ static GType etype = 0;
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ { EV_SCROLL_PAGE_FORWARD, "EV_SCROLL_PAGE_FORWARD", "scroll-page-forward" },
+ { EV_SCROLL_PAGE_BACKWARD, "EV_SCROLL_PAGE_BACKWARD", "scroll-page-backward" },
+ { EV_SCROLL_STEP_FORWARD, "EV_SCROLL_STEP_FORWARD", "scroll-step-forward" },
+ { EV_SCROLL_STEP_FORWARD, "EV_SCROLL_STEP_FORWARD", "scroll-step-forward" },
+ { EV_SCROLL_STEP_UP, "EV_SCROLL_STEP_UP", "scroll-step-up" },
+ { EV_SCROLL_STEP_DOWN, "EV_SCROLL_STEP_DOWN", "scroll-step-down" },
+ { 0, NULL, NULL }
+ };
+ etype = g_enum_register_static ("EvScrollType", values);
+ }
+ return etype;
+}