]> www.fi.muni.cz Git - evince.git/blob - libview/ev-document-model.c
Remove EvPageCache and use EvDocumentModel instead
[evince.git] / libview / ev-document-model.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2009 Carlos Garcia Campos
4  *  Copyright (C) 2005 Red Hat, Inc
5  *
6  * Evince is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Evince is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include "ev-document-model.h"
24 #include "ev-view-type-builtins.h"
25 #include "ev-view-marshal.h"
26
27 struct _EvDocumentModel
28 {
29         GObject base;
30
31         EvDocument *document;
32         gint n_pages;
33
34         gint page;
35         gint rotation;
36         gdouble scale;
37         EvSizingMode sizing_mode;
38
39         gdouble max_scale;
40         gdouble min_scale;
41 };
42
43 struct _EvDocumentModelClass
44 {
45         GObjectClass base_class;
46
47         /* Signals  */
48         void (* page_changed) (EvDocumentModel *model,
49                                gint             old_page,
50                                gint             new_page);
51 };
52
53 enum {
54         PROP_0,
55         PROP_DOCUMENT,
56         PROP_PAGE,
57         PROP_ROTATION,
58         PROP_SCALE,
59         PROP_SIZING_MODE
60 };
61
62 enum
63 {
64         PAGE_CHANGED,
65         N_SIGNALS
66 };
67
68 static guint signals[N_SIGNALS] = { 0 };
69
70 G_DEFINE_TYPE (EvDocumentModel, ev_document_model, G_TYPE_OBJECT)
71
72 static void
73 ev_document_model_finalize (GObject *object)
74 {
75         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
76
77         if (model->document) {
78                 g_object_unref (model->document);
79                 model->document = NULL;
80         }
81
82         G_OBJECT_CLASS (ev_document_model_parent_class)->finalize (object);
83 }
84
85 static void
86 ev_document_model_set_property (GObject      *object,
87                                 guint         prop_id,
88                                 const GValue *value,
89                                 GParamSpec   *pspec)
90 {
91         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
92
93         switch (prop_id) {
94         case PROP_DOCUMENT:
95                 ev_document_model_set_document (model, (EvDocument *)g_value_get_object (value));
96                 break;
97         case PROP_PAGE:
98                 ev_document_model_set_page (model, g_value_get_int (value));
99                 break;
100         case PROP_ROTATION:
101                 ev_document_model_set_rotation (model, g_value_get_int (value));
102                 break;
103         case PROP_SCALE:
104                 ev_document_model_set_scale (model, g_value_get_double (value));
105                 break;
106         case PROP_SIZING_MODE:
107                 ev_document_model_set_sizing_mode (model, g_value_get_enum (value));
108                 break;
109         default:
110                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
111         }
112 }
113
114 static void
115 ev_document_model_get_property (GObject    *object,
116                                 guint       prop_id,
117                                 GValue     *value,
118                                 GParamSpec *pspec)
119 {
120         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
121
122         switch (prop_id) {
123         case PROP_DOCUMENT:
124                 g_value_set_object (value, model->document);
125                 break;
126         case PROP_PAGE:
127                 g_value_set_int (value, model->page);
128                 break;
129         case PROP_ROTATION:
130                 g_value_set_int (value, model->rotation);
131                 break;
132         case PROP_SCALE:
133                 g_value_set_double (value, model->scale);
134                 break;
135         case PROP_SIZING_MODE:
136                 g_value_set_enum (value, model->sizing_mode);
137                 break;
138         default:
139                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140         }
141 }
142
143 static void
144 ev_document_model_class_init (EvDocumentModelClass *klass)
145 {
146         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
147
148         g_object_class->get_property = ev_document_model_get_property;
149         g_object_class->set_property = ev_document_model_set_property;
150         g_object_class->finalize = ev_document_model_finalize;
151
152         /* Properties */
153         g_object_class_install_property (g_object_class,
154                                          PROP_DOCUMENT,
155                                          g_param_spec_object ("document",
156                                                               "Document",
157                                                               "The current document",
158                                                               EV_TYPE_DOCUMENT,
159                                                               G_PARAM_READWRITE));
160         g_object_class_install_property (g_object_class,
161                                          PROP_PAGE,
162                                          g_param_spec_int ("page",
163                                                            "Page",
164                                                            "Current page",
165                                                            -1, G_MAXINT, -1,
166                                                            G_PARAM_READWRITE));
167         g_object_class_install_property (g_object_class,
168                                          PROP_ROTATION,
169                                          g_param_spec_int ("rotation",
170                                                            "Rotation",
171                                                            "Current rotation angle",
172                                                            0, 360, 0,
173                                                            G_PARAM_READWRITE));
174         g_object_class_install_property (g_object_class,
175                                          PROP_SCALE,
176                                          g_param_spec_double ("scale",
177                                                               "Scale",
178                                                               "Current scale factor",
179                                                               0., G_MAXDOUBLE, 1.,
180                                                               G_PARAM_READWRITE));
181         g_object_class_install_property (g_object_class,
182                                          PROP_SIZING_MODE,
183                                          g_param_spec_enum ("sizing-mode",
184                                                             "Sizing Mode",
185                                                             "Current sizing mode",
186                                                             EV_TYPE_SIZING_MODE,
187                                                             EV_SIZING_FIT_WIDTH,
188                                                             G_PARAM_READWRITE));
189
190         /* Signals */
191         signals [PAGE_CHANGED] =
192                 g_signal_new ("page-changed",
193                               EV_TYPE_DOCUMENT_MODEL,
194                               G_SIGNAL_RUN_LAST,
195                               G_STRUCT_OFFSET (EvDocumentModelClass, page_changed),
196                               NULL, NULL,
197                               ev_view_marshal_VOID__INT_INT,
198                               G_TYPE_NONE, 2,
199                               G_TYPE_INT, G_TYPE_INT);
200 }
201
202 static void
203 ev_document_model_init (EvDocumentModel *model)
204 {
205         model->page = -1;
206         model->scale = 1.;
207         model->sizing_mode = EV_SIZING_FIT_WIDTH;
208         model->min_scale = 0.;
209         model->max_scale = G_MAXDOUBLE;
210 }
211
212 EvDocumentModel *
213 ev_document_model_new (void)
214 {
215         return g_object_new (EV_TYPE_DOCUMENT_MODEL, NULL);
216 }
217
218 EvDocumentModel *
219 ev_document_model_new_with_document (EvDocument *document)
220 {
221         g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
222
223         return g_object_new (EV_TYPE_DOCUMENT_MODEL, "document", document, NULL);
224 }
225
226 void
227 ev_document_model_set_document (EvDocumentModel *model,
228                                 EvDocument      *document)
229 {
230         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
231         g_return_if_fail (EV_IS_DOCUMENT (document));
232
233         if (document == model->document)
234                 return;
235
236         if (model->document)
237                 g_object_unref (model->document);
238         model->document = g_object_ref (document);
239
240         model->n_pages = ev_document_get_n_pages (document);
241         ev_document_model_set_page (model, CLAMP (model->page, 0,
242                                                   model->n_pages - 1));
243
244         g_object_notify (G_OBJECT (model), "document");
245 }
246
247 EvDocument *
248 ev_document_model_get_document (EvDocumentModel *model)
249 {
250         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
251
252         return model->document;
253 }
254
255 void
256 ev_document_model_set_page (EvDocumentModel *model,
257                             gint             page)
258 {
259         gint old_page;
260
261         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
262
263         if (model->page == page)
264                 return;
265         if (page < 0 || (model->document && page >= model->n_pages))
266                 return;
267
268         old_page = model->page;
269         model->page = page;
270         g_signal_emit (model, signals[PAGE_CHANGED], 0, old_page, page);
271
272         g_object_notify (G_OBJECT (model), "page");
273 }
274
275 void
276 ev_document_model_set_page_by_label (EvDocumentModel *model,
277                                      const gchar     *page_label)
278 {
279         gint page;
280
281         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
282         g_return_if_fail (model->document != NULL);
283
284         if (ev_document_find_page_by_label (model->document, page_label, &page))
285                 ev_document_model_set_page (model, page);
286 }
287
288 gint
289 ev_document_model_get_page (EvDocumentModel *model)
290 {
291         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), -1);
292
293         return model->page;
294 }
295
296 void
297 ev_document_model_set_scale (EvDocumentModel *model,
298                              gdouble          scale)
299 {
300         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
301
302         scale = CLAMP (scale,
303                        model->sizing_mode == EV_SIZING_FREE ?
304                        model->min_scale : 0, model->max_scale);
305
306         if (scale == model->scale)
307                 return;
308
309         model->scale = scale;
310
311         g_object_notify (G_OBJECT (model), "scale");
312 }
313
314 gdouble
315 ev_document_model_get_scale (EvDocumentModel *model)
316 {
317         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
318
319         return model->scale;
320 }
321
322 void
323 ev_document_model_set_max_scale (EvDocumentModel *model,
324                                  gdouble          max_scale)
325 {
326         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
327
328         if (max_scale == model->max_scale)
329                 return;
330
331         model->max_scale = max_scale;
332
333         if (model->scale > max_scale)
334                 ev_document_model_set_scale (model, max_scale);
335 }
336
337 gdouble
338 ev_document_model_get_max_scale (EvDocumentModel *model)
339 {
340         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
341
342         return model->max_scale;
343 }
344
345 void
346 ev_document_model_set_min_scale (EvDocumentModel *model,
347                                  gdouble          min_scale)
348 {
349         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
350
351         if (min_scale == model->min_scale)
352                 return;
353
354         model->min_scale = min_scale;
355
356         if (model->scale < min_scale)
357                 ev_document_model_set_scale (model, min_scale);
358 }
359
360 gdouble
361 ev_document_model_get_min_scale (EvDocumentModel *model)
362 {
363         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0.);
364
365         return model->min_scale;
366 }
367
368 void
369 ev_document_model_set_sizing_mode (EvDocumentModel *model,
370                                    EvSizingMode     mode)
371 {
372         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
373
374         if (mode == model->sizing_mode)
375                 return;
376
377         model->sizing_mode = mode;
378
379         g_object_notify (G_OBJECT (model), "sizing-mode");
380 }
381
382 EvSizingMode
383 ev_document_model_get_sizing_mode (EvDocumentModel *model)
384 {
385         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), EV_SIZING_FIT_WIDTH);
386
387         return model->sizing_mode;
388 }
389
390 void
391 ev_document_model_set_rotation (EvDocumentModel *model,
392                                 gint             rotation)
393 {
394         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
395
396         if (rotation >= 360)
397                 rotation -= 360;
398         else if (rotation < 0)
399                 rotation += 360;
400
401         if (rotation == model->rotation)
402                 return;
403
404         model->rotation = rotation;
405
406         g_object_notify (G_OBJECT (model), "rotation");
407 }
408
409 gint
410 ev_document_model_get_rotation (EvDocumentModel *model)
411 {
412         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0);
413
414         return model->rotation;
415 }
416