]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-annotation.c
Preliminary support for adding new annotations
[evince.git] / libdocument / ev-annotation.c
1 /* ev-annotation.c
2  *  this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
5  * Copyright (C) 2007 IƱigo Martinez <inigomartinez@gmail.com>
6  *
7  * Evince is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * Evince is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23
24 #include "ev-annotation.h"
25 #include "ev-document-misc.h"
26 #include "ev-document-type-builtins.h"
27
28 struct _EvAnnotation {
29         GObject          parent;
30
31         EvAnnotationType type;
32         EvPage          *page;
33
34         gchar           *contents;
35         gchar           *name;
36         gchar           *modified;
37         GdkColor         color;
38
39 };
40
41 struct _EvAnnotationClass {
42         GObjectClass parent_class;
43 };
44
45 struct _EvAnnotationMarkupInterface {
46         GTypeInterface base_iface;
47 };
48
49 struct _EvAnnotationText {
50         EvAnnotation parent;
51
52         gboolean             is_open : 1;
53         EvAnnotationTextIcon icon;
54 };
55
56 struct _EvAnnotationTextClass {
57         EvAnnotationClass parent_class;
58 };
59
60 struct _EvAnnotationAttachment {
61         EvAnnotation parent;
62
63         EvAttachment *attachment;
64 };
65
66 struct _EvAnnotationAttachmentClass {
67         EvAnnotationClass parent_class;
68 };
69
70 static void ev_annotation_markup_default_init          (EvAnnotationMarkupInterface *iface);
71 static void ev_annotation_text_markup_iface_init       (EvAnnotationMarkupInterface *iface);
72 static void ev_annotation_attachment_markup_iface_init (EvAnnotationMarkupInterface *iface);
73
74 /* EvAnnotation */
75 enum {
76         PROP_ANNOT_0,
77         PROP_ANNOT_PAGE,
78         PROP_ANNOT_CONTENTS,
79         PROP_ANNOT_NAME,
80         PROP_ANNOT_MODIFIED,
81         PROP_ANNOT_COLOR
82 };
83
84 /* EvAnnotationMarkup */
85 enum {
86         PROP_MARKUP_0,
87         PROP_MARKUP_LABEL,
88         PROP_MARKUP_OPACITY,
89         PROP_MARKUP_HAS_POPUP,
90         PROP_MARKUP_RECTANGLE,
91         PROP_MARKUP_POPUP_IS_OPEN
92 };
93
94 /* EvAnnotationText */
95 enum {
96         PROP_TEXT_0,
97         PROP_TEXT_ICON,
98         PROP_TEXT_IS_OPEN
99 };
100
101 /* EvAnnotationAttachment */
102 enum {
103         PROP_ATTACHMENT_0,
104         PROP_ATTACHMENT_ATTACHMENT
105 };
106
107 G_DEFINE_ABSTRACT_TYPE (EvAnnotation, ev_annotation, G_TYPE_OBJECT)
108 G_DEFINE_INTERFACE (EvAnnotationMarkup, ev_annotation_markup, EV_TYPE_ANNOTATION)
109 G_DEFINE_TYPE_WITH_CODE (EvAnnotationText, ev_annotation_text, EV_TYPE_ANNOTATION,
110          {
111                  G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP,
112                                         ev_annotation_text_markup_iface_init);
113          });
114 G_DEFINE_TYPE_WITH_CODE (EvAnnotationAttachment, ev_annotation_attachment, EV_TYPE_ANNOTATION,
115          {
116                  G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP,
117                                         ev_annotation_attachment_markup_iface_init);
118          });
119
120 /* EvAnnotation */
121 static void
122 ev_annotation_finalize (GObject *object)
123 {
124         EvAnnotation *annot = EV_ANNOTATION (object);
125
126         if (annot->page) {
127                 g_object_unref (annot->page);
128                 annot->page = NULL;
129         }
130
131         if (annot->contents) {
132                 g_free (annot->contents);
133                 annot->contents = NULL;
134         }
135
136         if (annot->name) {
137                 g_free (annot->name);
138                 annot->name = NULL;
139         }
140
141         if (annot->modified) {
142                 g_free (annot->modified);
143                 annot->modified = NULL;
144         }
145
146         G_OBJECT_CLASS (ev_annotation_parent_class)->finalize (object);
147 }
148
149 static void
150 ev_annotation_init (EvAnnotation *annot)
151 {
152         annot->type = EV_ANNOTATION_TYPE_UNKNOWN;
153 }
154
155 static void
156 ev_annotation_set_property (GObject      *object,
157                             guint         prop_id,
158                             const GValue *value,
159                             GParamSpec   *pspec)
160 {
161         EvAnnotation *annot = EV_ANNOTATION (object);
162
163         switch (prop_id) {
164         case PROP_ANNOT_PAGE:
165                 annot->page = g_value_dup_object (value);
166                 break;
167         case PROP_ANNOT_CONTENTS:
168                 ev_annotation_set_contents (annot, g_value_get_string (value));
169                 break;
170         case PROP_ANNOT_NAME:
171                 ev_annotation_set_name (annot, g_value_get_string (value));
172                 break;
173         case PROP_ANNOT_MODIFIED:
174                 ev_annotation_set_modified (annot, g_value_get_string (value));
175                 break;
176         case PROP_ANNOT_COLOR:
177                 ev_annotation_set_color (annot, g_value_get_pointer (value));
178                 break;
179         default:
180                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
181         }
182 }
183
184 static void
185 ev_annotation_get_property (GObject    *object,
186                             guint       prop_id,
187                             GValue     *value,
188                             GParamSpec *pspec)
189 {
190         EvAnnotation *annot = EV_ANNOTATION (object);
191
192         switch (prop_id) {
193         case PROP_ANNOT_CONTENTS:
194                 g_value_set_string (value, ev_annotation_get_contents (annot));
195                 break;
196         case PROP_ANNOT_NAME:
197                 g_value_set_string (value, ev_annotation_get_name (annot));
198                 break;
199         case PROP_ANNOT_MODIFIED:
200                 g_value_set_string (value, ev_annotation_get_modified (annot));
201                 break;
202         case PROP_ANNOT_COLOR:
203                 g_value_set_pointer (value, &annot->color);
204                 break;
205         default:
206                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
207         }
208 }
209
210 static void
211 ev_annotation_class_init (EvAnnotationClass *klass)
212 {
213         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
214
215         g_object_class->finalize = ev_annotation_finalize;
216         g_object_class->set_property = ev_annotation_set_property;
217         g_object_class->get_property = ev_annotation_get_property;
218
219         g_object_class_install_property (g_object_class,
220                                          PROP_ANNOT_PAGE,
221                                          g_param_spec_object ("page",
222                                                               "Page",
223                                                               "The page wehere the annotation is",
224                                                               EV_TYPE_PAGE,
225                                                               G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
226         g_object_class_install_property (g_object_class,
227                                          PROP_ANNOT_CONTENTS,
228                                          g_param_spec_string ("contents",
229                                                               "Contents",
230                                                               "The annotation contents",
231                                                               NULL,
232                                                               G_PARAM_READWRITE));
233         g_object_class_install_property (g_object_class,
234                                          PROP_ANNOT_NAME,
235                                          g_param_spec_string ("name",
236                                                               "Name",
237                                                               "The annotation unique name",
238                                                               NULL,
239                                                               G_PARAM_READWRITE));
240         g_object_class_install_property (g_object_class,
241                                          PROP_ANNOT_MODIFIED,
242                                          g_param_spec_string ("modified",
243                                                               "Modified",
244                                                               "Last modified date as string",
245                                                               NULL,
246                                                               G_PARAM_READWRITE));
247         g_object_class_install_property (g_object_class,
248                                          PROP_ANNOT_COLOR,
249                                          g_param_spec_pointer ("color",
250                                                                "Color",
251                                                                "The annotation color",
252                                                                G_PARAM_READWRITE));
253 }
254
255 EvAnnotationType
256 ev_annotation_get_annotation_type (EvAnnotation *annot)
257 {
258         g_return_val_if_fail (EV_IS_ANNOTATION (annot), 0);
259
260         return annot->type;
261 }
262
263 EvPage *
264 ev_annotation_get_page (EvAnnotation *annot)
265 {
266         g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
267
268         return annot->page;
269 }
270
271 guint
272 ev_annotation_get_page_index (EvAnnotation *annot)
273 {
274         g_return_val_if_fail (EV_IS_ANNOTATION (annot), 0);
275
276         return annot->page->index;
277 }
278
279 gboolean
280 ev_annotation_equal (EvAnnotation *annot,
281                      EvAnnotation *other)
282 {
283         g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
284         g_return_val_if_fail (EV_IS_ANNOTATION (other), FALSE);
285
286         return (annot == other || g_strcmp0 (annot->name, other->name) == 0);
287 }
288
289 const gchar *
290 ev_annotation_get_contents (EvAnnotation *annot)
291 {
292         g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
293
294         return annot->contents;
295 }
296
297 gboolean
298 ev_annotation_set_contents (EvAnnotation *annot,
299                             const gchar  *contents)
300 {
301         g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
302
303         if (g_strcmp0 (annot->contents, contents) == 0)
304                 return FALSE;
305
306         if (annot->contents)
307                 g_free (annot->contents);
308         annot->contents = contents ? g_strdup (contents) : NULL;
309
310         g_object_notify (G_OBJECT (annot), "contents");
311
312         return TRUE;
313 }
314
315 const gchar *
316 ev_annotation_get_name (EvAnnotation *annot)
317 {
318         g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
319
320         return annot->name;
321 }
322
323 gboolean
324 ev_annotation_set_name (EvAnnotation *annot,
325                         const gchar  *name)
326 {
327         g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
328
329         if (g_strcmp0 (annot->name, name) == 0)
330                 return FALSE;
331
332         if (annot->name)
333                 g_free (annot->name);
334         annot->name = name ? g_strdup (name) : NULL;
335
336         g_object_notify (G_OBJECT (annot), "name");
337
338         return TRUE;
339 }
340
341 const gchar *
342 ev_annotation_get_modified (EvAnnotation *annot)
343 {
344         g_return_val_if_fail (EV_IS_ANNOTATION (annot), NULL);
345
346         return annot->modified;
347 }
348
349 gboolean
350 ev_annotation_set_modified (EvAnnotation *annot,
351                             const gchar  *modified)
352 {
353         g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
354
355         if (g_strcmp0 (annot->modified, modified) == 0)
356                 return FALSE;
357
358         if (annot->modified)
359                 g_free (annot->modified);
360         annot->modified = modified ? g_strdup (modified) : NULL;
361
362         g_object_notify (G_OBJECT (annot), "modified");
363
364         return TRUE;
365 }
366
367 gboolean
368 ev_annotation_set_modified_from_time (EvAnnotation *annot,
369                                       GTime         utime)
370 {
371         gchar *modified;
372
373         g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
374
375         modified = ev_document_misc_format_date (utime);
376
377         if (g_strcmp0 (annot->modified, modified) == 0) {
378                 g_free (modified);
379                 return FALSE;
380         }
381
382         if (annot->modified)
383                 g_free (annot->modified);
384         annot->modified = modified;
385
386         g_object_notify (G_OBJECT (annot), "modified");
387
388         return TRUE;
389 }
390
391 void
392 ev_annotation_get_color (EvAnnotation *annot,
393                          GdkColor     *color)
394 {
395         g_return_if_fail (EV_IS_ANNOTATION (annot));
396
397         if (color)
398                 *color = annot->color;
399 }
400
401 gboolean
402 ev_annotation_set_color (EvAnnotation   *annot,
403                          const GdkColor *color)
404 {
405         g_return_val_if_fail (EV_IS_ANNOTATION (annot), FALSE);
406
407         if (annot->color.red == color->red &&
408             annot->color.green == color->green &&
409             annot->color.blue == color->blue)
410                 return FALSE;
411
412         if (color)
413                 annot->color = *color;
414
415         g_object_notify (G_OBJECT (annot), "color");
416
417         return TRUE;
418 }
419
420 /* EvAnnotationMarkup */
421 typedef struct {
422         gchar   *label;
423         gdouble  opacity;
424         gboolean has_popup;
425         gboolean popup_is_open;
426         EvRectangle rectangle;
427 } EvAnnotationMarkupProps;
428
429 static void
430 ev_annotation_markup_default_init (EvAnnotationMarkupInterface *iface)
431 {
432         static gboolean initialized = FALSE;
433
434         if (!initialized) {
435                 g_object_interface_install_property (iface,
436                                                      g_param_spec_string ("label",
437                                                                           "Label",
438                                                                           "Label of the markup annotation",
439                                                                           NULL,
440                                                                           G_PARAM_READWRITE));
441                 g_object_interface_install_property (iface,
442                                                      g_param_spec_double ("opacity",
443                                                                           "Opacity",
444                                                                           "Opacity of the markup annotation",
445                                                                           0,
446                                                                           G_MAXDOUBLE,
447                                                                           1.,
448                                                                           G_PARAM_READWRITE));
449                 g_object_interface_install_property (iface,
450                                                      g_param_spec_boolean ("has_popup",
451                                                                            "Has popup",
452                                                                            "Whether the markup annotation has "
453                                                                            "a popup window associated",
454                                                                            TRUE,
455                                                                            G_PARAM_READWRITE));
456                 g_object_interface_install_property (iface,
457                                                      g_param_spec_boxed ("rectangle",
458                                                                          "Rectangle",
459                                                                          "The Rectangle of the popup associated "
460                                                                          "to the markup annotation",
461                                                                          EV_TYPE_RECTANGLE,
462                                                                          G_PARAM_READWRITE));
463                 g_object_interface_install_property (iface,
464                                                      g_param_spec_boolean ("popup_is_open",
465                                                                            "PopupIsOpen",
466                                                                            "Whether the popup associated to "
467                                                                            "the markup annotation is open",
468                                                                            FALSE,
469                                                                            G_PARAM_READWRITE));
470                 initialized = TRUE;
471         }
472 }
473
474 static void
475 ev_annotation_markup_props_free (EvAnnotationMarkupProps *props)
476 {
477         g_free (props->label);
478         g_slice_free (EvAnnotationMarkupProps, props);
479 }
480
481 static EvAnnotationMarkupProps *
482 ev_annotation_markup_get_properties (EvAnnotationMarkup *markup)
483 {
484         EvAnnotationMarkupProps *props;
485         static GQuark props_key = 0;
486
487         if (!props_key)
488                 props_key = g_quark_from_static_string ("ev-annotation-markup-props");
489
490         props = g_object_get_qdata (G_OBJECT (markup), props_key);
491         if (!props) {
492                 props = g_slice_new0 (EvAnnotationMarkupProps);
493                 g_object_set_qdata_full (G_OBJECT (markup),
494                                          props_key, props,
495                                          (GDestroyNotify) ev_annotation_markup_props_free);
496         }
497
498         return props;
499 }
500
501 static void
502 ev_annotation_markup_set_property (GObject      *object,
503                                    guint         prop_id,
504                                    const GValue *value,
505                                    GParamSpec   *pspec)
506 {
507         EvAnnotationMarkup *markup = EV_ANNOTATION_MARKUP (object);
508
509         switch (prop_id) {
510         case PROP_MARKUP_LABEL:
511                 ev_annotation_markup_set_label (markup, g_value_get_string (value));
512                 break;
513         case PROP_MARKUP_OPACITY:
514                 ev_annotation_markup_set_opacity (markup, g_value_get_double (value));
515                 break;
516         case PROP_MARKUP_HAS_POPUP:
517                 ev_annotation_markup_set_has_popup (markup, g_value_get_boolean (value));
518                 break;
519         case PROP_MARKUP_RECTANGLE:
520                 ev_annotation_markup_set_rectangle (markup, g_value_get_boxed (value));
521                 break;
522         case PROP_MARKUP_POPUP_IS_OPEN:
523                 ev_annotation_markup_set_popup_is_open (markup, g_value_get_boolean (value));
524                 break;
525         default:
526                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
527         }
528 }
529
530 static void
531 ev_annotation_markup_get_property (GObject    *object,
532                                    guint       prop_id,
533                                    GValue     *value,
534                                    GParamSpec *pspec)
535 {
536         EvAnnotationMarkupProps *props;
537
538         props = ev_annotation_markup_get_properties (EV_ANNOTATION_MARKUP (object));
539
540         switch (prop_id) {
541         case PROP_MARKUP_LABEL:
542                 g_value_set_string (value, props->label);
543                 break;
544         case PROP_MARKUP_OPACITY:
545                 g_value_set_double (value, props->opacity);
546                 break;
547         case PROP_MARKUP_HAS_POPUP:
548                 g_value_set_boolean (value, props->has_popup);
549                 break;
550         case PROP_MARKUP_RECTANGLE:
551                 g_value_set_boxed (value, &props->rectangle);
552                 break;
553         case PROP_MARKUP_POPUP_IS_OPEN:
554                 g_value_set_boolean (value, props->popup_is_open);
555                 break;
556         default:
557                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
558         }
559 }
560
561 static void
562 ev_annotation_markup_class_install_properties (GObjectClass *klass)
563 {
564         klass->set_property = ev_annotation_markup_set_property;
565         klass->get_property = ev_annotation_markup_get_property;
566
567         g_object_class_override_property (klass, PROP_MARKUP_LABEL, "label");
568         g_object_class_override_property (klass, PROP_MARKUP_OPACITY, "opacity");
569         g_object_class_override_property (klass, PROP_MARKUP_HAS_POPUP, "has_popup");
570         g_object_class_override_property (klass, PROP_MARKUP_RECTANGLE, "rectangle");
571         g_object_class_override_property (klass, PROP_MARKUP_POPUP_IS_OPEN, "popup_is_open");
572 }
573
574 const gchar *
575 ev_annotation_markup_get_label (EvAnnotationMarkup *markup)
576 {
577         EvAnnotationMarkupProps *props;
578
579         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), NULL);
580
581         props = ev_annotation_markup_get_properties (markup);
582         return props->label;
583 }
584
585 gboolean
586 ev_annotation_markup_set_label (EvAnnotationMarkup *markup,
587                                 const gchar        *label)
588 {
589         EvAnnotationMarkupProps *props;
590
591         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
592         g_return_val_if_fail (label != NULL, FALSE);
593
594         props = ev_annotation_markup_get_properties (markup);
595         if (g_strcmp0 (props->label, label) == 0)
596                 return FALSE;
597
598         if (props->label)
599                 g_free (props->label);
600         props->label = g_strdup (label);
601
602         g_object_notify (G_OBJECT (markup), "label");
603
604         return TRUE;
605 }
606
607 gdouble
608 ev_annotation_markup_get_opacity (EvAnnotationMarkup *markup)
609 {
610         EvAnnotationMarkupProps *props;
611
612         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), 1.0);
613
614         props = ev_annotation_markup_get_properties (markup);
615         return props->opacity;
616 }
617
618 gboolean
619 ev_annotation_markup_set_opacity (EvAnnotationMarkup *markup,
620                                   gdouble             opacity)
621 {
622         EvAnnotationMarkupProps *props;
623
624         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
625
626         props = ev_annotation_markup_get_properties (markup);
627         if (props->opacity == opacity)
628                 return FALSE;
629
630         props->opacity = opacity;
631
632         g_object_notify (G_OBJECT (markup), "opacity");
633
634         return TRUE;
635 }
636
637 gboolean
638 ev_annotation_markup_has_popup (EvAnnotationMarkup *markup)
639 {
640         EvAnnotationMarkupProps *props;
641
642         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
643
644         props = ev_annotation_markup_get_properties (markup);
645         return props->has_popup;
646 }
647
648 gboolean
649 ev_annotation_markup_set_has_popup (EvAnnotationMarkup *markup,
650                                     gboolean            has_popup)
651 {
652         EvAnnotationMarkupProps *props;
653
654         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
655
656         props = ev_annotation_markup_get_properties (markup);
657         if (props->has_popup == has_popup)
658                 return FALSE;
659
660         props->has_popup = has_popup;
661
662         g_object_notify (G_OBJECT (markup), "has-popup");
663
664         return TRUE;
665 }
666
667 void
668 ev_annotation_markup_get_rectangle (EvAnnotationMarkup *markup,
669                                     EvRectangle        *ev_rect)
670 {
671         EvAnnotationMarkupProps *props;
672
673         g_return_if_fail (EV_IS_ANNOTATION_MARKUP (markup));
674         g_return_if_fail (ev_rect != NULL);
675
676         props = ev_annotation_markup_get_properties (markup);
677         *ev_rect = props->rectangle;
678 }
679
680 gboolean
681 ev_annotation_markup_set_rectangle (EvAnnotationMarkup *markup,
682                                     const EvRectangle  *ev_rect)
683 {
684         EvAnnotationMarkupProps *props;
685
686         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
687         g_return_val_if_fail (ev_rect != NULL, FALSE);
688
689         props = ev_annotation_markup_get_properties (markup);
690         if (props->rectangle.x1 == ev_rect->x1 &&
691             props->rectangle.y1 == ev_rect->y1 &&
692             props->rectangle.x2 == ev_rect->x2 &&
693             props->rectangle.y2 == ev_rect->y2)
694                 return FALSE;
695
696         props->rectangle = *ev_rect;
697
698         g_object_notify (G_OBJECT (markup), "rectangle");
699
700         return TRUE;
701 }
702
703 gboolean
704 ev_annotation_markup_get_popup_is_open (EvAnnotationMarkup *markup)
705 {
706         EvAnnotationMarkupProps *props;
707
708         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
709
710         props = ev_annotation_markup_get_properties (markup);
711         return props->popup_is_open;
712 }
713
714 gboolean
715 ev_annotation_markup_set_popup_is_open (EvAnnotationMarkup *markup,
716                                         gboolean            is_open)
717 {
718         EvAnnotationMarkupProps *props;
719
720         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
721
722         props = ev_annotation_markup_get_properties (markup);
723         if (props->popup_is_open == is_open)
724                 return FALSE;
725
726         props->popup_is_open = is_open;
727
728         g_object_notify (G_OBJECT (markup), "popup_is_open");
729
730         return TRUE;
731 }
732
733 /* EvAnnotationText */
734 static void
735 ev_annotation_text_init (EvAnnotationText *annot)
736 {
737         EV_ANNOTATION (annot)->type = EV_ANNOTATION_TYPE_TEXT;
738 }
739
740 static void
741 ev_annotation_text_set_property (GObject      *object,
742                                  guint         prop_id,
743                                  const GValue *value,
744                                  GParamSpec   *pspec)
745 {
746         EvAnnotationText *annot = EV_ANNOTATION_TEXT (object);
747
748         switch (prop_id) {
749         case PROP_TEXT_ICON:
750                 ev_annotation_text_set_icon (annot, g_value_get_enum (value));
751                 break;
752         case PROP_TEXT_IS_OPEN:
753                 ev_annotation_text_set_is_open (annot, g_value_get_boolean (value));
754                 break;
755         default:
756                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
757         }
758 }
759
760 static void
761 ev_annotation_text_get_property (GObject    *object,
762                                  guint       prop_id,
763                                  GValue     *value,
764                                  GParamSpec *pspec)
765 {
766         EvAnnotationText *annot = EV_ANNOTATION_TEXT (object);
767
768         switch (prop_id) {
769         case PROP_TEXT_ICON:
770                 g_value_set_enum (value, annot->icon);
771                 break;
772         case PROP_TEXT_IS_OPEN:
773                 g_value_set_boolean (value, annot->is_open);
774                 break;
775         default:
776                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
777         }
778 }
779
780 static void
781 ev_annotation_text_class_init (EvAnnotationTextClass *klass)
782 {
783         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
784
785         g_object_class->set_property = ev_annotation_text_set_property;
786         g_object_class->get_property = ev_annotation_text_get_property;
787
788         ev_annotation_markup_class_install_properties (g_object_class);
789
790         g_object_class_install_property (g_object_class,
791                                          PROP_TEXT_ICON,
792                                          g_param_spec_enum ("icon",
793                                                             "Icon",
794                                                             "The icon fo the text annotation",
795                                                             EV_TYPE_ANNOTATION_TEXT_ICON,
796                                                             EV_ANNOTATION_TEXT_ICON_NOTE,
797                                                             G_PARAM_READWRITE));
798         g_object_class_install_property (g_object_class,
799                                          PROP_TEXT_IS_OPEN,
800                                          g_param_spec_boolean ("is_open",
801                                                                "IsOpen",
802                                                                "Whether text annot is initially open",
803                                                                FALSE,
804                                                                G_PARAM_READWRITE));
805 }
806
807 static void
808 ev_annotation_text_markup_iface_init (EvAnnotationMarkupInterface *iface)
809 {
810 }
811
812 EvAnnotation *
813 ev_annotation_text_new (EvPage *page)
814 {
815         return EV_ANNOTATION (g_object_new (EV_TYPE_ANNOTATION_TEXT,
816                                             "page", page,
817                                             NULL));
818 }
819
820 EvAnnotationTextIcon
821 ev_annotation_text_get_icon (EvAnnotationText *text)
822 {
823         g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), 0);
824
825         return text->icon;
826 }
827
828 gboolean
829 ev_annotation_text_set_icon (EvAnnotationText    *text,
830                              EvAnnotationTextIcon icon)
831 {
832         g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), FALSE);
833
834         if (text->icon == icon)
835                 return FALSE;
836
837         text->icon = icon;
838
839         g_object_notify (G_OBJECT (text), "icon");
840
841         return TRUE;
842 }
843
844 gboolean
845 ev_annotation_text_get_is_open (EvAnnotationText *text)
846 {
847         g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), FALSE);
848
849         return text->is_open;
850 }
851
852 gboolean
853 ev_annotation_text_set_is_open (EvAnnotationText *text,
854                                 gboolean          is_open)
855 {
856         g_return_val_if_fail (EV_IS_ANNOTATION_TEXT (text), FALSE);
857
858         if (text->is_open == is_open)
859                 return FALSE;
860
861         text->is_open = is_open;
862
863         g_object_notify (G_OBJECT (text), "is_open");
864
865         return TRUE;
866 }
867
868 /* EvAnnotationAttachment */
869 static void
870 ev_annotation_attachment_finalize (GObject *object)
871 {
872         EvAnnotationAttachment *annot = EV_ANNOTATION_ATTACHMENT (object);
873
874         if (annot->attachment) {
875                 g_object_unref (annot->attachment);
876                 annot->attachment = NULL;
877         }
878
879         G_OBJECT_CLASS (ev_annotation_attachment_parent_class)->finalize (object);
880 }
881
882 static void
883 ev_annotation_attachment_init (EvAnnotationAttachment *annot)
884 {
885         EV_ANNOTATION (annot)->type = EV_ANNOTATION_TYPE_ATTACHMENT;
886 }
887
888 static void
889 ev_annotation_attachment_set_property (GObject      *object,
890                                        guint         prop_id,
891                                        const GValue *value,
892                                        GParamSpec   *pspec)
893 {
894         EvAnnotationAttachment *annot = EV_ANNOTATION_ATTACHMENT (object);
895
896         switch (prop_id) {
897         case PROP_ATTACHMENT_ATTACHMENT:
898                 ev_annotation_attachment_set_attachment (annot, g_value_get_object (value));
899                 break;
900         default:
901                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
902         }
903 }
904
905 static void
906 ev_annotation_attachment_get_property (GObject    *object,
907                                        guint       prop_id,
908                                        GValue     *value,
909                                        GParamSpec *pspec)
910 {
911         EvAnnotationAttachment *annot = EV_ANNOTATION_ATTACHMENT (object);
912
913         switch (prop_id) {
914         case PROP_ATTACHMENT_ATTACHMENT:
915                 g_value_set_object (value, annot->attachment);
916                 break;
917         default:
918                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
919         }
920 }
921
922 static void
923 ev_annotation_attachment_class_init (EvAnnotationAttachmentClass *klass)
924 {
925         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
926
927         g_object_class->set_property = ev_annotation_attachment_set_property;
928         g_object_class->get_property = ev_annotation_attachment_get_property;
929         g_object_class->finalize = ev_annotation_attachment_finalize;
930
931         ev_annotation_markup_class_install_properties (g_object_class);
932
933         g_object_class_install_property (g_object_class,
934                                          PROP_ATTACHMENT_ATTACHMENT,
935                                          g_param_spec_object ("attachment",
936                                                               "Attachment",
937                                                               "The attachment of the annotation",
938                                                               EV_TYPE_ATTACHMENT,
939                                                               G_PARAM_CONSTRUCT |
940                                                               G_PARAM_READWRITE));
941 }
942
943 static void
944 ev_annotation_attachment_markup_iface_init (EvAnnotationMarkupInterface *iface)
945 {
946 }
947
948 EvAnnotation *
949 ev_annotation_attachment_new (EvPage       *page,
950                               EvAttachment *attachment)
951 {
952         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
953
954         return EV_ANNOTATION (g_object_new (EV_TYPE_ANNOTATION_ATTACHMENT,
955                                             "page", page,
956                                             "attachment", attachment,
957                                             NULL));
958 }
959
960 EvAttachment *
961 ev_annotation_attachment_get_attachment (EvAnnotationAttachment *annot)
962 {
963         g_return_val_if_fail (EV_IS_ANNOTATION_ATTACHMENT (annot), NULL);
964
965         return annot->attachment;
966 }
967
968 gboolean
969 ev_annotation_attachment_set_attachment (EvAnnotationAttachment *annot,
970                                          EvAttachment           *attachment)
971 {
972         g_return_val_if_fail (EV_IS_ANNOTATION_ATTACHMENT (annot), FALSE);
973
974         if (annot->attachment == attachment)
975                 return FALSE;
976
977         if (annot->attachment)
978                 g_object_unref (annot->attachment);
979         annot->attachment = attachment ? g_object_ref (attachment) : NULL;
980
981         g_object_notify (G_OBJECT (annot), "attachment");
982
983         return TRUE;
984 }