+update_visible_range (EvSidebarThumbnails *sidebar_thumbnails,
+ gint start_page,
+ gint end_page)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ int old_start_page, old_end_page;
+
+ old_start_page = priv->start_page;
+ old_end_page = priv->end_page;
+
+ if (start_page == old_start_page &&
+ end_page == old_end_page)
+ return;
+
+ /* Clear the areas we no longer display */
+ if (old_start_page >= 0 && old_start_page < start_page)
+ clear_range (sidebar_thumbnails, old_start_page, MIN (start_page - 1, old_end_page));
+
+ if (old_end_page > 0 && old_end_page > end_page)
+ clear_range (sidebar_thumbnails, MAX (end_page + 1, old_start_page), old_end_page);
+
+ add_range (sidebar_thumbnails, start_page, end_page);
+
+ priv->start_page = start_page;
+ priv->end_page = end_page;
+}
+
+static void
+adjustment_changed_cb (EvSidebarThumbnails *sidebar_thumbnails)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ GtkTreePath *path = NULL;
+ GtkTreePath *path2 = NULL;
+ gint wy1;
+ gint wy2;
+
+ /* Widget is not currently visible */
+ if (!GTK_WIDGET_MAPPED (sidebar_thumbnails))
+ return;
+
+ if (priv->vadjustment->page_size == 0)
+ return;
+
+ if (priv->tree_view) {
+ if (! GTK_WIDGET_REALIZED (priv->tree_view))
+ return;
+
+ gtk_tree_view_convert_tree_to_bin_window_coords (GTK_TREE_VIEW (priv->tree_view),
+ 0, (int) priv->vadjustment->value,
+ NULL, &wy1);
+ gtk_tree_view_convert_tree_to_bin_window_coords (GTK_TREE_VIEW (priv->tree_view),
+ 0, (int) (priv->vadjustment->value + priv->vadjustment->page_size),
+ NULL, &wy2);
+ gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (priv->tree_view),
+ 1, wy1 + 1, &path,
+ NULL, NULL, NULL);
+ gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (priv->tree_view),
+ 1, wy2 -1, &path2,
+ NULL, NULL, NULL);
+ } else if (priv->icon_view) {
+ if (! GTK_WIDGET_REALIZED (priv->icon_view))
+ return;
+ if (! gtk_icon_view_get_visible_range (GTK_ICON_VIEW (priv->icon_view), &path, &path2))
+ return;
+ } else {
+ return;
+ }
+
+ if (path && path2) {
+ update_visible_range (sidebar_thumbnails,
+ gtk_tree_path_get_indices (path)[0],
+ gtk_tree_path_get_indices (path2)[0]);
+ }
+
+ gtk_tree_path_free (path);
+ gtk_tree_path_free (path2);
+}
+
+static void
+ev_sidebar_thumbnails_fill_model (EvSidebarThumbnails *sidebar_thumbnails)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ GtkTreeIter iter;
+ int i;
+ gint prev_width = -1;
+ gint prev_height = -1;
+
+ for (i = 0; i < sidebar_thumbnails->priv->n_pages; i++) {
+ gchar *page_label;
+ gchar *page_string;
+ GdkPixbuf *loading_icon = NULL;
+ gint width, height;
+
+ page_label = ev_page_cache_get_page_label (priv->page_cache, i);
+ page_string = g_markup_printf_escaped ("<i>%s</i>", page_label);
+ ev_page_cache_get_thumbnail_size (sidebar_thumbnails->priv->page_cache, i,
+ sidebar_thumbnails->priv->rotation,
+ &width, &height);
+ if (!loading_icon || (width != prev_width && height != prev_height)) {
+ loading_icon =
+ ev_sidebar_thumbnails_get_loading_icon (sidebar_thumbnails,
+ width, height);
+ }
+
+ prev_width = width;
+ prev_height = height;
+
+ gtk_list_store_append (priv->list_store, &iter);
+ gtk_list_store_set (priv->list_store, &iter,
+ COLUMN_PAGE_STRING, page_string,
+ COLUMN_PIXBUF, loading_icon,
+ COLUMN_THUMBNAIL_SET, FALSE,
+ -1);
+ g_free (page_label);
+ g_free (page_string);
+ }
+}
+
+static gboolean
+refresh (EvSidebarThumbnails *sidebar_thumbnails)
+{
+ adjustment_changed_cb (sidebar_thumbnails);
+ return FALSE;
+}
+
+void
+ev_sidebar_thumbnails_refresh (EvSidebarThumbnails *sidebar_thumbnails,
+ int rotation)
+{
+ sidebar_thumbnails->priv->rotation = rotation;
+ if (sidebar_thumbnails->priv->loading_icons)
+ g_hash_table_remove_all (sidebar_thumbnails->priv->loading_icons);
+
+ if (sidebar_thumbnails->priv->document == NULL ||
+ sidebar_thumbnails->priv->n_pages <= 0)
+ return;
+
+ ev_sidebar_thumbnails_clear_model (sidebar_thumbnails);
+ ev_sidebar_thumbnails_fill_model (sidebar_thumbnails);
+
+ /* Trigger a redraw */
+ sidebar_thumbnails->priv->start_page = -1;
+ sidebar_thumbnails->priv->end_page = -1;
+ g_idle_add ((GSourceFunc)refresh, sidebar_thumbnails);
+}
+
+static void
+ev_sidebar_tree_selection_changed (GtkTreeSelection *selection,
+ EvSidebarThumbnails *ev_sidebar_thumbnails)
+{
+ EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ int page;
+
+ if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
+ return;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->list_store),
+ &iter);
+ page = gtk_tree_path_get_indices (path)[0];
+ gtk_tree_path_free (path);
+
+ ev_page_cache_set_current_page_history (priv->page_cache, page);
+}
+
+static void
+ev_sidebar_icon_selection_changed (GtkIconView *icon_view,
+ EvSidebarThumbnails *ev_sidebar_thumbnails)
+{
+ EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
+ GtkTreePath *path;
+ GList *selected;
+ int page;
+
+ selected = gtk_icon_view_get_selected_items (icon_view);
+ if (selected == NULL)
+ return;
+
+ /* We don't handle or expect multiple selection. */
+ g_assert (selected->next == NULL);
+
+ path = selected->data;
+ page = gtk_tree_path_get_indices (path)[0];
+
+ gtk_tree_path_free (path);
+ g_list_free (selected);
+
+ ev_page_cache_set_current_page_history (priv->page_cache, page);
+}
+
+static void
+ev_sidebar_init_tree_view (EvSidebarThumbnails *ev_sidebar_thumbnails)