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