]> www.fi.muni.cz Git - evince.git/blob - shell/ev-page-action.c
Clear the list store when setting document
[evince.git] / shell / ev-page-action.c
1 /*
2  *  Copyright (C) 2003, 2004 Marco Pesenti Gritti
3  *  Copyright (C) 2003, 2004 Christian Persch
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  *  $Id$
20  */
21
22 #include "config.h"
23
24 #include "ev-page-action.h"
25 #include "ev-window.h"
26
27 #include <glib/gi18n.h>
28 #include <gtk/gtkentry.h>
29 #include <gtk/gtktoolitem.h>
30 #include <gtk/gtklabel.h>
31 #include <gtk/gtkhbox.h>
32 #include <stdlib.h>
33
34 struct _EvPageActionPrivate
35 {
36         int current_page;
37         int total_pages;
38 };
39
40 enum
41 {
42         PROP_0,
43         PROP_CURRENT_PAGE,
44         PROP_TOTAL_PAGES
45 };
46
47 static void ev_page_action_init       (EvPageAction *action);
48 static void ev_page_action_class_init (EvPageActionClass *class);
49
50 enum
51 {
52         GOTO_PAGE_SIGNAL,
53         LAST_SIGNAL
54 };
55
56 static guint signals[LAST_SIGNAL] = { 0 };
57
58 G_DEFINE_TYPE (EvPageAction, ev_page_action, GTK_TYPE_ACTION)
59
60 #define EV_PAGE_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_PAGE_ACTION, EvPageActionPrivate))
61
62 static void
63 update_label (GtkAction *action, gpointer dummy, GtkWidget *proxy)
64 {
65         EvPageAction *page = EV_PAGE_ACTION (action);
66         char *text;
67         GtkWidget *label;
68
69         label = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "label"));
70
71         text = g_strdup_printf (_("of %d"), page->priv->total_pages);
72         gtk_label_set_text (GTK_LABEL (label), text);
73 }
74
75 static void
76 update_entry (EvPageAction *page_action, GtkWidget *entry)
77 {
78         char *text;
79
80         text = g_strdup_printf ("%d", page_action->priv->current_page);
81         gtk_entry_set_text (GTK_ENTRY (entry), text);
82         g_free (text);
83 }
84
85 static void
86 sync_entry (GtkAction *action, gpointer dummy, GtkWidget *proxy)
87 {
88         EvPageAction *page_action = EV_PAGE_ACTION (action);
89         GtkWidget *entry;
90
91         entry = GTK_WIDGET (g_object_get_data (G_OBJECT (proxy), "entry"));
92         update_entry (page_action, entry);
93 }
94
95 static void
96 activate_cb (GtkWidget *entry, GtkAction *action)
97 {
98         EvPageAction *page_action = EV_PAGE_ACTION (action);
99         const char *text;
100         char *endptr;
101         int page = -1;
102
103         text = gtk_entry_get_text (GTK_ENTRY (entry));
104         if (text) {
105                 long value;
106
107                 value = strtol (text, &endptr, 10);
108                 if (endptr[0] == '\0') {
109                         /* Page number is an integer */
110                         page = MIN (G_MAXINT, value);
111                 }
112         }
113
114         if (page > 0 && page <= page_action->priv->total_pages) {
115                 g_signal_emit (action, signals[GOTO_PAGE_SIGNAL], 0, page);
116         } else {
117                 update_entry (page_action, entry);
118         }
119 }
120
121 static void
122 entry_size_request_cb (GtkWidget      *entry,
123                        GtkRequisition *requisition,
124                        GtkAction      *action)
125 {
126         PangoContext *context;
127         PangoFontMetrics *metrics;
128         int digit_width;
129
130         context = gtk_widget_get_pango_context (entry);
131         metrics = pango_context_get_metrics
132                         (context, entry->style->font_desc,
133                          pango_context_get_language (context));
134
135         digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
136         digit_width = PANGO_SCALE * ((digit_width + PANGO_SCALE - 1) / PANGO_SCALE);
137
138         pango_font_metrics_unref (metrics);
139
140         /* Space for 4 digits. Probably 3 would be enough but it doesnt
141            seem to possible to calculate entry borders without using
142            gtk private info */
143         requisition->width = PANGO_PIXELS (digit_width * 4);
144 }
145
146 static GtkWidget *
147 create_tool_item (GtkAction *action)
148 {
149         GtkWidget *hbox, *entry, *item, *label;
150
151         hbox = gtk_hbox_new (FALSE, 6);
152         gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); 
153         gtk_widget_show (hbox);
154
155         item = GTK_WIDGET (gtk_tool_item_new ());
156         gtk_widget_show (item);
157
158         entry = gtk_entry_new ();
159         g_signal_connect (entry, "size_request",
160                           G_CALLBACK (entry_size_request_cb),
161                           action);
162         g_object_set_data (G_OBJECT (item), "entry", entry);
163         gtk_widget_show (entry);
164
165         g_signal_connect (entry, "activate",
166                           G_CALLBACK (activate_cb),
167                           action);
168
169         label = gtk_label_new ("");
170         g_object_set_data (G_OBJECT (item), "label", label);
171         update_label (action, NULL, item);
172         gtk_widget_show (label);
173
174         gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
175         gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
176         gtk_container_add (GTK_CONTAINER (item), hbox);
177
178         return item;
179 }
180
181 static void
182 connect_proxy (GtkAction *action, GtkWidget *proxy)
183 {
184         if (GTK_IS_TOOL_ITEM (proxy))
185         {
186                 g_signal_connect_object (action, "notify::total-pages",
187                                          G_CALLBACK (update_label),
188                                          proxy, 0);
189                 g_signal_connect_object (action, "notify::current-page",
190                                          G_CALLBACK (sync_entry),
191                                          proxy, 0);
192         }
193
194         GTK_ACTION_CLASS (ev_page_action_parent_class)->connect_proxy (action, proxy);
195 }
196
197 static void
198 ev_page_action_init (EvPageAction *action)
199 {
200         action->priv = EV_PAGE_ACTION_GET_PRIVATE (action);
201 }
202
203 static void
204 ev_page_action_finalize (GObject *object)
205 {
206         G_OBJECT_CLASS (ev_page_action_parent_class)->finalize (object);
207 }
208
209 static void
210 ev_page_action_set_property (GObject *object,
211                              guint prop_id,
212                              const GValue *value,
213                              GParamSpec *pspec)
214 {
215         EvPageAction *page = EV_PAGE_ACTION (object);
216
217         switch (prop_id)
218         {
219                 case PROP_CURRENT_PAGE:
220                         page->priv->current_page = g_value_get_int (value);
221                         break;
222                 case PROP_TOTAL_PAGES:
223                         page->priv->total_pages = g_value_get_int (value);
224                         break;
225         }
226 }
227
228 static void
229 ev_page_action_get_property (GObject *object,
230                              guint prop_id,
231                              GValue *value,
232                              GParamSpec *pspec)
233 {
234         EvPageAction *page = EV_PAGE_ACTION (object);
235
236         switch (prop_id)
237         {
238                 case PROP_CURRENT_PAGE:
239                         g_value_set_int (value, page->priv->current_page);
240                         break;
241                 case PROP_TOTAL_PAGES:
242                         g_value_set_int (value, page->priv->total_pages);
243                         break;
244         }
245 }
246
247 void
248 ev_page_action_set_current_page (EvPageAction *page, int current_page)
249 {
250         g_object_set (page, "current-page", current_page, NULL);
251 }
252
253 void
254 ev_page_action_set_total_pages (EvPageAction *page, int total_pages)
255 {
256         g_object_set (page, "total-pages", total_pages, NULL);
257 }
258
259 static void
260 ev_page_action_class_init (EvPageActionClass *class)
261 {
262         GObjectClass *object_class = G_OBJECT_CLASS (class);
263         GtkActionClass *action_class = GTK_ACTION_CLASS (class);
264
265         object_class->finalize = ev_page_action_finalize;
266         object_class->set_property = ev_page_action_set_property;
267         object_class->get_property = ev_page_action_get_property;
268
269         action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;
270         action_class->create_tool_item = create_tool_item;
271         action_class->connect_proxy = connect_proxy;
272
273         signals[GOTO_PAGE_SIGNAL] =
274                 g_signal_new ("goto_page",
275                               G_OBJECT_CLASS_TYPE (object_class),
276                               G_SIGNAL_RUN_FIRST,
277                               G_STRUCT_OFFSET (EvPageActionClass, goto_page),
278                               NULL, NULL,
279                               g_cclosure_marshal_VOID__INT,
280                               G_TYPE_NONE,
281                               1,
282                               G_TYPE_INT);
283
284         g_object_class_install_property (object_class,
285                                          PROP_CURRENT_PAGE,
286                                          g_param_spec_int ("current-page",
287                                                            "Current Page",
288                                                            "The number of current page",
289                                                            0,
290                                                            G_MAXINT,
291                                                            0,
292                                                            G_PARAM_READWRITE));
293
294         g_object_class_install_property (object_class,
295                                          PROP_TOTAL_PAGES,
296                                          g_param_spec_int ("total-pages",
297                                                            "Total Pages",
298                                                            "The total number of pages",
299                                                            0,
300                                                            G_MAXINT,
301                                                            0,
302                                                            G_PARAM_READWRITE));
303
304         g_type_class_add_private (object_class, sizeof (EvPageActionPrivate));
305 }