1 /*
2 * Copyright (C) 2011-2013 Jiri Techet <techet@gmail.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * SECTION:champlain-license
21 * @short_description: An actor that displays license text.
22 *
23 * An actor that displays license text.
24 */
25
26 #include "config.h"
27
28 #include "champlain-license.h"
29 #include "champlain-defines.h"
30 #include "champlain-private.h"
31 #include "champlain-enum-types.h"
32 #include "champlain-view.h"
33
34 #include <clutter/clutter.h>
35 #include <glib.h>
36 #include <glib-object.h>
37 #include <cairo.h>
38 #include <math.h>
39 #include <string.h>
40
41
42 enum
43 {
44 /* normal signals */
45 LAST_SIGNAL
46 };
47
48 enum
49 {
50 PROP_0,
51 PROP_LICENSE_EXTRA,
52 PROP_ALIGNMENT,
53 };
54
55 /* static guint champlain_license_signals[LAST_SIGNAL] = { 0, }; */
56
57 struct _ChamplainLicensePrivate
58 {
59 gchar *extra_text; /* Extra license text */
60 ClutterActor *license_actor;
61 PangoAlignment alignment;
62
63 ChamplainView *view;
64 };
65
G_DEFINE_TYPE_WITH_PRIVATE(ChamplainLicense,champlain_license,CLUTTER_TYPE_ACTOR)66 G_DEFINE_TYPE_WITH_PRIVATE (ChamplainLicense, champlain_license, CLUTTER_TYPE_ACTOR)
67
68 #define WIDTH_PADDING 10
69 #define HEIGHT_PADDING 7
70
71
72 static void
73 champlain_license_get_property (GObject *object,
74 guint prop_id,
75 GValue *value,
76 GParamSpec *pspec)
77 {
78 ChamplainLicensePrivate *priv = CHAMPLAIN_LICENSE (object)->priv;
79
80 switch (prop_id)
81 {
82 case PROP_LICENSE_EXTRA:
83 g_value_set_string (value, priv->extra_text);
84 break;
85
86 case PROP_ALIGNMENT:
87 g_value_set_enum (value, priv->alignment);
88 break;
89
90 default:
91 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
92 }
93 }
94
95
96 static void
champlain_license_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)97 champlain_license_set_property (GObject *object,
98 guint prop_id,
99 const GValue *value,
100 GParamSpec *pspec)
101 {
102 ChamplainLicense *license = CHAMPLAIN_LICENSE (object);
103
104 switch (prop_id)
105 {
106 case PROP_LICENSE_EXTRA:
107 champlain_license_set_extra_text (license, g_value_get_string (value));
108 break;
109
110 case PROP_ALIGNMENT:
111 champlain_license_set_alignment (license, g_value_get_enum (value));
112 break;
113
114 default:
115 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
116 }
117 }
118
119
120 static void
redraw_license(ChamplainLicense * license)121 redraw_license (ChamplainLicense *license)
122 {
123 ChamplainLicensePrivate *priv = license->priv;
124 gchar *text;
125 gfloat width, height;
126 ChamplainMapSource *map_source;
127 GList *overlay_sources, *iter;
128
129 if (!priv->view)
130 return;
131
132 map_source = champlain_view_get_map_source (priv->view);
133
134 if (!map_source)
135 return;
136
137 if (priv->extra_text)
138 text = g_strjoin ("\n",
139 priv->extra_text,
140 champlain_map_source_get_license (map_source),
141 NULL);
142 else
143 text = g_strdup (champlain_map_source_get_license (map_source));
144
145 overlay_sources = champlain_view_get_overlay_sources (priv->view);
146 for (iter = overlay_sources; iter; iter = iter->next)
147 {
148 ChamplainMapSource *map_source = iter->data;
149 const gchar *overlay_license = champlain_map_source_get_license (map_source);
150
151 if (g_strrstr (text, overlay_license) == NULL)
152 {
153 gchar *old_text = text;
154 text = g_strjoin ("\n",
155 text,
156 champlain_map_source_get_license (map_source),
157 NULL);
158 g_free (old_text);
159 }
160 }
161 g_list_free (overlay_sources);
162
163 clutter_text_set_text (CLUTTER_TEXT (priv->license_actor), text);
164 clutter_actor_get_size (priv->license_actor, &width, &height);
165 clutter_actor_set_size (CLUTTER_ACTOR (license), width + 2 * WIDTH_PADDING, height + 2 * HEIGHT_PADDING);
166 clutter_actor_set_position (priv->license_actor, WIDTH_PADDING, HEIGHT_PADDING);
167
168 g_free (text);
169 }
170
171
172 static void
redraw_license_cb(G_GNUC_UNUSED GObject * gobject,G_GNUC_UNUSED GParamSpec * arg1,ChamplainLicense * license)173 redraw_license_cb (G_GNUC_UNUSED GObject *gobject,
174 G_GNUC_UNUSED GParamSpec *arg1,
175 ChamplainLicense *license)
176 {
177 redraw_license (license);
178 }
179
180
181 static void
champlain_license_dispose(GObject * object)182 champlain_license_dispose (GObject *object)
183 {
184 ChamplainLicensePrivate *priv = CHAMPLAIN_LICENSE (object)->priv;
185
186 priv->license_actor = NULL;
187
188 if (priv->view)
189 {
190 champlain_license_disconnect_view (CHAMPLAIN_LICENSE (object));
191 priv->view = NULL;
192 }
193
194 G_OBJECT_CLASS (champlain_license_parent_class)->dispose (object);
195 }
196
197
198 static void
champlain_license_finalize(GObject * object)199 champlain_license_finalize (GObject *object)
200 {
201 ChamplainLicensePrivate *priv = CHAMPLAIN_LICENSE (object)->priv;
202
203 g_free (priv->extra_text);
204
205 G_OBJECT_CLASS (champlain_license_parent_class)->finalize (object);
206 }
207
208
209 static void
champlain_license_class_init(ChamplainLicenseClass * klass)210 champlain_license_class_init (ChamplainLicenseClass *klass)
211 {
212 GObjectClass *object_class = G_OBJECT_CLASS (klass);
213
214 object_class->finalize = champlain_license_finalize;
215 object_class->dispose = champlain_license_dispose;
216 object_class->get_property = champlain_license_get_property;
217 object_class->set_property = champlain_license_set_property;
218
219 /**
220 * ChamplainLicense:extra-text:
221 *
222 * Sets additional text to be displayed in the license area. The map's
223 * license will be added below it. Your text can have multiple lines, just use
224 * "\n" in between.
225 *
226 * Since: 0.10
227 */
228 g_object_class_install_property (object_class,
229 PROP_LICENSE_EXTRA,
230 g_param_spec_string ("extra-text",
231 "Additional license",
232 "Additional license text",
233 "",
234 CHAMPLAIN_PARAM_READWRITE));
235
236 /**
237 * ChamplainLicense:alignment:
238 *
239 * The license's alignment
240 *
241 * Since: 0.10
242 */
243 g_object_class_install_property (object_class,
244 PROP_ALIGNMENT,
245 g_param_spec_enum ("alignment",
246 "Alignment",
247 "The license's alignment",
248 PANGO_TYPE_ALIGNMENT,
249 PANGO_ALIGN_LEFT,
250 CHAMPLAIN_PARAM_READWRITE));
251 }
252
253
254 static void
champlain_license_init(ChamplainLicense * license)255 champlain_license_init (ChamplainLicense *license)
256 {
257 ChamplainLicensePrivate *priv = champlain_license_get_instance_private (license);
258
259 license->priv = priv;
260 priv->extra_text = NULL;
261 priv->view = NULL;
262 priv->alignment = PANGO_ALIGN_RIGHT;
263
264 priv->license_actor = clutter_text_new ();
265 clutter_text_set_font_name (CLUTTER_TEXT (priv->license_actor), "sans 8");
266 clutter_text_set_line_alignment (CLUTTER_TEXT (priv->license_actor), priv->alignment);
267 clutter_actor_set_opacity (priv->license_actor, 128);
268 clutter_actor_add_child (CLUTTER_ACTOR (license), priv->license_actor);
269 }
270
271
272 /**
273 * champlain_license_new:
274 *
275 * Creates an instance of #ChamplainLicense.
276 *
277 * Returns: a new #ChamplainLicense.
278 *
279 * Since: 0.10
280 */
281 ClutterActor *
champlain_license_new(void)282 champlain_license_new (void)
283 {
284 return CLUTTER_ACTOR (g_object_new (CHAMPLAIN_TYPE_LICENSE, NULL));
285 }
286
287
288 /**
289 * champlain_license_connect_view:
290 * @license: The license
291 * @view: a #ChamplainView
292 *
293 * This method connects to the necessary signals of #ChamplainView to make the
294 * license change automatically when the map source changes.
295 *
296 * Since: 0.10
297 */
298 void
champlain_license_connect_view(ChamplainLicense * license,ChamplainView * view)299 champlain_license_connect_view (ChamplainLicense *license,
300 ChamplainView *view)
301 {
302 g_return_if_fail (CHAMPLAIN_IS_LICENSE (license));
303
304 license->priv->view = g_object_ref (view);
305
306 g_signal_connect (view, "notify::map-source",
307 G_CALLBACK (redraw_license_cb), license);
308 g_signal_connect (view, "notify::width",
309 G_CALLBACK (redraw_license_cb), license);
310 g_signal_connect (view, "notify::height",
311 G_CALLBACK (redraw_license_cb), license);
312 redraw_license (license);
313 }
314
315
316 /**
317 * champlain_license_disconnect_view:
318 * @license: The license
319 *
320 * This method disconnects from the signals previously connected by champlain_license_connect_view().
321 *
322 * Since: 0.10
323 */
324 void
champlain_license_disconnect_view(ChamplainLicense * license)325 champlain_license_disconnect_view (ChamplainLicense *license)
326 {
327 g_return_if_fail (CHAMPLAIN_IS_LICENSE (license));
328
329 g_signal_handlers_disconnect_by_func (license->priv->view,
330 redraw_license_cb,
331 license);
332 g_object_unref (license->priv->view);
333 license->priv->view = NULL;
334 }
335
336
337 /**
338 * champlain_license_set_extra_text:
339 * @license: a #ChamplainLicense
340 * @text: the additional license text
341 *
342 * Show the additional license text on the map view. The text will preceed the
343 * map's licence when displayed. Use "\n" to separate the lines.
344 *
345 * Since: 0.10
346 */
347 void
champlain_license_set_extra_text(ChamplainLicense * license,const gchar * text)348 champlain_license_set_extra_text (ChamplainLicense *license,
349 const gchar *text)
350 {
351 g_return_if_fail (CHAMPLAIN_IS_LICENSE (license));
352
353 ChamplainLicensePrivate *priv = license->priv;
354
355 if (priv->extra_text)
356 g_free (priv->extra_text);
357
358 priv->extra_text = g_strdup (text);
359 g_object_notify (G_OBJECT (license), "extra-text");
360 redraw_license (license);
361 }
362
363
364 /**
365 * champlain_license_get_extra_text:
366 * @license: a #ChamplainLicense
367 *
368 * Gets the additional license text.
369 *
370 * Returns: the additional license text
371 *
372 * Since: 0.10
373 */
374 const gchar *
champlain_license_get_extra_text(ChamplainLicense * license)375 champlain_license_get_extra_text (ChamplainLicense *license)
376 {
377 g_return_val_if_fail (CHAMPLAIN_IS_LICENSE (license), FALSE);
378
379 return license->priv->extra_text;
380 }
381
382
383 /**
384 * champlain_license_set_alignment:
385 * @license: a #ChamplainLicense
386 * @alignment: The license's text alignment
387 *
388 * Set the license's text alignment.
389 *
390 * Since: 0.10
391 */
392 void
champlain_license_set_alignment(ChamplainLicense * license,PangoAlignment alignment)393 champlain_license_set_alignment (ChamplainLicense *license,
394 PangoAlignment alignment)
395 {
396 g_return_if_fail (CHAMPLAIN_IS_LICENSE (license));
397
398 license->priv->alignment = alignment;
399 clutter_text_set_line_alignment (CLUTTER_TEXT (license->priv->license_actor), alignment);
400 g_object_notify (G_OBJECT (license), "alignment");
401 }
402
403
404 /**
405 * champlain_license_get_alignment:
406 * @license: The license
407 *
408 * Get the license's text alignment.
409 *
410 * Returns: the license's text alignment.
411 *
412 * Since: 0.10
413 */
414 PangoAlignment
champlain_license_get_alignment(ChamplainLicense * license)415 champlain_license_get_alignment (ChamplainLicense *license)
416 {
417 g_return_val_if_fail (CHAMPLAIN_IS_LICENSE (license), FALSE);
418
419 return license->priv->alignment;
420 }
421