Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2022 James Westman <james@jwestman.net>
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, see <https://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #include "shumate-location.h"
19 : : #include "shumate-symbol-event-private.h"
20 : :
21 : : /**
22 : : * ShumateSymbolEvent:
23 : : *
24 : : * An object containing the details of a map feature that has been clicked.
25 : : * It is the argument of the [signal@MapLayer::symbol-clicked] and
26 : : * [signal@SimpleMap::symbol-clicked] signals.
27 : : *
28 : : * When vector maps are rendered, they may contain labels and icons. When one
29 : : * of these symbols is clicked, these signals are emitted to give the
30 : : * application access to the original location and details of the map feature.
31 : : *
32 : : * [class@SymbolEvent] implements [iface@Location] so you can get the latitude
33 : : * and longitude of the feature that was clicked.
34 : : *
35 : : * Since: 1.1
36 : : */
37 : :
38 : : struct _ShumateSymbolEvent
39 : : {
40 : : GObject parent_instance;
41 : :
42 : : char *layer;
43 : : char *source_layer;
44 : : char *feature_id;
45 : : double lat, lon;
46 : : GHashTable *tags;
47 : : };
48 : :
49 : : static void location_interface_init (ShumateLocationInterface *iface);
50 : :
51 [ + + + - ]: 5 : G_DEFINE_FINAL_TYPE_WITH_CODE (ShumateSymbolEvent, shumate_symbol_event, G_TYPE_OBJECT,
52 : : G_IMPLEMENT_INTERFACE (SHUMATE_TYPE_LOCATION, location_interface_init))
53 : :
54 : : enum {
55 : : PROP_0,
56 : : PROP_LAYER,
57 : : PROP_SOURCE_LAYER,
58 : : PROP_FEATURE_ID,
59 : : N_PROPS,
60 : :
61 : : PROP_LONGITUDE,
62 : : PROP_LATITUDE,
63 : : };
64 : :
65 : : static GParamSpec *properties [N_PROPS];
66 : :
67 : : static void
68 : 0 : shumate_symbol_event_finalize (GObject *object)
69 : : {
70 : 0 : ShumateSymbolEvent *self = (ShumateSymbolEvent *)object;
71 : :
72 [ # # ]: 0 : g_clear_pointer (&self->layer, g_free);
73 [ # # ]: 0 : g_clear_pointer (&self->source_layer, g_free);
74 [ # # ]: 0 : g_clear_pointer (&self->feature_id, g_free);
75 [ # # ]: 0 : g_clear_pointer (&self->tags, g_hash_table_unref);
76 : :
77 : 0 : G_OBJECT_CLASS (shumate_symbol_event_parent_class)->finalize (object);
78 : 0 : }
79 : :
80 : : static void
81 : 0 : shumate_symbol_event_get_property (GObject *object,
82 : : guint prop_id,
83 : : GValue *value,
84 : : GParamSpec *pspec)
85 : : {
86 : 0 : ShumateSymbolEvent *self = SHUMATE_SYMBOL_EVENT (object);
87 : :
88 [ # # # # : 0 : switch (prop_id)
# # ]
89 : : {
90 : 0 : case PROP_LAYER:
91 : 0 : g_value_set_string (value, self->layer);
92 : 0 : break;
93 : 0 : case PROP_SOURCE_LAYER:
94 : 0 : g_value_set_string (value, self->source_layer);
95 : 0 : break;
96 : 0 : case PROP_FEATURE_ID:
97 : 0 : g_value_set_string (value, self->feature_id);
98 : 0 : break;
99 : 0 : case PROP_LATITUDE:
100 : 0 : g_value_set_double (value, self->lat);
101 : 0 : break;
102 : 0 : case PROP_LONGITUDE:
103 : 0 : g_value_set_double (value, self->lon);
104 : 0 : break;
105 : 0 : default:
106 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
107 : : }
108 : 0 : }
109 : :
110 : : static void
111 : 0 : shumate_symbol_event_set_property (GObject *object,
112 : : guint prop_id,
113 : : const GValue *value,
114 : : GParamSpec *pspec)
115 : : {
116 [ # # ]: 0 : switch (prop_id)
117 : : {
118 : 0 : case PROP_LATITUDE:
119 : : case PROP_LONGITUDE:
120 : 0 : g_warning ("Cannot change the location of a ShumateSymbolEvent");
121 : 0 : break;
122 : 0 : default:
123 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124 : : }
125 : 0 : }
126 : :
127 : : static void
128 : 1 : shumate_symbol_event_class_init (ShumateSymbolEventClass *klass)
129 : : {
130 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
131 : :
132 : 1 : object_class->finalize = shumate_symbol_event_finalize;
133 : 1 : object_class->get_property = shumate_symbol_event_get_property;
134 : 1 : object_class->set_property = shumate_symbol_event_set_property;
135 : :
136 : : /**
137 : : * ShumateSymbolEvent:layer:
138 : : *
139 : : * The ID of the style layer of the symbol that this event pertains to.
140 : : *
141 : : * Since: 1.1
142 : : */
143 : 2 : properties[PROP_LAYER] =
144 : 1 : g_param_spec_string ("layer",
145 : : "layer",
146 : : "layer",
147 : : NULL,
148 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
149 : :
150 : : /**
151 : : * ShumateSymbolEvent:source-layer:
152 : : *
153 : : * The ID of the source layer of the symbol that this event pertains to.
154 : : */
155 : 2 : properties[PROP_SOURCE_LAYER] =
156 : 1 : g_param_spec_string ("source-layer",
157 : : "source-layer",
158 : : "source-layer",
159 : : NULL,
160 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
161 : :
162 : : /**
163 : : * ShumateSymbolEvent:feature-id:
164 : : *
165 : : * The ID of the feature that this event pertains to, as it was given in the
166 : : * data source.
167 : : *
168 : : * Since: 1.1
169 : : */
170 : 2 : properties[PROP_FEATURE_ID] =
171 : 1 : g_param_spec_string ("feature-id",
172 : : "Feature ID",
173 : : "Feature ID",
174 : : NULL,
175 : : G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
176 : :
177 : 1 : g_object_class_install_properties (object_class, N_PROPS, properties);
178 : :
179 : 1 : g_object_class_override_property (object_class,
180 : : PROP_LONGITUDE,
181 : : "longitude");
182 : :
183 : 1 : g_object_class_override_property (object_class,
184 : : PROP_LATITUDE,
185 : : "latitude");
186 : 1 : }
187 : :
188 : : static void
189 : 0 : shumate_symbol_event_init (ShumateSymbolEvent *self)
190 : : {
191 : 0 : self->tags = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
192 : 0 : }
193 : :
194 : : static double
195 : 0 : shumate_symbol_event_get_latitude (ShumateLocation *location)
196 : : {
197 : 0 : ShumateSymbolEvent *self = (ShumateSymbolEvent *) location;
198 : 0 : return self->lat;
199 : : }
200 : :
201 : : static double
202 : 0 : shumate_symbol_event_get_longitude (ShumateLocation *location)
203 : : {
204 : 0 : ShumateSymbolEvent *self = (ShumateSymbolEvent *) location;
205 : 0 : return self->lon;
206 : : }
207 : :
208 : : static void
209 : 0 : shumate_symbol_event_set_location (ShumateLocation *location,
210 : : double lat,
211 : : double lon)
212 : : {
213 : 0 : g_warning ("Cannot change the location of a ShumateSymbolEvent");
214 : 0 : }
215 : :
216 : : static void
217 : 1 : location_interface_init (ShumateLocationInterface *iface)
218 : : {
219 : 1 : iface->get_latitude = shumate_symbol_event_get_latitude;
220 : 1 : iface->get_longitude = shumate_symbol_event_get_longitude;
221 : 1 : iface->set_location = shumate_symbol_event_set_location;
222 : 1 : }
223 : :
224 : : /**
225 : : * shumate_symbol_event_get_layer:
226 : : * @self: a [class@SymbolEvent]
227 : : *
228 : : * Gets the name of the layer the clicked symbol is in, as named in the vector
229 : : * stylesheet.
230 : : *
231 : : * Note that this is distinct from the name of the layer in the vector tile
232 : : * schema. Some styles have multiple symbol layers derived from the same
233 : : * data source layer.
234 : : *
235 : : * Returns: (transfer none): the layer name
236 : : *
237 : : * Since: 1.1
238 : : */
239 : : const char *
240 : 0 : shumate_symbol_event_get_layer (ShumateSymbolEvent *self)
241 : : {
242 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL);
243 : 0 : return self->layer;
244 : : }
245 : :
246 : : /**
247 : : * shumate_symbol_event_get_source_layer:
248 : : * @self: a [class@SymbolEvent]
249 : : *
250 : : * Gets the name of the source layer the clicked feature is in,
251 : : * as named in the vector tile schema.
252 : : *
253 : : * Returns: (transfer none): the layer name
254 : : *
255 : : * Since: 1.1
256 : : */
257 : : const char *
258 : 0 : shumate_symbol_event_get_source_layer (ShumateSymbolEvent *self)
259 : : {
260 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL);
261 : 0 : return self->source_layer;
262 : : }
263 : :
264 : : /**
265 : : * shumate_symbol_event_get_feature_id:
266 : : * @self: a [class@SymbolEvent]
267 : : *
268 : : * Gets the feature ID as specified in the data source. The meaning of the
269 : : * ID, if any, is up to the source.
270 : : *
271 : : * Feature IDs in Mapbox Vector Tile format are integers, but they are
272 : : * formatted as a string here for futureproofing.
273 : : *
274 : : * Returns: (transfer none): the feature ID
275 : : *
276 : : * Since: 1.1
277 : : */
278 : : const char *
279 : 0 : shumate_symbol_event_get_feature_id (ShumateSymbolEvent *self)
280 : : {
281 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL);
282 : 0 : return self->feature_id;
283 : : }
284 : :
285 : : /**
286 : : * shumate_symbol_event_get_keys:
287 : : * @self: a [class@SymbolEvent]
288 : : *
289 : : * Gets a list of the keys of the source feature's tags.
290 : : *
291 : : * Returns: (transfer container): a list of the tag keys
292 : : *
293 : : * Since: 1.1
294 : : */
295 : : const GStrv
296 : 0 : shumate_symbol_event_get_keys (ShumateSymbolEvent *self)
297 : : {
298 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL);
299 : 0 : return (GStrv)g_hash_table_get_keys_as_array (self->tags, NULL);
300 : : }
301 : :
302 : : /**
303 : : * shumate_symbol_event_get_tag:
304 : : * @self: a [class@SymbolEvent]
305 : : * @tag_name: the tag to get
306 : : *
307 : : * Gets a tag from the source feature.
308 : : *
309 : : * The available tags depend on the vector tile schema and the source layer.
310 : : * Check the documentation for the tiles you're using to see what information
311 : : * is available.
312 : : *
313 : : * Returns: (transfer none): the tag value, formatted as a string
314 : : *
315 : : * Since: 1.1
316 : : */
317 : : const char *
318 : 0 : shumate_symbol_event_get_tag (ShumateSymbolEvent *self,
319 : : const char *tag_name)
320 : : {
321 [ # # ]: 0 : g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL);
322 : 0 : return g_hash_table_lookup (self->tags, tag_name);
323 : : }
324 : :
325 : : ShumateSymbolEvent *
326 : 0 : shumate_symbol_event_new (const char *layer,
327 : : const char *source_layer,
328 : : const char *feature_id,
329 : : GHashTable *tags)
330 : : {
331 : 0 : ShumateSymbolEvent *self = g_object_new (SHUMATE_TYPE_SYMBOL_EVENT, NULL);
332 : :
333 [ # # ]: 0 : self->layer = g_strdup (layer);
334 [ # # ]: 0 : self->source_layer = g_strdup (source_layer);
335 [ # # ]: 0 : self->feature_id = g_strdup (feature_id);
336 : 0 : self->tags = g_hash_table_ref (tags);
337 : :
338 : 0 : return self;
339 : : }
340 : :
341 : : void
342 : 0 : shumate_symbol_event_set_lat_lon (ShumateSymbolEvent *self,
343 : : double lat,
344 : : double lon)
345 : : {
346 : 0 : self->lat = lat;
347 : 0 : self->lon = lon;
348 : 0 : }
|