]> www.fi.muni.cz Git - evince.git/blob - libview/ev-document-model.c
[libview] Add continuous, dual-page and fullscreen properties to EvDocumentModel
[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         guint continuous : 1;
39         guint dual_page  : 1;
40         guint fullscreen : 1;
41
42         gdouble max_scale;
43         gdouble min_scale;
44 };
45
46 struct _EvDocumentModelClass
47 {
48         GObjectClass base_class;
49
50         /* Signals  */
51         void (* page_changed) (EvDocumentModel *model,
52                                gint             old_page,
53                                gint             new_page);
54 };
55
56 enum {
57         PROP_0,
58         PROP_DOCUMENT,
59         PROP_PAGE,
60         PROP_ROTATION,
61         PROP_SCALE,
62         PROP_SIZING_MODE,
63         PROP_CONTINUOUS,
64         PROP_DUAL_PAGE,
65         PROP_FULLSCREEN
66 };
67
68 enum
69 {
70         PAGE_CHANGED,
71         N_SIGNALS
72 };
73
74 static guint signals[N_SIGNALS] = { 0 };
75
76 G_DEFINE_TYPE (EvDocumentModel, ev_document_model, G_TYPE_OBJECT)
77
78 static void
79 ev_document_model_finalize (GObject *object)
80 {
81         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
82
83         if (model->document) {
84                 g_object_unref (model->document);
85                 model->document = NULL;
86         }
87
88         G_OBJECT_CLASS (ev_document_model_parent_class)->finalize (object);
89 }
90
91 static void
92 ev_document_model_set_property (GObject      *object,
93                                 guint         prop_id,
94                                 const GValue *value,
95                                 GParamSpec   *pspec)
96 {
97         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
98
99         switch (prop_id) {
100         case PROP_DOCUMENT:
101                 ev_document_model_set_document (model, (EvDocument *)g_value_get_object (value));
102                 break;
103         case PROP_PAGE:
104                 ev_document_model_set_page (model, g_value_get_int (value));
105                 break;
106         case PROP_ROTATION:
107                 ev_document_model_set_rotation (model, g_value_get_int (value));
108                 break;
109         case PROP_SCALE:
110                 ev_document_model_set_scale (model, g_value_get_double (value));
111                 break;
112         case PROP_SIZING_MODE:
113                 ev_document_model_set_sizing_mode (model, g_value_get_enum (value));
114                 break;
115         case PROP_CONTINUOUS:
116                 ev_document_model_set_continuous (model, g_value_get_boolean (value));
117                 break;
118         case PROP_DUAL_PAGE:
119                 ev_document_model_set_dual_page (model, g_value_get_boolean (value));
120                 break;
121         case PROP_FULLSCREEN:
122                 ev_document_model_set_fullscreen (model, g_value_get_boolean (value));
123                 break;
124         default:
125                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
126         }
127 }
128
129 static void
130 ev_document_model_get_property (GObject    *object,
131                                 guint       prop_id,
132                                 GValue     *value,
133                                 GParamSpec *pspec)
134 {
135         EvDocumentModel *model = EV_DOCUMENT_MODEL (object);
136
137         switch (prop_id) {
138         case PROP_DOCUMENT:
139                 g_value_set_object (value, model->document);
140                 break;
141         case PROP_PAGE:
142                 g_value_set_int (value, model->page);
143                 break;
144         case PROP_ROTATION:
145                 g_value_set_int (value, model->rotation);
146                 break;
147         case PROP_SCALE:
148                 g_value_set_double (value, model->scale);
149                 break;
150         case PROP_SIZING_MODE:
151                 g_value_set_enum (value, model->sizing_mode);
152                 break;
153         case PROP_CONTINUOUS:
154                 g_value_set_boolean (value, ev_document_model_get_continuous (model));
155                 break;
156         case PROP_DUAL_PAGE:
157                 g_value_set_boolean (value, ev_document_model_get_dual_page (model));
158                 break;
159         case PROP_FULLSCREEN:
160                 g_value_set_boolean (value, ev_document_model_get_fullscreen (model));
161                 break;
162         default:
163                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
164         }
165 }
166
167 static void
168 ev_document_model_class_init (EvDocumentModelClass *klass)
169 {
170         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
171
172         g_object_class->get_property = ev_document_model_get_property;
173         g_object_class->set_property = ev_document_model_set_property;
174         g_object_class->finalize = ev_document_model_finalize;
175
176         /* Properties */
177         g_object_class_install_property (g_object_class,
178                                          PROP_DOCUMENT,
179                                          g_param_spec_object ("document",
180                                                               "Document",
181                                                               "The current document",
182                                                               EV_TYPE_DOCUMENT,
183                                                               G_PARAM_READWRITE));
184         g_object_class_install_property (g_object_class,
185                                          PROP_PAGE,
186                                          g_param_spec_int ("page",
187                                                            "Page",
188                                                            "Current page",
189                                                            -1, G_MAXINT, -1,
190                                                            G_PARAM_READWRITE));
191         g_object_class_install_property (g_object_class,
192                                          PROP_ROTATION,
193                                          g_param_spec_int ("rotation",
194                                                            "Rotation",
195                                                            "Current rotation angle",
196                                                            0, 360, 0,
197                                                            G_PARAM_READWRITE));
198         g_object_class_install_property (g_object_class,
199                                          PROP_SCALE,
200                                          g_param_spec_double ("scale",
201                                                               "Scale",
202                                                               "Current scale factor",
203                                                               0., G_MAXDOUBLE, 1.,
204                                                               G_PARAM_READWRITE));
205         g_object_class_install_property (g_object_class,
206                                          PROP_SIZING_MODE,
207                                          g_param_spec_enum ("sizing-mode",
208                                                             "Sizing Mode",
209                                                             "Current sizing mode",
210                                                             EV_TYPE_SIZING_MODE,
211                                                             EV_SIZING_FIT_WIDTH,
212                                                             G_PARAM_READWRITE));
213         g_object_class_install_property (g_object_class,
214                                          PROP_CONTINUOUS,
215                                          g_param_spec_boolean ("continuous",
216                                                                "Continuous",
217                                                                "Whether document is displayed in continuous mode",
218                                                                TRUE,
219                                                                G_PARAM_READWRITE));
220         g_object_class_install_property (g_object_class,
221                                          PROP_DUAL_PAGE,
222                                          g_param_spec_boolean ("dual-page",
223                                                                "Dual Page",
224                                                                "Whether document is displayed in dual page mode",
225                                                                FALSE,
226                                                                G_PARAM_READWRITE));
227         g_object_class_install_property (g_object_class,
228                                          PROP_FULLSCREEN,
229                                          g_param_spec_boolean ("fullscreen",
230                                                                "Fullscreen",
231                                                                "Whether document is displayed in fullscreen mode",
232                                                                FALSE,
233                                                                G_PARAM_READWRITE));
234
235         /* Signals */
236         signals [PAGE_CHANGED] =
237                 g_signal_new ("page-changed",
238                               EV_TYPE_DOCUMENT_MODEL,
239                               G_SIGNAL_RUN_LAST,
240                               G_STRUCT_OFFSET (EvDocumentModelClass, page_changed),
241                               NULL, NULL,
242                               ev_view_marshal_VOID__INT_INT,
243                               G_TYPE_NONE, 2,
244                               G_TYPE_INT, G_TYPE_INT);
245 }
246
247 static void
248 ev_document_model_init (EvDocumentModel *model)
249 {
250         model->page = -1;
251         model->scale = 1.;
252         model->sizing_mode = EV_SIZING_FIT_WIDTH;
253         model->continuous = TRUE;
254         model->min_scale = 0.;
255         model->max_scale = G_MAXDOUBLE;
256 }
257
258 EvDocumentModel *
259 ev_document_model_new (void)
260 {
261         return g_object_new (EV_TYPE_DOCUMENT_MODEL, NULL);
262 }
263
264 EvDocumentModel *
265 ev_document_model_new_with_document (EvDocument *document)
266 {
267         g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);
268
269         return g_object_new (EV_TYPE_DOCUMENT_MODEL, "document", document, NULL);
270 }
271
272 void
273 ev_document_model_set_document (EvDocumentModel *model,
274                                 EvDocument      *document)
275 {
276         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
277         g_return_if_fail (EV_IS_DOCUMENT (document));
278
279         if (document == model->document)
280                 return;
281
282         if (model->document)
283                 g_object_unref (model->document);
284         model->document = g_object_ref (document);
285
286         model->n_pages = ev_document_get_n_pages (document);
287         ev_document_model_set_page (model, CLAMP (model->page, 0,
288                                                   model->n_pages - 1));
289
290         g_object_notify (G_OBJECT (model), "document");
291 }
292
293 EvDocument *
294 ev_document_model_get_document (EvDocumentModel *model)
295 {
296         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
297
298         return model->document;
299 }
300
301 void
302 ev_document_model_set_page (EvDocumentModel *model,
303                             gint             page)
304 {
305         gint old_page;
306
307         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
308
309         if (model->page == page)
310                 return;
311         if (page < 0 || (model->document && page >= model->n_pages))
312                 return;
313
314         old_page = model->page;
315         model->page = page;
316         g_signal_emit (model, signals[PAGE_CHANGED], 0, old_page, page);
317
318         g_object_notify (G_OBJECT (model), "page");
319 }
320
321 void
322 ev_document_model_set_page_by_label (EvDocumentModel *model,
323                                      const gchar     *page_label)
324 {
325         gint page;
326
327         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
328         g_return_if_fail (model->document != NULL);
329
330         if (ev_document_find_page_by_label (model->document, page_label, &page))
331                 ev_document_model_set_page (model, page);
332 }
333
334 gint
335 ev_document_model_get_page (EvDocumentModel *model)
336 {
337         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), -1);
338
339         return model->page;
340 }
341
342 void
343 ev_document_model_set_scale (EvDocumentModel *model,
344                              gdouble          scale)
345 {
346         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
347
348         scale = CLAMP (scale,
349                        model->sizing_mode == EV_SIZING_FREE ?
350                        model->min_scale : 0, model->max_scale);
351
352         if (scale == model->scale)
353                 return;
354
355         model->scale = scale;
356
357         g_object_notify (G_OBJECT (model), "scale");
358 }
359
360 gdouble
361 ev_document_model_get_scale (EvDocumentModel *model)
362 {
363         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
364
365         return model->scale;
366 }
367
368 void
369 ev_document_model_set_max_scale (EvDocumentModel *model,
370                                  gdouble          max_scale)
371 {
372         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
373
374         if (max_scale == model->max_scale)
375                 return;
376
377         model->max_scale = max_scale;
378
379         if (model->scale > max_scale)
380                 ev_document_model_set_scale (model, max_scale);
381 }
382
383 gdouble
384 ev_document_model_get_max_scale (EvDocumentModel *model)
385 {
386         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 1.0);
387
388         return model->max_scale;
389 }
390
391 void
392 ev_document_model_set_min_scale (EvDocumentModel *model,
393                                  gdouble          min_scale)
394 {
395         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
396
397         if (min_scale == model->min_scale)
398                 return;
399
400         model->min_scale = min_scale;
401
402         if (model->scale < min_scale)
403                 ev_document_model_set_scale (model, min_scale);
404 }
405
406 gdouble
407 ev_document_model_get_min_scale (EvDocumentModel *model)
408 {
409         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0.);
410
411         return model->min_scale;
412 }
413
414 void
415 ev_document_model_set_sizing_mode (EvDocumentModel *model,
416                                    EvSizingMode     mode)
417 {
418         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
419
420         if (mode == model->sizing_mode)
421                 return;
422
423         model->sizing_mode = mode;
424
425         g_object_notify (G_OBJECT (model), "sizing-mode");
426 }
427
428 EvSizingMode
429 ev_document_model_get_sizing_mode (EvDocumentModel *model)
430 {
431         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), EV_SIZING_FIT_WIDTH);
432
433         return model->sizing_mode;
434 }
435
436 void
437 ev_document_model_set_rotation (EvDocumentModel *model,
438                                 gint             rotation)
439 {
440         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
441
442         if (rotation >= 360)
443                 rotation -= 360;
444         else if (rotation < 0)
445                 rotation += 360;
446
447         if (rotation == model->rotation)
448                 return;
449
450         model->rotation = rotation;
451
452         g_object_notify (G_OBJECT (model), "rotation");
453 }
454
455 gint
456 ev_document_model_get_rotation (EvDocumentModel *model)
457 {
458         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), 0);
459
460         return model->rotation;
461 }
462
463 void
464 ev_document_model_set_continuous (EvDocumentModel *model,
465                                   gboolean         continuous)
466 {
467         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
468
469         continuous = continuous != FALSE;
470
471         if (continuous == model->continuous)
472                 return;
473
474         model->continuous = continuous;
475
476         g_object_notify (G_OBJECT (model), "continuous");
477 }
478
479 gboolean
480 ev_document_model_get_continuous (EvDocumentModel *model)
481 {
482         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), TRUE);
483
484         return model->continuous;
485 }
486
487 void
488 ev_document_model_set_dual_page (EvDocumentModel *model,
489                                  gboolean         dual_page)
490 {
491         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
492
493         dual_page = dual_page != FALSE;
494
495         if (dual_page == model->dual_page)
496                 return;
497
498         model->dual_page = dual_page;
499
500         g_object_notify (G_OBJECT (model), "dual-page");
501 }
502
503 gboolean
504 ev_document_model_get_dual_page (EvDocumentModel *model)
505 {
506         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
507
508         return model->dual_page;
509 }
510
511 void
512 ev_document_model_set_fullscreen (EvDocumentModel *model,
513                                   gboolean         fullscreen)
514 {
515         g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
516
517         fullscreen = fullscreen != FALSE;
518
519         if (fullscreen == model->fullscreen)
520                 return;
521
522         model->fullscreen = fullscreen;
523
524         g_object_notify (G_OBJECT (model), "fullscreen");
525 }
526
527 gboolean
528 ev_document_model_get_fullscreen (EvDocumentModel *model)
529 {
530         g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), FALSE);
531
532         return model->fullscreen;
533 }