]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-annotation.c
3245593d740292f2a08b125c848c2630c387ee4e
[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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include "ev-annotation.h"
25
26
27 static void ev_annotation_markup_iface_base_init (EvAnnotationMarkupIface *iface);
28 static void ev_annotation_text_markup_iface_init (EvAnnotationMarkupIface *iface);
29
30 enum {
31         PROP_0,
32         PROP_LABEL,
33         PROP_OPACITY,
34         PROP_RECTANGLE,
35         PROP_IS_OPEN
36 };
37
38 G_DEFINE_ABSTRACT_TYPE (EvAnnotation, ev_annotation, G_TYPE_OBJECT)
39 GType
40 ev_annotation_markup_get_type (void)
41 {
42         static volatile gsize g_define_type_id__volatile = 0;
43
44         if (g_once_init_enter (&g_define_type_id__volatile)) {
45                 GType g_define_type_id;
46                 const GTypeInfo our_info = {
47                         sizeof (EvAnnotationMarkupIface),
48                         (GBaseInitFunc) ev_annotation_markup_iface_base_init,
49                         NULL,
50                 };
51
52                 g_define_type_id = g_type_register_static (G_TYPE_INTERFACE,
53                                                            "EvAnnotationMarkup",
54                                                            &our_info, (GTypeFlags)0);
55                 g_type_interface_add_prerequisite (g_define_type_id, EV_TYPE_ANNOTATION);
56
57                 g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
58         }
59
60         return g_define_type_id__volatile;
61 }
62
63 G_DEFINE_TYPE_WITH_CODE (EvAnnotationText, ev_annotation_text, EV_TYPE_ANNOTATION,
64          {
65                  G_IMPLEMENT_INTERFACE (EV_TYPE_ANNOTATION_MARKUP,
66                                         ev_annotation_text_markup_iface_init);
67          });
68
69 /* EvAnnotation */
70 static void
71 ev_annotation_finalize (GObject *object)
72 {
73         EvAnnotation *annot = EV_ANNOTATION (object);
74
75         if (annot->page) {
76                 g_object_unref (annot->page);
77                 annot->page = NULL;
78         }
79
80         if (annot->contents) {
81                 g_free (annot->contents);
82                 annot->contents = NULL;
83         }
84
85         if (annot->name) {
86                 g_free (annot->name);
87                 annot->name = NULL;
88         }
89
90         if (annot->modified) {
91                 g_free (annot->modified);
92                 annot->modified = NULL;
93         }
94
95         G_OBJECT_CLASS (ev_annotation_parent_class)->finalize (object);
96 }
97
98 static void
99 ev_annotation_init (EvAnnotation *annot)
100 {
101 }
102
103 static void
104 ev_annotation_class_init (EvAnnotationClass *klass)
105 {
106         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
107
108         g_object_class->finalize = ev_annotation_finalize;
109 }
110
111 EvAnnotation *
112 ev_annotation_text_new (EvPage *page)
113 {
114         EvAnnotation *annot;
115
116         annot = EV_ANNOTATION (g_object_new (EV_TYPE_ANNOTATION_TEXT, NULL));
117         annot->page = g_object_ref (page);
118
119         return annot;
120 }
121
122 /* EvAnnotationMarkup */
123 typedef struct {
124         gchar   *label;
125         gdouble  opacity;
126         gboolean is_open;
127         EvRectangle *rectangle;
128 } EvAnnotationMarkupProps;
129
130 static void
131 ev_annotation_markup_iface_base_init (EvAnnotationMarkupIface *iface)
132 {
133         static gboolean initialized = FALSE;
134
135         if (!initialized) {
136                 g_object_interface_install_property (iface,
137                                                      g_param_spec_string ("label",
138                                                                           "Label",
139                                                                           "Label of the markup annotation",
140                                                                           NULL,
141                                                                           G_PARAM_READWRITE));
142                 g_object_interface_install_property (iface,
143                                                      g_param_spec_double ("opacity",
144                                                                           "Opacity",
145                                                                           "Opacity of the markup annotation",
146                                                                           0,
147                                                                           G_MAXDOUBLE,
148                                                                           0,
149                                                                           G_PARAM_READWRITE));
150                 g_object_interface_install_property (iface,
151                                                      g_param_spec_boxed ("rectangle",
152                                                                          "Rectangle",
153                                                                          "The Rectangle of the popup associated "
154                                                                          "to the markup annotation",
155                                                                          EV_TYPE_RECTANGLE,
156                                                                          G_PARAM_READWRITE));
157                 g_object_interface_install_property (iface,
158                                                      g_param_spec_boolean ("is_open",
159                                                                            "Is open",
160                                                                            "Whether the popup associated to "
161                                                                            "the markup annotation is open",
162                                                                            FALSE,
163                                                                            G_PARAM_READWRITE));
164                 initialized = TRUE;
165         }
166 }
167
168 static void
169 ev_annotation_markup_props_free (EvAnnotationMarkupProps *props)
170 {
171         g_free (props->label);
172         ev_rectangle_free (props->rectangle);
173         g_slice_free (EvAnnotationMarkupProps, props);
174 }
175
176 static EvAnnotationMarkupProps *
177 ev_annotation_markup_get_properties (EvAnnotationMarkup *markup)
178 {
179         EvAnnotationMarkupProps *props;
180         static GQuark props_key = 0;
181
182         if (!props_key)
183                 props_key = g_quark_from_static_string ("ev-annotation-markup-props");
184
185         props = g_object_get_qdata (G_OBJECT (markup), props_key);
186         if (!props) {
187                 props = g_slice_new0 (EvAnnotationMarkupProps);
188                 g_object_set_qdata_full (G_OBJECT (markup),
189                                          props_key, props,
190                                          (GDestroyNotify) ev_annotation_markup_props_free);
191         }
192
193         return props;
194 }
195
196 static void
197 ev_annotation_markup_set_property (GObject      *object,
198                                    guint         prop_id,
199                                    const GValue *value,
200                                    GParamSpec   *pspec)
201 {
202         EvAnnotationMarkupProps *props;
203
204         props = ev_annotation_markup_get_properties (EV_ANNOTATION_MARKUP (object));
205
206         switch (prop_id) {
207         case PROP_LABEL:
208                 g_free (props->label);
209                 props->label = g_value_dup_string (value);
210                 break;
211         case PROP_OPACITY:
212                 props->opacity = g_value_get_double (value);
213                 break;
214         case PROP_RECTANGLE:
215                 ev_rectangle_free (props->rectangle);
216                 props->rectangle = g_value_dup_boxed (value);
217                 break;
218         case PROP_IS_OPEN:
219                 props->is_open = g_value_get_boolean (value);
220                 break;
221         default:
222                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223         }
224 }
225
226 static void
227 ev_annotation_markup_get_property (GObject    *object,
228                                    guint       prop_id,
229                                    GValue     *value,
230                                    GParamSpec *pspec)
231 {
232         EvAnnotationMarkupProps *props;
233
234         props = ev_annotation_markup_get_properties (EV_ANNOTATION_MARKUP (object));
235
236         switch (prop_id) {
237         case PROP_LABEL:
238                 g_value_set_string (value, props->label);
239                 break;
240         case PROP_OPACITY:
241                 g_value_set_double (value, props->opacity);
242                 break;
243         case PROP_RECTANGLE:
244                 g_value_set_boxed (value, props->rectangle);
245                 break;
246         case PROP_IS_OPEN:
247                 g_value_set_boolean (value, props->is_open);
248                 break;
249         default:
250                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
251         }
252 }
253
254 static void
255 ev_annotation_markup_class_install_properties (GObjectClass *klass)
256 {
257         klass->set_property = ev_annotation_markup_set_property;
258         klass->get_property = ev_annotation_markup_get_property;
259
260         g_object_class_override_property (klass, PROP_LABEL, "label");
261         g_object_class_override_property (klass, PROP_OPACITY, "opacity");
262         g_object_class_override_property (klass, PROP_RECTANGLE, "rectangle");
263         g_object_class_override_property (klass, PROP_IS_OPEN, "is_open");
264 }
265
266 gchar *
267 ev_annotation_markup_get_label (EvAnnotationMarkup *markup)
268 {
269         gchar *retval;
270
271         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), NULL);
272
273         g_object_get (G_OBJECT (markup), "label", &retval, NULL);
274
275         return retval;
276 }
277
278 void
279 ev_annotation_markup_set_label (EvAnnotationMarkup *markup,
280                                 const gchar        *label)
281 {
282         g_return_if_fail (EV_IS_ANNOTATION_MARKUP (markup));
283         g_return_if_fail (label != NULL);
284
285         g_object_set (G_OBJECT (markup), "label", label, NULL);
286 }
287
288 gdouble
289 ev_annotation_markup_get_opacity (EvAnnotationMarkup *markup)
290 {
291         gdouble retval;
292
293         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), 0.0);
294
295         g_object_get (G_OBJECT (markup), "opacity", &retval, NULL);
296
297         return retval;
298 }
299
300 void
301 ev_annotation_markup_set_opacity (EvAnnotationMarkup *markup,
302                                   gdouble             opacity)
303 {
304         g_return_if_fail (EV_IS_ANNOTATION_MARKUP (markup));
305
306         g_object_set (G_OBJECT (markup), "opacity", opacity, NULL);
307 }
308
309 void
310 ev_annotation_markup_get_rectangle (EvAnnotationMarkup *markup,
311                                     EvRectangle        *ev_rect)
312 {
313         EvRectangle *r;
314
315         g_return_if_fail (EV_IS_ANNOTATION_MARKUP (markup));
316         g_return_if_fail (ev_rect != NULL);
317
318         g_object_get (G_OBJECT (markup), "rectangle", &r, NULL);
319         *ev_rect = *r;
320 }
321
322 gboolean
323 ev_annotation_markup_get_is_open (EvAnnotationMarkup *markup)
324 {
325         gboolean retval;
326
327         g_return_val_if_fail (EV_IS_ANNOTATION_MARKUP (markup), FALSE);
328
329         g_object_get (G_OBJECT (markup), "is_open", &retval, NULL);
330
331         return retval;
332 }
333
334 void
335 ev_annotation_markup_set_is_open (EvAnnotationMarkup *markup,
336                                   gboolean            is_open)
337 {
338         g_return_if_fail (EV_IS_ANNOTATION_MARKUP (markup));
339
340         g_object_set (G_OBJECT (markup), "is_open", is_open, NULL);
341 }
342
343 /* EvAnnotationText */
344 static void
345 ev_annotation_text_init (EvAnnotationText *annot)
346 {
347 }
348
349 static void
350 ev_annotation_text_class_init (EvAnnotationTextClass *klass)
351 {
352         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
353
354         ev_annotation_markup_class_install_properties (g_object_class);
355 }
356
357 static void
358 ev_annotation_text_markup_iface_init (EvAnnotationMarkupIface *iface)
359 {
360 }
361
362 /* Annotation Mapping stuff */
363 static void
364 ev_annotation_mapping_free_foreach (EvAnnotationMapping *mapping)
365 {
366         g_object_unref (mapping->annotation);
367         g_free (mapping);
368 }
369
370 void
371 ev_annotation_mapping_free (GList *annotation_mapping)
372 {
373         if (!annotation_mapping)
374                 return;
375
376         g_list_foreach (annotation_mapping, (GFunc) ev_annotation_mapping_free_foreach, NULL);
377         g_list_free (annotation_mapping);
378 }
379
380 EvAnnotation *
381 ev_annotation_mapping_find (GList   *annotation_mapping,
382                             gdouble  x,
383                             gdouble  y)
384 {
385         GList *list;
386
387         for (list = annotation_mapping; list; list = list->next) {
388                 EvAnnotationMapping *mapping = list->data;
389
390                 if ((x >= mapping->x1) &&
391                     (y >= mapping->y1) &&
392                     (x <= mapping->x2) &&
393                     (y <= mapping->y2)) {
394                         return mapping->annotation;
395                 }
396         }
397
398         return NULL;
399 }
400
401 void
402 ev_annotation_mapping_get_area (GList        *annotation_mapping,
403                                 EvAnnotation *annotation,
404                                 EvRectangle  *area)
405 {
406         GList *list;
407
408         for (list = annotation_mapping; list; list = list->next) {
409                 EvAnnotationMapping *mapping = list->data;
410
411                 if (mapping->annotation == annotation) {
412                         area->x1 = mapping->x1;
413                         area->y1 = mapping->y1;
414                         area->x2 = mapping->x2;
415                         area->y2 = mapping->y2;
416
417                         break;
418                 }
419         }
420 }