Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc@pierlux.com>
3 : : * Copyright (C) 2011-2013 Jiri Techet <techet@gmail.com>
4 : : * Copyright (C) 2019 Marcus Lundblad <ml@update.uu.se>
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, write to the Free Software
18 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : : */
20 : :
21 : : /**
22 : : * ShumatePathLayer:
23 : : *
24 : : * A layer displaying line path between inserted [iface@Location] objects
25 : : *
26 : : * This layer shows a connection between inserted objects implementing the
27 : : * [iface@Location] interface. This means that both [class@Marker]
28 : : * objects and [class@Coordinate] objects can be inserted into the layer.
29 : : * Of course, custom objects implementing the [iface@Location] interface
30 : : * can be used as well.
31 : : */
32 : :
33 : : #include "shumate-path-layer.h"
34 : :
35 : : #include "shumate-enum-types.h"
36 : :
37 : : #include <cairo/cairo-gobject.h>
38 : : #include <gdk/gdk.h>
39 : : #include <gtk/gtk.h>
40 : : #include <glib.h>
41 : :
42 : : enum
43 : : {
44 : : PROP_CLOSED_PATH = 1,
45 : : PROP_STROKE_WIDTH,
46 : : PROP_STROKE_COLOR,
47 : : PROP_FILL,
48 : : PROP_FILL_COLOR,
49 : : PROP_STROKE,
50 : : PROP_OUTLINE_WIDTH,
51 : : PROP_OUTLINE_COLOR,
52 : : N_PROPERTIES
53 : : };
54 : :
55 : : static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
56 : :
57 : : static GdkRGBA DEFAULT_FILL_COLOR = { 0.8, 0.0, 0.0, 0.67 };
58 : : static GdkRGBA DEFAULT_STROKE_COLOR = { 0.64, 0.0, 0.0, 1.0 };
59 : : static GdkRGBA DEFAULT_OUTLINE_COLOR = { 1.0, 0.8, 0.8, 1.0 };
60 : :
61 : : struct _ShumatePathLayer
62 : : {
63 : : ShumateLayer parent_instance;
64 : :
65 : : gboolean closed_path;
66 : : GdkRGBA *stroke_color;
67 : : gboolean fill;
68 : : GdkRGBA *fill_color;
69 : : gboolean stroke;
70 : : double stroke_width;
71 : : GdkRGBA *outline_color;
72 : : double outline_width;
73 : : GArray *dashes; /* double */
74 : :
75 : : GList *nodes; /* ShumateLocation */
76 : : };
77 : :
78 [ + + + - ]: 19 : G_DEFINE_TYPE (ShumatePathLayer, shumate_path_layer, SHUMATE_TYPE_LAYER);
79 : :
80 : : static void
81 : 0 : on_viewport_changed (ShumatePathLayer *self,
82 : : GParamSpec *pspec,
83 : : ShumateViewport *view)
84 : : {
85 [ # # ]: 0 : g_assert (SHUMATE_IS_PATH_LAYER (self));
86 : :
87 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
88 : 0 : }
89 : :
90 : :
91 : : static void
92 : 0 : shumate_path_layer_get_property (GObject *object,
93 : : guint property_id,
94 : : G_GNUC_UNUSED GValue *value,
95 : : GParamSpec *pspec)
96 : : {
97 : 0 : ShumatePathLayer *self = SHUMATE_PATH_LAYER (object);
98 : :
99 [ # # # # : 0 : switch (property_id)
# # # #
# ]
100 : : {
101 : 0 : case PROP_CLOSED_PATH:
102 : 0 : g_value_set_boolean (value, self->closed_path);
103 : 0 : break;
104 : :
105 : 0 : case PROP_FILL:
106 : 0 : g_value_set_boolean (value, self->fill);
107 : 0 : break;
108 : :
109 : 0 : case PROP_STROKE:
110 : 0 : g_value_set_boolean (value, self->stroke);
111 : 0 : break;
112 : :
113 : 0 : case PROP_FILL_COLOR:
114 : 0 : g_value_set_boxed (value, self->fill_color);
115 : 0 : break;
116 : :
117 : 0 : case PROP_STROKE_COLOR:
118 : 0 : g_value_set_boxed (value, self->stroke_color);
119 : 0 : break;
120 : :
121 : 0 : case PROP_STROKE_WIDTH:
122 : 0 : g_value_set_double (value, self->stroke_width);
123 : 0 : break;
124 : :
125 : 0 : case PROP_OUTLINE_COLOR:
126 : 0 : g_value_set_boxed (value, self->outline_color);
127 : 0 : break;
128 : :
129 : 0 : case PROP_OUTLINE_WIDTH:
130 : 0 : g_value_set_double (value, self->outline_width);
131 : 0 : break;
132 : :
133 : 0 : default:
134 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
135 : : }
136 : 0 : }
137 : :
138 : :
139 : : static void
140 : 0 : shumate_path_layer_set_property (GObject *object,
141 : : guint property_id,
142 : : const GValue *value,
143 : : GParamSpec *pspec)
144 : : {
145 [ # # # # : 0 : switch (property_id)
# # # #
# ]
146 : : {
147 : 0 : case PROP_CLOSED_PATH:
148 : 0 : shumate_path_layer_set_closed (SHUMATE_PATH_LAYER (object),
149 : : g_value_get_boolean (value));
150 : 0 : break;
151 : :
152 : 0 : case PROP_FILL:
153 : 0 : shumate_path_layer_set_fill (SHUMATE_PATH_LAYER (object),
154 : : g_value_get_boolean (value));
155 : 0 : break;
156 : :
157 : 0 : case PROP_STROKE:
158 : 0 : shumate_path_layer_set_stroke (SHUMATE_PATH_LAYER (object),
159 : : g_value_get_boolean (value));
160 : 0 : break;
161 : :
162 : 0 : case PROP_FILL_COLOR:
163 : 0 : shumate_path_layer_set_fill_color (SHUMATE_PATH_LAYER (object),
164 : 0 : g_value_get_boxed (value));
165 : 0 : break;
166 : :
167 : 0 : case PROP_STROKE_COLOR:
168 : 0 : shumate_path_layer_set_stroke_color (SHUMATE_PATH_LAYER (object),
169 : 0 : g_value_get_boxed (value));
170 : 0 : break;
171 : :
172 : 0 : case PROP_STROKE_WIDTH:
173 : 0 : shumate_path_layer_set_stroke_width (SHUMATE_PATH_LAYER (object),
174 : : g_value_get_double (value));
175 : 0 : break;
176 : :
177 : 0 : case PROP_OUTLINE_COLOR:
178 : 0 : shumate_path_layer_set_outline_color (SHUMATE_PATH_LAYER (object),
179 : 0 : g_value_get_boxed (value));
180 : 0 : break;
181 : :
182 : 0 : case PROP_OUTLINE_WIDTH:
183 : 0 : shumate_path_layer_set_outline_width (SHUMATE_PATH_LAYER (object),
184 : : g_value_get_double (value));
185 : 0 : break;
186 : :
187 : 0 : default:
188 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
189 : : }
190 : 0 : }
191 : :
192 : :
193 : : static void
194 : 8 : shumate_path_layer_dispose (GObject *object)
195 : : {
196 : 8 : ShumatePathLayer *self = SHUMATE_PATH_LAYER (object);
197 : 8 : ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
198 : :
199 : 8 : g_signal_handlers_disconnect_by_data (viewport, self);
200 : :
201 [ - + ]: 8 : if (self->nodes)
202 : 0 : shumate_path_layer_remove_all (SHUMATE_PATH_LAYER (object));
203 : :
204 : 8 : G_OBJECT_CLASS (shumate_path_layer_parent_class)->dispose (object);
205 : 8 : }
206 : :
207 : : static void
208 : 12 : shumate_path_layer_constructed (GObject *object)
209 : : {
210 : 12 : ShumatePathLayer *self = SHUMATE_PATH_LAYER (object);
211 : 12 : ShumateViewport *viewport;
212 : :
213 : 12 : G_OBJECT_CLASS (shumate_path_layer_parent_class)->constructed (object);
214 : :
215 : 12 : viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
216 : 12 : g_signal_connect_swapped (viewport, "notify", G_CALLBACK (on_viewport_changed), self);
217 : 12 : }
218 : :
219 : :
220 : : static void
221 : 8 : shumate_path_layer_finalize (GObject *object)
222 : : {
223 : 8 : ShumatePathLayer *self = SHUMATE_PATH_LAYER (object);
224 : :
225 [ + - ]: 8 : g_clear_pointer (&self->stroke_color, gdk_rgba_free);
226 [ + - ]: 8 : g_clear_pointer (&self->outline_color, gdk_rgba_free);
227 [ + - ]: 8 : g_clear_pointer (&self->fill_color, gdk_rgba_free);
228 [ + - ]: 8 : g_clear_pointer (&self->dashes, g_array_unref);
229 : :
230 : 8 : G_OBJECT_CLASS (shumate_path_layer_parent_class)->finalize (object);
231 : 8 : }
232 : :
233 : : static void
234 : 0 : shumate_path_layer_snapshot (GtkWidget *widget,
235 : : GtkSnapshot *snapshot)
236 : : {
237 : 0 : ShumatePathLayer *self = (ShumatePathLayer *)widget;
238 : 0 : ShumateViewport *viewport;
239 : 0 : int width, height;
240 : 0 : cairo_t *cr;
241 : 0 : GList *elem;
242 : :
243 : 0 : width = gtk_widget_get_width (widget);
244 : 0 : height = gtk_widget_get_height (widget);
245 : 0 : viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
246 : :
247 [ # # # # ]: 0 : if (!gtk_widget_get_visible (widget) || width <= 0 || height <= 0)
248 : 0 : return;
249 : :
250 : 0 : cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT(0, 0, width, height));
251 : :
252 : 0 : cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL);
253 : :
254 [ # # ]: 0 : for (elem = self->nodes; elem != NULL; elem = elem->next)
255 : : {
256 : 0 : ShumateLocation *location = SHUMATE_LOCATION (elem->data);
257 : 0 : double x, y, lat, lon;
258 : :
259 : 0 : lat = shumate_location_get_latitude (location);
260 : 0 : lon = shumate_location_get_longitude (location);
261 : 0 : shumate_viewport_location_to_widget_coords (viewport, widget, lat, lon, &x, &y);
262 : :
263 : 0 : cairo_line_to (cr, x, y);
264 : : }
265 : :
266 [ # # ]: 0 : if (self->closed_path)
267 : 0 : cairo_close_path (cr);
268 : :
269 : 0 : gdk_cairo_set_source_rgba (cr, self->fill_color);
270 : :
271 [ # # ]: 0 : if (self->fill)
272 : 0 : cairo_fill_preserve (cr);
273 : :
274 [ # # ]: 0 : if (self->stroke)
275 : : {
276 : : /* width of the backgroud-colored part of the stroke,
277 : : * will be reduced by the outline, when that is set (non-zero)
278 : : */
279 : 0 : double inner_width = self->stroke_width - 2 * self->outline_width;
280 : :
281 : 0 : cairo_set_dash (cr, (const double *) self->dashes->data, self->dashes->len, 0);
282 : :
283 [ # # ]: 0 : if (self->outline_width > 0)
284 : : {
285 : 0 : gdk_cairo_set_source_rgba (cr, self->outline_color);
286 : 0 : cairo_set_line_width (cr, self->stroke_width);
287 : 0 : cairo_stroke_preserve (cr);
288 : : }
289 : :
290 : 0 : gdk_cairo_set_source_rgba (cr, self->stroke_color);
291 : 0 : cairo_set_line_width (cr, inner_width);
292 : 0 : cairo_stroke (cr);
293 : : }
294 : :
295 : 0 : cairo_destroy (cr);
296 : : }
297 : :
298 : : static char *
299 : 0 : shumate_path_layer_get_debug_text (ShumateLayer *layer)
300 : : {
301 : 0 : ShumatePathLayer *self = SHUMATE_PATH_LAYER (layer);
302 : 0 : return g_strdup_printf ("%d nodes", g_list_length (self->nodes));
303 : : }
304 : :
305 : : static void
306 : 3 : shumate_path_layer_class_init (ShumatePathLayerClass *klass)
307 : : {
308 : 3 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
309 : 3 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
310 : 3 : ShumateLayerClass *layer_class = SHUMATE_LAYER_CLASS (klass);
311 : :
312 : 3 : object_class->finalize = shumate_path_layer_finalize;
313 : 3 : object_class->dispose = shumate_path_layer_dispose;
314 : 3 : object_class->constructed = shumate_path_layer_constructed;
315 : 3 : object_class->get_property = shumate_path_layer_get_property;
316 : 3 : object_class->set_property = shumate_path_layer_set_property;
317 : :
318 : 3 : widget_class->snapshot = shumate_path_layer_snapshot;
319 : :
320 : 3 : layer_class->get_debug_text = shumate_path_layer_get_debug_text;
321 : :
322 : : /**
323 : : * ShumatePathLayer:closed:
324 : : *
325 : : * The shape is a closed path
326 : : */
327 : 6 : obj_properties[PROP_CLOSED_PATH] =
328 : 3 : g_param_spec_boolean ("closed",
329 : : "Closed Path",
330 : : "The Path is Closed",
331 : : FALSE,
332 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
333 : :
334 : : /**
335 : : * ShumatePathLayer:fill:
336 : : *
337 : : * The shape should be filled
338 : : */
339 : 6 : obj_properties[PROP_FILL] =
340 : 3 : g_param_spec_boolean ("fill",
341 : : "Fill",
342 : : "The shape is filled",
343 : : FALSE,
344 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
345 : :
346 : : /**
347 : : * ShumatePathLayer:stroke:
348 : : *
349 : : * The shape should be stroked
350 : : */
351 : 6 : obj_properties[PROP_STROKE] =
352 : 3 : g_param_spec_boolean ("stroke",
353 : : "Stroke",
354 : : "The shape is stroked",
355 : : TRUE,
356 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
357 : :
358 : : /**
359 : : * ShumatePathLayer:stroke-color:
360 : : *
361 : : * The path's stroke color
362 : : */
363 : 6 : obj_properties[PROP_STROKE_COLOR] =
364 : 3 : g_param_spec_boxed ("stroke-color",
365 : : "Stroke Color",
366 : : "The path's stroke color",
367 : : GDK_TYPE_RGBA,
368 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
369 : :
370 : : /**
371 : : * ShumatePathLayer:fill-color:
372 : : *
373 : : * The path's fill color
374 : : */
375 : 6 : obj_properties[PROP_FILL_COLOR] =
376 : 3 : g_param_spec_boxed ("fill-color",
377 : : "Fill Color",
378 : : "The path's fill color",
379 : : GDK_TYPE_RGBA,
380 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
381 : :
382 : : /**
383 : : * ShumatePathLayer:stroke-width:
384 : : *
385 : : * The path's stroke width (in pixels)
386 : : */
387 : 6 : obj_properties[PROP_STROKE_WIDTH] =
388 : 3 : g_param_spec_double ("stroke-width",
389 : : "Stroke Width",
390 : : "The path's stroke width",
391 : : 0,
392 : : 100.0,
393 : : 2.0,
394 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
395 : :
396 : : /**
397 : : * ShumatePathLayer:outline-color:
398 : : *
399 : : * The path's outline color
400 : : */
401 : 6 : obj_properties[PROP_OUTLINE_COLOR] =
402 : 3 : g_param_spec_boxed ("outline-color",
403 : : "Outline Color",
404 : : "The path's outline color",
405 : : GDK_TYPE_RGBA,
406 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
407 : :
408 : : /**
409 : : * ShumatePathLayer:outline-width:
410 : : *
411 : : * The path's outline width (in pixels)
412 : : */
413 : 6 : obj_properties[PROP_OUTLINE_WIDTH] =
414 : 3 : g_param_spec_double ("outline-width",
415 : : "Outline Width",
416 : : "The path's outline width",
417 : : 0,
418 : : 50.0,
419 : : 0.0,
420 : : G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
421 : :
422 : 3 : g_object_class_install_properties (object_class,
423 : : N_PROPERTIES,
424 : : obj_properties);
425 : 3 : }
426 : :
427 : : static void
428 : 12 : shumate_path_layer_init (ShumatePathLayer *self)
429 : : {
430 : 12 : self->fill = FALSE;
431 : 12 : self->stroke = TRUE;
432 : 12 : self->stroke_width = 2.0;
433 : 12 : self->outline_width = 0.0;
434 : 12 : self->nodes = NULL;
435 : 12 : self->dashes = g_array_new (FALSE, TRUE, sizeof(double));
436 : :
437 : 12 : self->fill_color = gdk_rgba_copy (&DEFAULT_FILL_COLOR);
438 : 12 : self->stroke_color = gdk_rgba_copy (&DEFAULT_STROKE_COLOR);
439 : 12 : self->outline_color = gdk_rgba_copy (&DEFAULT_OUTLINE_COLOR);
440 : 12 : }
441 : :
442 : : /**
443 : : * shumate_path_layer_new:
444 : : * @viewport: the [class@Viewport]
445 : : *
446 : : * Creates a new instance of [class@PathLayer].
447 : : *
448 : : * Returns: a new instance of [class@PathLayer].
449 : : */
450 : : ShumatePathLayer *
451 : 12 : shumate_path_layer_new (ShumateViewport *viewport)
452 : : {
453 : 12 : return g_object_new (SHUMATE_TYPE_PATH_LAYER,
454 : : "viewport", viewport,
455 : : NULL);
456 : : }
457 : :
458 : : static void
459 : 0 : position_notify (ShumateLocation *location,
460 : : GParamSpec *pspec,
461 : : ShumatePathLayer *self)
462 : : {
463 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
464 : 0 : }
465 : :
466 : : static void
467 : 0 : add_node (ShumatePathLayer *self,
468 : : ShumateLocation *location,
469 : : gboolean prepend,
470 : : guint position)
471 : : {
472 : 0 : g_signal_connect (G_OBJECT (location), "notify::latitude", G_CALLBACK (position_notify), self);
473 : :
474 [ # # ]: 0 : if (prepend)
475 : 0 : self->nodes = g_list_prepend (self->nodes, g_object_ref_sink (location));
476 : : else
477 : 0 : self->nodes = g_list_insert (self->nodes, g_object_ref_sink (location), position);
478 : :
479 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
480 : 0 : }
481 : :
482 : :
483 : : /**
484 : : * shumate_path_layer_add_node:
485 : : * @self: a [class@PathLayer]
486 : : * @location: a [iface@Location]
487 : : *
488 : : * Adds a [iface@Location] object to the layer.
489 : : * The node is prepended to the list.
490 : : */
491 : : void
492 : 0 : shumate_path_layer_add_node (ShumatePathLayer *self,
493 : : ShumateLocation *location)
494 : : {
495 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
496 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_LOCATION (location));
497 : :
498 : 0 : add_node (self, location, TRUE, 0);
499 : : }
500 : :
501 : :
502 : : /**
503 : : * shumate_path_layer_remove_all:
504 : : * @self: a [class@PathLayer]
505 : : *
506 : : * Removes all [iface@Location] objects from the layer.
507 : : */
508 : : void
509 : 0 : shumate_path_layer_remove_all (ShumatePathLayer *self)
510 : : {
511 : 0 : GList *elem;
512 : :
513 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
514 : :
515 [ # # ]: 0 : for (elem = self->nodes; elem != NULL; elem = elem->next)
516 : : {
517 : 0 : GObject *node = G_OBJECT (elem->data);
518 : :
519 : 0 : g_signal_handlers_disconnect_by_func (node,
520 : : G_CALLBACK (position_notify), self);
521 : :
522 : 0 : g_object_unref (node);
523 : : }
524 : :
525 [ # # ]: 0 : g_clear_pointer (&self->nodes, g_list_free);
526 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
527 : : }
528 : :
529 : :
530 : : /**
531 : : * shumate_path_layer_get_nodes:
532 : : * @self: a [class@PathLayer]
533 : : *
534 : : * Gets a copy of the list of all [iface@Location] objects inserted into the layer. You should
535 : : * free the list but not its contents.
536 : : *
537 : : * Returns: (transfer container) (element-type ShumateLocation): the list
538 : : */
539 : : GList *
540 : 0 : shumate_path_layer_get_nodes (ShumatePathLayer *self)
541 : : {
542 : 0 : GList *lst;
543 : :
544 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), NULL);
545 : :
546 : 0 : lst = g_list_copy (self->nodes);
547 : 0 : return g_list_reverse (lst);
548 : : }
549 : :
550 : : /**
551 : : * shumate_path_layer_remove_node:
552 : : * @self: a [class@PathLayer]
553 : : * @location: a [iface@Location]
554 : : *
555 : : * Removes the [iface@Location] object from the layer.
556 : : */
557 : : void
558 : 0 : shumate_path_layer_remove_node (ShumatePathLayer *self,
559 : : ShumateLocation *location)
560 : : {
561 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
562 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_LOCATION (location));
563 : :
564 : 0 : g_signal_handlers_disconnect_by_func (G_OBJECT (location), G_CALLBACK (position_notify), self);
565 : :
566 : 0 : self->nodes = g_list_remove (self->nodes, location);
567 : 0 : g_object_unref (location);
568 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
569 : : }
570 : :
571 : : /**
572 : : * shumate_path_layer_insert_node:
573 : : * @self: a [class@PathLayer]
574 : : * @location: a [iface@Location]
575 : : * @position: position in the list where the [iface@Location] object should be inserted
576 : : *
577 : : * Inserts a [iface@Location] object to the specified position.
578 : : */
579 : : void
580 : 0 : shumate_path_layer_insert_node (ShumatePathLayer *self,
581 : : ShumateLocation *location,
582 : : guint position)
583 : : {
584 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
585 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_LOCATION (location));
586 : :
587 : 0 : add_node (self, location, FALSE, position);
588 : : }
589 : :
590 : : /**
591 : : * shumate_path_layer_set_fill_color:
592 : : * @self: a [class@PathLayer]
593 : : * @color: (nullable): The path's fill color or %NULL to reset to the
594 : : * default color. The color parameter is copied.
595 : : *
596 : : * Set the path's fill color.
597 : : */
598 : : void
599 : 0 : shumate_path_layer_set_fill_color (ShumatePathLayer *self,
600 : : const GdkRGBA *color)
601 : : {
602 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
603 : :
604 [ # # ]: 0 : if (self->fill_color != NULL)
605 : 0 : gdk_rgba_free (self->fill_color);
606 : :
607 [ # # ]: 0 : if (color == NULL)
608 : 0 : color = &DEFAULT_FILL_COLOR;
609 : :
610 : 0 : self->fill_color = gdk_rgba_copy (color);
611 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_FILL_COLOR]);
612 : :
613 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
614 : : }
615 : :
616 : :
617 : : /**
618 : : * shumate_path_layer_get_fill_color:
619 : : * @self: a [class@PathLayer]
620 : : *
621 : : * Gets the path's fill color.
622 : : *
623 : : * Returns: the path's fill color.
624 : : */
625 : : GdkRGBA *
626 : 0 : shumate_path_layer_get_fill_color (ShumatePathLayer *self)
627 : : {
628 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), NULL);
629 : :
630 : 0 : return self->fill_color;
631 : : }
632 : :
633 : :
634 : : /**
635 : : * shumate_path_layer_set_stroke_color:
636 : : * @self: a [class@PathLayer]
637 : : * @color: (nullable): The path's stroke color or %NULL to reset to the
638 : : * default color. The color parameter is copied.
639 : : *
640 : : * Set the path's stroke color.
641 : : */
642 : : void
643 : 0 : shumate_path_layer_set_stroke_color (ShumatePathLayer *self,
644 : : const GdkRGBA *color)
645 : : {
646 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
647 : :
648 [ # # ]: 0 : if (self->stroke_color != NULL)
649 : 0 : gdk_rgba_free (self->stroke_color);
650 : :
651 [ # # ]: 0 : if (color == NULL)
652 : 0 : color = &DEFAULT_STROKE_COLOR;
653 : :
654 : 0 : self->stroke_color = gdk_rgba_copy (color);
655 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_STROKE_COLOR]);
656 : :
657 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
658 : : }
659 : :
660 : :
661 : : /**
662 : : * shumate_path_layer_get_stroke_color:
663 : : * @self: a [class@PathLayer]
664 : : *
665 : : * Gets the path's stroke color.
666 : : *
667 : : * Returns: the path's stroke color.
668 : : */
669 : : GdkRGBA *
670 : 0 : shumate_path_layer_get_stroke_color (ShumatePathLayer *self)
671 : : {
672 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), NULL);
673 : :
674 : 0 : return self->stroke_color;
675 : : }
676 : :
677 : : /**
678 : : * shumate_path_layer_set_outline_color:
679 : : * @self: a [class@PathLayer]
680 : : * @color: (nullable): The path's outline color or %NULL to reset to the
681 : : * default color. The color parameter is copied.
682 : : *
683 : : * Set the path's outline color.
684 : : */
685 : : void
686 : 0 : shumate_path_layer_set_outline_color (ShumatePathLayer *self,
687 : : const GdkRGBA *color)
688 : : {
689 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
690 : :
691 [ # # ]: 0 : if (self->outline_color != NULL)
692 : 0 : gdk_rgba_free (self->outline_color);
693 : :
694 [ # # ]: 0 : if (color == NULL)
695 : 0 : color = &DEFAULT_OUTLINE_COLOR;
696 : :
697 : 0 : self->outline_color = gdk_rgba_copy (color);
698 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_OUTLINE_COLOR]);
699 : :
700 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
701 : : }
702 : :
703 : : /**
704 : : * shumate_path_layer_get_outline_color:
705 : : * @self: a [class@PathLayer]
706 : : *
707 : : * Gets the path's outline color.
708 : : *
709 : : * Returns: the path's outline color.
710 : : */
711 : : GdkRGBA *
712 : 0 : shumate_path_layer_get_outline_color (ShumatePathLayer *self)
713 : : {
714 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), NULL);
715 : :
716 : 0 : return self->outline_color;
717 : : }
718 : :
719 : : /**
720 : : * shumate_path_layer_set_stroke:
721 : : * @self: a [class@PathLayer]
722 : : * @value: if the path is stroked
723 : : *
724 : : * Sets the path to be stroked
725 : : */
726 : : void
727 : 0 : shumate_path_layer_set_stroke (ShumatePathLayer *self,
728 : : gboolean value)
729 : : {
730 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
731 : :
732 : 0 : self->stroke = value;
733 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_STROKE]);
734 : :
735 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
736 : : }
737 : :
738 : :
739 : : /**
740 : : * shumate_path_layer_get_stroke:
741 : : * @self: a [class@PathLayer]
742 : : *
743 : : * Checks whether the path is stroked.
744 : : *
745 : : * Returns: %TRUE if the path is stroked, %FALSE otherwise.
746 : : */
747 : : gboolean
748 : 0 : shumate_path_layer_get_stroke (ShumatePathLayer *self)
749 : : {
750 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), FALSE);
751 : :
752 : 0 : return self->stroke;
753 : : }
754 : :
755 : :
756 : : /**
757 : : * shumate_path_layer_set_fill:
758 : : * @self: a [class@PathLayer]
759 : : * @value: if the path is filled
760 : : *
761 : : * Sets the path to be filled
762 : : */
763 : : void
764 : 0 : shumate_path_layer_set_fill (ShumatePathLayer *self,
765 : : gboolean value)
766 : : {
767 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
768 : :
769 : 0 : self->fill = value;
770 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_FILL]);
771 : :
772 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
773 : : }
774 : :
775 : :
776 : : /**
777 : : * shumate_path_layer_get_fill:
778 : : * @self: a [class@PathLayer]
779 : : *
780 : : * Checks whether the path is filled.
781 : : *
782 : : * Returns: %TRUE if the path is filled, %FALSE otherwise.
783 : : */
784 : : gboolean
785 : 0 : shumate_path_layer_get_fill (ShumatePathLayer *self)
786 : : {
787 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), FALSE);
788 : :
789 : 0 : return self->fill;
790 : : }
791 : :
792 : :
793 : : /**
794 : : * shumate_path_layer_set_stroke_width:
795 : : * @self: a [class@PathLayer]
796 : : * @value: the width of the stroke (in pixels)
797 : : *
798 : : * Sets the width of the stroke
799 : : */
800 : : void
801 : 0 : shumate_path_layer_set_stroke_width (ShumatePathLayer *self,
802 : : double value)
803 : : {
804 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
805 : :
806 : 0 : self->stroke_width = value;
807 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_STROKE_WIDTH]);
808 : :
809 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
810 : : }
811 : :
812 : :
813 : : /**
814 : : * shumate_path_layer_get_stroke_width:
815 : : * @self: a [class@PathLayer]
816 : : *
817 : : * Gets the width of the stroke.
818 : : *
819 : : * Returns: the width of the stroke
820 : : */
821 : : double
822 : 0 : shumate_path_layer_get_stroke_width (ShumatePathLayer *self)
823 : : {
824 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), 0);
825 : :
826 : 0 : return self->stroke_width;
827 : : }
828 : :
829 : : /**
830 : : * shumate_path_layer_set_outline_width:
831 : : * @self: a [class@PathLayer]
832 : : * @value: the width of the outline (in pixels)
833 : : *
834 : : * Sets the width of the outline
835 : : */
836 : : void
837 : 0 : shumate_path_layer_set_outline_width (ShumatePathLayer *self,
838 : : double value)
839 : : {
840 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
841 : :
842 : 0 : self->outline_width = value;
843 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_OUTLINE_WIDTH]);
844 : :
845 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
846 : : }
847 : :
848 : :
849 : : /**
850 : : * shumate_path_layer_get_outline_width:
851 : : * @self: a [class@PathLayer]
852 : : *
853 : : * Gets the width of the outline.
854 : : *
855 : : * Returns: the width of the outline
856 : : */
857 : : double
858 : 0 : shumate_path_layer_get_outline_width (ShumatePathLayer *self)
859 : : {
860 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), 0);
861 : :
862 : 0 : return self->outline_width;
863 : : }
864 : :
865 : : /**
866 : : * shumate_path_layer_set_closed:
867 : : * @self: a [class@PathLayer]
868 : : * @value: %TRUE to make the path closed
869 : : *
870 : : * Makes the path closed.
871 : : */
872 : : void
873 : 0 : shumate_path_layer_set_closed (ShumatePathLayer *self,
874 : : gboolean value)
875 : : {
876 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
877 : :
878 : 0 : self->closed_path = value;
879 : 0 : g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_CLOSED_PATH]);
880 : :
881 : 0 : gtk_widget_queue_draw (GTK_WIDGET (self));
882 : : }
883 : :
884 : :
885 : : /**
886 : : * shumate_path_layer_get_closed:
887 : : * @self: a [class@PathLayer]
888 : : *
889 : : * Gets information whether the path is closed.
890 : : *
891 : : * Returns: %TRUE when the path is closed, %FALSE otherwise
892 : : */
893 : : gboolean
894 : 0 : shumate_path_layer_get_closed (ShumatePathLayer *self)
895 : : {
896 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), FALSE);
897 : :
898 : 0 : return self->closed_path;
899 : : }
900 : :
901 : :
902 : : /**
903 : : * shumate_path_layer_set_dash:
904 : : * @self: a [class@PathLayer]
905 : : * @dash_pattern: (element-type guint): list of integer values representing lengths
906 : : * of dashes/spaces (see cairo documentation of cairo_set_dash())
907 : : *
908 : : * Sets dashed line pattern in a way similar to cairo_set_dash() of cairo. This
909 : : * method supports only integer values for segment lengths. The values have to be
910 : : * passed inside the data pointer of the list (using the %GUINT_TO_POINTER conversion)
911 : : *
912 : : * Pass %NULL to use solid line.
913 : : */
914 : : void
915 : 0 : shumate_path_layer_set_dash (ShumatePathLayer *self,
916 : : GList *dash_pattern)
917 : : {
918 : 0 : GList *iter = NULL;
919 : :
920 [ # # ]: 0 : g_return_if_fail (SHUMATE_IS_PATH_LAYER (self));
921 : :
922 : 0 : g_array_set_size (self->dashes, 0);
923 [ # # ]: 0 : if (dash_pattern == NULL)
924 : : return;
925 : :
926 [ # # ]: 0 : for (iter = dash_pattern; iter != NULL; iter = iter->next)
927 : : {
928 : 0 : double val = (double) GPOINTER_TO_UINT (iter->data);
929 : 0 : g_array_append_val (self->dashes, val);
930 : : }
931 : : }
932 : :
933 : :
934 : : /**
935 : : * shumate_path_layer_get_dash:
936 : : * @self: a [class@PathLayer]
937 : : *
938 : : * Returns the list of dash segment lengths.
939 : : *
940 : : * Returns: (transfer full) (element-type guint): the list
941 : : */
942 : : GList *
943 : 0 : shumate_path_layer_get_dash (ShumatePathLayer *self)
944 : : {
945 : 0 : GList *list = NULL;
946 : 0 : guint i;
947 : :
948 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_PATH_LAYER (self), NULL);
949 : :
950 [ # # ]: 0 : for (i = 0; i < self->dashes->len; i++)
951 : 0 : list = g_list_append (list, GUINT_TO_POINTER ((guint) g_array_index (self->dashes, double, i)));
952 : :
953 : : return list;
954 : : }
|