]> www.fi.muni.cz Git - evince.git/blob - shell/ev-sidebar-thumbnails.c
New misc file to do simple drop shadows.
[evince.git] / shell / ev-sidebar-thumbnails.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2004 Red Hat, Inc.
4  *  Copyright (C) 2004 Anders Carlsson <andersca@gnome.org>
5  *
6  *  Authors:
7  *    Jonathan Blandford <jrb@alum.mit.edu>
8  *    Anders Carlsson <andersca@gnome.org>
9  *
10  * Evince is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * Evince is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <gtk/gtk.h>
31
32 #include "ev-sidebar-thumbnails.h"
33 #include "ev-document-thumbnails.h"
34 #include "ev-utils.h"
35
36 #define THUMBNAIL_WIDTH 75
37 /* Amount of time we devote to each iteration of the idle, in microseconds */
38 #define IDLE_WORK_LENGTH 5000
39
40 struct _EvSidebarThumbnailsPrivate {
41         GtkWidget *tree_view;
42         GtkListStore *list_store;
43         EvDocument *document;
44         
45         guint idle_id;
46         gint current_page, n_pages;
47 };
48
49 enum {
50         COLUMN_PAGE_STRING,
51         COLUMN_PIXBUF,
52         NUM_COLUMNS
53 };
54
55 static GtkVBoxClass *parent_class;
56
57 G_DEFINE_TYPE (EvSidebarThumbnails, ev_sidebar_thumbnails, GTK_TYPE_VBOX);
58
59 #define EV_SIDEBAR_THUMBNAILS_GET_PRIVATE(object) \
60         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_THUMBNAILS, EvSidebarThumbnailsPrivate));
61
62 static void
63 ev_sidebar_thumbnails_destroy (GtkObject *object)
64 {
65         EvSidebarThumbnails *ev_sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (object);
66         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
67         
68         if (priv->idle_id != 0) {
69                 g_source_remove (priv->idle_id);
70
71                 priv->idle_id = 0;
72         }
73         
74         GTK_OBJECT_CLASS (parent_class)->destroy (object);
75 }
76
77 static void
78 ev_sidebar_thumbnails_class_init (EvSidebarThumbnailsClass *ev_sidebar_thumbnails_class)
79 {
80         GObjectClass *g_object_class;
81         GtkObjectClass *gtk_object_class;
82         
83         g_object_class = G_OBJECT_CLASS (ev_sidebar_thumbnails_class);
84         gtk_object_class = GTK_OBJECT_CLASS (ev_sidebar_thumbnails_class);
85
86         parent_class = g_type_class_peek_parent (ev_sidebar_thumbnails_class);
87         
88         gtk_object_class->destroy = ev_sidebar_thumbnails_destroy;
89         
90         g_type_class_add_private (g_object_class, sizeof (EvSidebarThumbnailsPrivate));
91
92 }
93
94 static void
95 ev_sidebar_thumbnails_init (EvSidebarThumbnails *ev_sidebar_thumbnails)
96 {
97         GtkWidget *swindow;
98         EvSidebarThumbnailsPrivate *priv;
99         GtkCellRenderer *renderer;
100
101         priv = ev_sidebar_thumbnails->priv = EV_SIDEBAR_THUMBNAILS_GET_PRIVATE (ev_sidebar_thumbnails);
102
103         priv->list_store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF);
104         priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->list_store));
105
106         gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
107         renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
108                                  "xpad", 2,
109                                  "ypad", 2,
110                                  NULL);
111         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
112                                                      NULL, renderer,
113                                                      "pixbuf", 1,
114                                                      NULL);
115         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
116                                                      NULL, gtk_cell_renderer_text_new (),
117                                                      "markup", 0, NULL);
118         
119         g_object_unref (priv->list_store);
120
121         swindow = gtk_scrolled_window_new (NULL, NULL);
122         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
123                                         GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
124         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
125                                              GTK_SHADOW_IN);
126
127         gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
128         gtk_box_pack_start (GTK_BOX (ev_sidebar_thumbnails), swindow, TRUE, TRUE, 0);
129         
130         gtk_widget_show_all (swindow);
131 }
132
133 GtkWidget *
134 ev_sidebar_thumbnails_new (void)
135 {
136         GtkWidget *ev_sidebar_thumbnails;
137
138         ev_sidebar_thumbnails = g_object_new (EV_TYPE_SIDEBAR_THUMBNAILS, NULL);
139
140         return ev_sidebar_thumbnails;
141 }
142
143 static gboolean
144 do_one_iteration (EvSidebarThumbnails *ev_sidebar_thumbnails)
145 {
146         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
147         GdkPixbuf *pixbuf;
148         GtkTreePath *path;
149         GtkTreeIter iter;
150
151         pixbuf = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (priv->document),
152                                                        priv->current_page, THUMBNAIL_WIDTH);
153
154         path = gtk_tree_path_new_from_indices (priv->current_page, -1);
155         gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
156         gtk_tree_path_free (path);
157
158         gtk_list_store_set (priv->list_store, &iter,
159                             COLUMN_PIXBUF, pixbuf,
160                             -1);
161
162         g_object_unref (pixbuf);
163         
164         priv->current_page++;
165         
166         if (priv->current_page == priv->n_pages)
167                 return FALSE;
168         else
169                 return TRUE;
170 }
171
172 static gboolean
173 populate_thumbnails_idle (gpointer data)
174 {
175         GTimer *timer;
176         gint i;
177         gulong microseconds = 0;
178
179         EvSidebarThumbnails *ev_sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (data);
180         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
181
182         if (priv->current_page == priv->n_pages) {
183                 priv->idle_id = 0;
184                 return FALSE;
185         }
186
187         timer = g_timer_new ();
188         i = 0;
189         g_timer_start (timer);
190         while (do_one_iteration (ev_sidebar_thumbnails)) {
191                 i++;
192                 g_timer_elapsed (timer, &microseconds);
193                 if (microseconds > IDLE_WORK_LENGTH)
194                         break;
195         }
196         g_timer_destroy (timer);
197 #if 0
198         g_print ("%d rows done this idle in %d\n", i, (int)microseconds);
199 #endif
200
201         return TRUE;
202 }
203
204 void
205 ev_sidebar_thumbnails_set_document (EvSidebarThumbnails *sidebar_thumbnails,
206                                     EvDocument          *document)
207 {
208         GtkIconTheme *theme;
209         GdkPixbuf *loading_icon;
210         gint i, n_pages;
211         EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
212         
213         g_return_if_fail (EV_IS_DOCUMENT_THUMBNAILS (document));
214
215         if (priv->idle_id != 0) {
216                 g_source_remove (priv->idle_id);
217         }
218         
219         theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (sidebar_thumbnails)));
220
221         loading_icon = gtk_icon_theme_load_icon (theme, "gnome-fs-loading-icon",
222                                                  THUMBNAIL_WIDTH, 0, NULL);
223
224         n_pages = ev_document_get_n_pages (document);
225         
226         for (i = 0; i < n_pages; i++) {
227                 GtkTreeIter iter;
228                 gchar *page;
229
230                 page = g_strdup_printf ("<i>%d</i>", i + 1);
231                 gtk_list_store_append (sidebar_thumbnails->priv->list_store,
232                                        &iter);
233                 gtk_list_store_set (sidebar_thumbnails->priv->list_store,
234                                     &iter,
235                                     COLUMN_PAGE_STRING, page,
236                                     COLUMN_PIXBUF, loading_icon,
237                                     -1);
238                 g_free (page);
239         }
240
241         priv->document = document;
242         priv->idle_id = g_idle_add (populate_thumbnails_idle, sidebar_thumbnails);
243         priv->n_pages = n_pages;
244         priv->current_page = 0;
245 }
246