]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-link-dest.c
Do not change left, top and zoom values when they are null in PDF
[evince.git] / libdocument / ev-link-dest.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
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 "ev-link-dest.h"
22
23 enum {
24         PROP_0,
25         PROP_TYPE,
26         PROP_PAGE,
27         PROP_LEFT,
28         PROP_TOP,
29         PROP_BOTTOM,
30         PROP_RIGHT,
31         PROP_ZOOM,
32         PROP_CHANGE,
33         PROP_NAMED,
34         PROP_PAGE_LABEL
35 };
36
37 typedef enum {
38         EV_DEST_CHANGE_TOP    = 1 << 0,
39         EV_DEST_CHANGE_LEFT   = 1 << 1,
40         EV_DEST_CHANGE_ZOOM   = 1 << 2
41 } EvDestChange;
42
43 struct _EvLinkDest {
44         GObject base_instance;
45         
46         EvLinkDestPrivate *priv;
47 };
48
49 struct _EvLinkDestClass {
50         GObjectClass base_class;
51 };
52
53 struct _EvLinkDestPrivate {
54         EvLinkDestType type;
55         int            page;
56         double         top;
57         double         left;
58         double         bottom;
59         double         right;
60         double         zoom;
61         EvDestChange   change;
62         gchar         *named;
63         gchar         *page_label;
64 };
65
66 G_DEFINE_TYPE (EvLinkDest, ev_link_dest, G_TYPE_OBJECT)
67
68 #define EV_LINK_DEST_GET_PRIVATE(object) \
69         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_LINK_DEST, EvLinkDestPrivate))
70
71 GType
72 ev_link_dest_type_get_type (void)
73 {
74         static GType type = 0;
75
76         if (G_UNLIKELY (type == 0)) {
77                 static const GEnumValue values[] = {
78                         { EV_LINK_DEST_TYPE_PAGE, "EV_LINK_DEST_TYPE_PAGE", "page" },
79                         { EV_LINK_DEST_TYPE_XYZ, "EV_LINK_DEST_TYPE_XYZ", "xyz" },
80                         { EV_LINK_DEST_TYPE_FIT, "EV_LINK_DEST_TYPE_FIT", "fit" },
81                         { EV_LINK_DEST_TYPE_FITH, "EV_LINK_DEST_TYPE_FITH", "fith" },
82                         { EV_LINK_DEST_TYPE_FITV, "EV_LINK_DEST_TYPE_FITV", "fitv" },
83                         { EV_LINK_DEST_TYPE_FITR, "EV_LINK_DEST_TYPE_FITR", "fitr" },
84                         { EV_LINK_DEST_TYPE_NAMED, "EV_LINK_DEST_TYPE_NAMED", "named" },
85                         { EV_LINK_DEST_TYPE_PAGE_LABEL, "EV_LINK_DEST_TYPE_PAGE_LABEL", "page_label" },
86                         { EV_LINK_DEST_TYPE_UNKNOWN, "EV_LINK_DEST_TYPE_UNKNOWN", "unknown" },
87                         { 0, NULL, NULL }
88                 };
89
90                 type = g_enum_register_static ("EvLinkDestType", values);
91         }
92
93         return type;
94 }
95
96 EvLinkDestType
97 ev_link_dest_get_dest_type (EvLinkDest *self)
98 {
99         g_return_val_if_fail (EV_IS_LINK_DEST (self), 0);
100
101         return self->priv->type;
102 }
103
104 gint
105 ev_link_dest_get_page (EvLinkDest *self)
106 {
107         g_return_val_if_fail (EV_IS_LINK_DEST (self), -1);
108
109         return self->priv->page;
110 }
111
112 gdouble
113 ev_link_dest_get_top (EvLinkDest *self,
114                       gboolean   *change_top)
115 {
116         g_return_val_if_fail (EV_IS_LINK_DEST (self), 0);
117
118         if (change_top)
119                 *change_top = (self->priv->change & EV_DEST_CHANGE_TOP);
120         
121         return self->priv->top;
122 }
123
124 gdouble
125 ev_link_dest_get_left (EvLinkDest *self,
126                        gboolean   *change_left)
127 {
128         g_return_val_if_fail (EV_IS_LINK_DEST (self), 0);
129
130         if (change_left)
131                 *change_left = (self->priv->change & EV_DEST_CHANGE_LEFT);
132
133         return self->priv->left;
134 }
135
136 gdouble
137 ev_link_dest_get_bottom (EvLinkDest *self)
138 {
139         g_return_val_if_fail (EV_IS_LINK_DEST (self), 0);
140
141         return self->priv->bottom;
142 }
143
144 gdouble
145 ev_link_dest_get_right (EvLinkDest *self)
146 {
147         g_return_val_if_fail (EV_IS_LINK_DEST (self), 0);
148
149         return self->priv->right;
150 }
151
152 gdouble
153 ev_link_dest_get_zoom (EvLinkDest *self,
154                        gboolean   *change_zoom)
155 {
156         g_return_val_if_fail (EV_IS_LINK_DEST (self), 0);
157
158         if (change_zoom)
159                 *change_zoom = (self->priv->change & EV_DEST_CHANGE_ZOOM);
160
161         return self->priv->zoom;
162 }
163
164 const gchar *
165 ev_link_dest_get_named_dest (EvLinkDest *self)
166 {
167         g_return_val_if_fail (EV_IS_LINK_DEST (self), NULL);
168
169         return self->priv->named;
170 }
171
172 const gchar *
173 ev_link_dest_get_page_label (EvLinkDest *self)
174 {
175         g_return_val_if_fail (EV_IS_LINK_DEST (self), NULL);
176
177         return self->priv->page_label;
178 }
179
180 static void
181 ev_link_dest_get_property (GObject    *object,
182                            guint       prop_id,
183                            GValue     *value,
184                            GParamSpec *param_spec)
185 {
186         EvLinkDest *self;
187
188         self = EV_LINK_DEST (object);
189
190         switch (prop_id) {
191                 case PROP_TYPE:
192                         g_value_set_enum (value, self->priv->type);
193                         break;
194                 case PROP_PAGE:
195                         g_value_set_int (value, self->priv->page);
196                         break;
197                 case PROP_TOP:
198                         g_value_set_double (value, self->priv->top);
199                         break;
200                 case PROP_LEFT:
201                         g_value_set_double (value, self->priv->left);
202                         break;
203                 case PROP_BOTTOM:
204                         g_value_set_double (value, self->priv->bottom);
205                         break;
206                 case PROP_RIGHT:
207                         g_value_set_double (value, self->priv->left);
208                         break;
209                 case PROP_ZOOM:
210                         g_value_set_double (value, self->priv->zoom);
211                         break;
212                 case PROP_CHANGE:
213                         g_value_set_uint (value, self->priv->change);
214                         break;
215                 case PROP_NAMED:
216                         g_value_set_string (value, self->priv->named);
217                         break;
218                 case PROP_PAGE_LABEL:
219                         g_value_set_string (value, self->priv->page_label);
220                         break;
221                 default:
222                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
223                                                            prop_id,
224                                                            param_spec);
225                         break;
226         }
227 }
228
229 static void
230 ev_link_dest_set_property (GObject      *object,
231                            guint         prop_id,
232                            const GValue *value,
233                            GParamSpec   *param_spec)
234 {
235         EvLinkDest *self = EV_LINK_DEST (object);
236
237         switch (prop_id) {
238                 case PROP_TYPE:
239                         self->priv->type = g_value_get_enum (value);
240                         break;
241                 case PROP_PAGE:
242                         self->priv->page = g_value_get_int (value);
243                         break;
244                 case PROP_TOP:
245                         self->priv->top = g_value_get_double (value);
246                         break;
247                 case PROP_LEFT:
248                         self->priv->left = g_value_get_double (value);
249                         break;
250                 case PROP_BOTTOM:
251                         self->priv->bottom = g_value_get_double (value);
252                         break;
253                 case PROP_RIGHT:
254                         self->priv->right = g_value_get_double (value);
255                         break;
256                 case PROP_ZOOM:
257                         self->priv->zoom = g_value_get_double (value);
258                         break;
259                 case PROP_CHANGE:
260                         self->priv->change = g_value_get_uint (value);
261                         break;
262                 case PROP_NAMED:
263                         self->priv->named = g_value_dup_string (value);
264                         break;
265                 case PROP_PAGE_LABEL:
266                         self->priv->page_label = g_value_dup_string (value);
267                         break;
268                 default:
269                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
270                                                            prop_id,
271                                                            param_spec);
272                         break;
273         }
274 }
275
276 static void
277 ev_link_dest_finalize (GObject *object)
278 {
279         EvLinkDestPrivate *priv;
280
281         priv = EV_LINK_DEST (object)->priv;
282
283         if (priv->named) {
284                 g_free (priv->named);
285                 priv->named = NULL;
286         }
287         if (priv->page_label) {
288                 g_free (priv->page_label);
289                 priv->page_label = NULL;
290         }
291
292         G_OBJECT_CLASS (ev_link_dest_parent_class)->finalize (object);
293 }
294
295 static void
296 ev_link_dest_init (EvLinkDest *ev_link_dest)
297 {
298         ev_link_dest->priv = EV_LINK_DEST_GET_PRIVATE (ev_link_dest);
299
300         ev_link_dest->priv->named = NULL;
301 }
302
303 static void
304 ev_link_dest_class_init (EvLinkDestClass *ev_link_dest_class)
305 {
306         GObjectClass *g_object_class;
307
308         g_object_class = G_OBJECT_CLASS (ev_link_dest_class);
309
310         g_object_class->set_property = ev_link_dest_set_property;
311         g_object_class->get_property = ev_link_dest_get_property;
312
313         g_object_class->finalize = ev_link_dest_finalize;
314
315         g_type_class_add_private (g_object_class, sizeof (EvLinkDestPrivate));
316
317         g_object_class_install_property (g_object_class,
318                                          PROP_TYPE,
319                                          g_param_spec_enum  ("type",
320                                                              "Dest Type",
321                                                              "The destination type",
322                                                              EV_TYPE_LINK_DEST_TYPE,
323                                                              EV_LINK_DEST_TYPE_UNKNOWN,
324                                                              G_PARAM_READWRITE |
325                                                              G_PARAM_CONSTRUCT_ONLY));
326         g_object_class_install_property (g_object_class,
327                                          PROP_PAGE,
328                                          g_param_spec_int ("page",
329                                                            "Dest Page",
330                                                            "The destination page",
331                                                            -1,
332                                                            G_MAXINT,
333                                                            0,
334                                                            G_PARAM_READWRITE |
335                                                            G_PARAM_CONSTRUCT_ONLY));
336         g_object_class_install_property (g_object_class,
337                                          PROP_LEFT,
338                                          g_param_spec_double ("left",
339                                                               "Left coordinate",
340                                                               "The left coordinate",
341                                                               -G_MAXDOUBLE,
342                                                               G_MAXDOUBLE,
343                                                               0,
344                                                               G_PARAM_READWRITE |
345                                                               G_PARAM_CONSTRUCT_ONLY));
346         g_object_class_install_property (g_object_class,
347                                          PROP_TOP,
348                                          g_param_spec_double ("top",
349                                                               "Top coordinate",
350                                                               "The top coordinate",
351                                                               -G_MAXDOUBLE,
352                                                               G_MAXDOUBLE,
353                                                               0,
354                                                               G_PARAM_READWRITE |
355                                                               G_PARAM_CONSTRUCT_ONLY));
356         g_object_class_install_property (g_object_class,
357                                          PROP_BOTTOM,
358                                          g_param_spec_double ("bottom",
359                                                               "Bottom coordinate",
360                                                               "The bottom coordinate",
361                                                               -G_MAXDOUBLE,
362                                                               G_MAXDOUBLE,
363                                                               0,
364                                                               G_PARAM_READWRITE |
365                                                               G_PARAM_CONSTRUCT_ONLY));
366         g_object_class_install_property (g_object_class,
367                                          PROP_RIGHT,
368                                          g_param_spec_double ("right",
369                                                               "Right coordinate",
370                                                               "The right coordinate",
371                                                               -G_MAXDOUBLE,
372                                                               G_MAXDOUBLE,
373                                                               0,
374                                                               G_PARAM_READWRITE |
375                                                               G_PARAM_CONSTRUCT_ONLY));
376
377         g_object_class_install_property (g_object_class,
378                                          PROP_ZOOM,
379                                          g_param_spec_double ("zoom",
380                                                               "Zoom",
381                                                               "Zoom",
382                                                               0,
383                                                               G_MAXDOUBLE,
384                                                               0,
385                                                               G_PARAM_READWRITE |
386                                                               G_PARAM_CONSTRUCT_ONLY));
387         g_object_class_install_property (g_object_class,
388                                          PROP_CHANGE,
389                                          g_param_spec_uint ("change",
390                                                             "Change",
391                                                             "Wether top, left, and zoom should be changed",
392                                                             0,
393                                                             G_MAXUINT,
394                                                             0,
395                                                             G_PARAM_READWRITE |
396                                                             G_PARAM_CONSTRUCT_ONLY));
397         g_object_class_install_property (g_object_class,
398                                          PROP_NAMED,
399                                          g_param_spec_string ("named",
400                                                               "Named destination",
401                                                               "The named destination",
402                                                               NULL,
403                                                               G_PARAM_READWRITE |
404                                                               G_PARAM_CONSTRUCT_ONLY));
405         g_object_class_install_property (g_object_class,
406                                          PROP_PAGE_LABEL,
407                                          g_param_spec_string ("page_label",
408                                                               "Label of the page",
409                                                               "The label of the destination page",
410                                                               NULL,
411                                                               G_PARAM_READWRITE |
412                                                               G_PARAM_CONSTRUCT_ONLY));
413 }
414
415 EvLinkDest *
416 ev_link_dest_new_page (gint page)
417 {
418         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
419                                            "page", page,
420                                            "type", EV_LINK_DEST_TYPE_PAGE,
421                                            NULL));
422 }
423
424 EvLinkDest *
425 ev_link_dest_new_xyz (gint     page,
426                       gdouble  left,
427                       gdouble  top,
428                       gdouble  zoom,
429                       gboolean change_left,
430                       gboolean change_top,
431                       gboolean change_zoom)
432 {
433         EvDestChange change = 0;
434
435         if (change_left)
436                 change |= EV_DEST_CHANGE_LEFT;
437         if (change_top)
438                 change |= EV_DEST_CHANGE_TOP;
439         if (change_zoom)
440                 change |= EV_DEST_CHANGE_ZOOM;
441         
442         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
443                                            "page", page,
444                                            "type", EV_LINK_DEST_TYPE_XYZ,
445                                            "left", left,
446                                            "top", top,
447                                            "zoom", zoom,
448                                            "change", change,
449                                            NULL));
450 }
451
452 EvLinkDest *
453 ev_link_dest_new_fit (gint page)
454 {
455         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
456                                            "page", page,
457                                            "type", EV_LINK_DEST_TYPE_FIT,
458                                            NULL));
459 }
460
461 EvLinkDest *
462 ev_link_dest_new_fith (gint     page,
463                        gdouble  top,
464                        gboolean change_top)
465 {
466         EvDestChange change = 0;
467
468         if (change_top)
469                 change |= EV_DEST_CHANGE_TOP;
470         
471         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
472                                            "page", page,
473                                            "type", EV_LINK_DEST_TYPE_FITH,
474                                            "top", top,
475                                            "change", change,
476                                            NULL));
477 }
478
479 EvLinkDest *
480 ev_link_dest_new_fitv (gint     page,
481                        gdouble  left,
482                        gboolean change_left)
483 {
484         EvDestChange change = 0;
485
486         if (change_left)
487                 change |= EV_DEST_CHANGE_LEFT;
488
489         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
490                                            "page", page,
491                                            "type", EV_LINK_DEST_TYPE_FITV,
492                                            "left", left,
493                                            "change", change,
494                                            NULL));
495 }
496
497 EvLinkDest *
498 ev_link_dest_new_fitr (gint    page,
499                        gdouble left,
500                        gdouble bottom,
501                        gdouble right,
502                        gdouble top)
503 {
504         EvDestChange change = EV_DEST_CHANGE_TOP | EV_DEST_CHANGE_LEFT;
505         
506         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
507                                            "page", page,
508                                            "type", EV_LINK_DEST_TYPE_FITR,
509                                            "left", left,
510                                            "bottom", bottom,
511                                            "right", right,
512                                            "top", top,
513                                            "change", change,
514                                            NULL));
515 }
516
517 EvLinkDest *
518 ev_link_dest_new_named (const gchar *named_dest)
519 {
520         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
521                                            "named", named_dest,
522                                            "type", EV_LINK_DEST_TYPE_NAMED,
523                                            NULL));
524 }
525
526 EvLinkDest *
527 ev_link_dest_new_page_label (const gchar *page_label)
528 {
529         return EV_LINK_DEST (g_object_new (EV_TYPE_LINK_DEST,
530                                            "page_label", page_label,
531                                            "type", EV_LINK_DEST_TYPE_PAGE_LABEL,
532                                            NULL));
533 }