shumate/shumate-symbol-event.c
| Line | Branch | Exec | Source |
|---|---|---|---|
| 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 | gint n_press; | ||
| 48 | }; | ||
| 49 | |||
| 50 | static void location_interface_init (ShumateLocationInterface *iface); | ||
| 51 | |||
| 52 |
4/6shumate_symbol_event_class_intern_init:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
shumate_symbol_event_get_type:
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 7 taken 2 times.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 7 not taken.
|
5 | G_DEFINE_FINAL_TYPE_WITH_CODE (ShumateSymbolEvent, shumate_symbol_event, G_TYPE_OBJECT, |
| 53 | G_IMPLEMENT_INTERFACE (SHUMATE_TYPE_LOCATION, location_interface_init)) | ||
| 54 | |||
| 55 | enum { | ||
| 56 | PROP_0, | ||
| 57 | PROP_LAYER, | ||
| 58 | PROP_SOURCE_LAYER, | ||
| 59 | PROP_FEATURE_ID, | ||
| 60 | PROP_N_PRESS, | ||
| 61 | N_PROPS, | ||
| 62 | |||
| 63 | PROP_LONGITUDE, | ||
| 64 | PROP_LATITUDE, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static GParamSpec *properties [N_PROPS]; | ||
| 68 | |||
| 69 | static void | ||
| 70 | ✗ | shumate_symbol_event_finalize (GObject *object) | |
| 71 | { | ||
| 72 | ✗ | ShumateSymbolEvent *self = (ShumateSymbolEvent *)object; | |
| 73 | |||
| 74 | ✗ | g_clear_pointer (&self->layer, g_free); | |
| 75 | ✗ | g_clear_pointer (&self->source_layer, g_free); | |
| 76 | ✗ | g_clear_pointer (&self->feature_id, g_free); | |
| 77 | ✗ | g_clear_pointer (&self->tags, g_hash_table_unref); | |
| 78 | |||
| 79 | ✗ | G_OBJECT_CLASS (shumate_symbol_event_parent_class)->finalize (object); | |
| 80 | ✗ | } | |
| 81 | |||
| 82 | static void | ||
| 83 | ✗ | shumate_symbol_event_get_property (GObject *object, | |
| 84 | guint prop_id, | ||
| 85 | GValue *value, | ||
| 86 | GParamSpec *pspec) | ||
| 87 | { | ||
| 88 | ✗ | ShumateSymbolEvent *self = SHUMATE_SYMBOL_EVENT (object); | |
| 89 | |||
| 90 | ✗ | switch (prop_id) | |
| 91 | { | ||
| 92 | ✗ | case PROP_LAYER: | |
| 93 | ✗ | g_value_set_string (value, self->layer); | |
| 94 | ✗ | break; | |
| 95 | ✗ | case PROP_SOURCE_LAYER: | |
| 96 | ✗ | g_value_set_string (value, self->source_layer); | |
| 97 | ✗ | break; | |
| 98 | ✗ | case PROP_FEATURE_ID: | |
| 99 | ✗ | g_value_set_string (value, self->feature_id); | |
| 100 | ✗ | break; | |
| 101 | ✗ | case PROP_LATITUDE: | |
| 102 | ✗ | g_value_set_double (value, self->lat); | |
| 103 | ✗ | break; | |
| 104 | ✗ | case PROP_LONGITUDE: | |
| 105 | ✗ | g_value_set_double (value, self->lon); | |
| 106 | ✗ | break; | |
| 107 | ✗ | case PROP_N_PRESS: | |
| 108 | ✗ | g_value_set_int (value, self->n_press); | |
| 109 | ✗ | break; | |
| 110 | ✗ | default: | |
| 111 | ✗ | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
| 112 | } | ||
| 113 | ✗ | } | |
| 114 | |||
| 115 | static void | ||
| 116 | ✗ | shumate_symbol_event_set_property (GObject *object, | |
| 117 | guint prop_id, | ||
| 118 | const GValue *value, | ||
| 119 | GParamSpec *pspec) | ||
| 120 | { | ||
| 121 | ✗ | ShumateSymbolEvent *symbol_event = SHUMATE_SYMBOL_EVENT (object); | |
| 122 | |||
| 123 | ✗ | switch (prop_id) | |
| 124 | { | ||
| 125 | ✗ | case PROP_LATITUDE: | |
| 126 | case PROP_LONGITUDE: | ||
| 127 | ✗ | g_warning ("Cannot change the location of a ShumateSymbolEvent"); | |
| 128 | ✗ | break; | |
| 129 | ✗ | case PROP_N_PRESS: | |
| 130 | ✗ | shumate_symbol_event_set_n_press (symbol_event, g_value_get_int (value)); | |
| 131 | ✗ | break; | |
| 132 | ✗ | default: | |
| 133 | ✗ | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
| 134 | } | ||
| 135 | ✗ | } | |
| 136 | |||
| 137 | static void | ||
| 138 | 1 | shumate_symbol_event_class_init (ShumateSymbolEventClass *klass) | |
| 139 | { | ||
| 140 | 1 | GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
| 141 | |||
| 142 | 1 | object_class->finalize = shumate_symbol_event_finalize; | |
| 143 | 1 | object_class->get_property = shumate_symbol_event_get_property; | |
| 144 | 1 | object_class->set_property = shumate_symbol_event_set_property; | |
| 145 | |||
| 146 | /** | ||
| 147 | * ShumateSymbolEvent:layer: | ||
| 148 | * | ||
| 149 | * The ID of the style layer of the symbol that this event pertains to. | ||
| 150 | * | ||
| 151 | * Since: 1.1 | ||
| 152 | */ | ||
| 153 | 2 | properties[PROP_LAYER] = | |
| 154 | 1 | g_param_spec_string ("layer", NULL, NULL, | |
| 155 | NULL, | ||
| 156 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); | ||
| 157 | |||
| 158 | /** | ||
| 159 | * ShumateSymbolEvent:source-layer: | ||
| 160 | * | ||
| 161 | * The ID of the source layer of the symbol that this event pertains to. | ||
| 162 | */ | ||
| 163 | 2 | properties[PROP_SOURCE_LAYER] = | |
| 164 | 1 | g_param_spec_string ("source-layer", NULL, NULL, | |
| 165 | NULL, | ||
| 166 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); | ||
| 167 | |||
| 168 | /** | ||
| 169 | * ShumateSymbolEvent:feature-id: | ||
| 170 | * | ||
| 171 | * The ID of the feature that this event pertains to, as it was given in the | ||
| 172 | * data source. | ||
| 173 | * | ||
| 174 | * Since: 1.1 | ||
| 175 | */ | ||
| 176 | 2 | properties[PROP_FEATURE_ID] = | |
| 177 | 1 | g_param_spec_string ("feature-id", NULL, NULL, | |
| 178 | NULL, | ||
| 179 | G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); | ||
| 180 | |||
| 181 | /** | ||
| 182 | * ShumateSymbolEvent:n-press: | ||
| 183 | * | ||
| 184 | * The number of clicks/presses triggering the symbol event. | ||
| 185 | * | ||
| 186 | * Since: 1.5 | ||
| 187 | */ | ||
| 188 | 2 | properties[PROP_N_PRESS] = | |
| 189 | 1 | g_param_spec_uint ("n-press", NULL, NULL, | |
| 190 | 1, | ||
| 191 | INT_MAX, | ||
| 192 | 1, | ||
| 193 | G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); | ||
| 194 | |||
| 195 | 1 | g_object_class_install_properties (object_class, N_PROPS, properties); | |
| 196 | |||
| 197 | 1 | g_object_class_override_property (object_class, | |
| 198 | PROP_LONGITUDE, | ||
| 199 | "longitude"); | ||
| 200 | |||
| 201 | 1 | g_object_class_override_property (object_class, | |
| 202 | PROP_LATITUDE, | ||
| 203 | "latitude"); | ||
| 204 | 1 | } | |
| 205 | |||
| 206 | static void | ||
| 207 | ✗ | shumate_symbol_event_init (ShumateSymbolEvent *self) | |
| 208 | { | ||
| 209 | ✗ | self->tags = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); | |
| 210 | ✗ | } | |
| 211 | |||
| 212 | static double | ||
| 213 | ✗ | shumate_symbol_event_get_latitude (ShumateLocation *location) | |
| 214 | { | ||
| 215 | ✗ | ShumateSymbolEvent *self = (ShumateSymbolEvent *) location; | |
| 216 | ✗ | return self->lat; | |
| 217 | } | ||
| 218 | |||
| 219 | static double | ||
| 220 | ✗ | shumate_symbol_event_get_longitude (ShumateLocation *location) | |
| 221 | { | ||
| 222 | ✗ | ShumateSymbolEvent *self = (ShumateSymbolEvent *) location; | |
| 223 | ✗ | return self->lon; | |
| 224 | } | ||
| 225 | |||
| 226 | static void | ||
| 227 | ✗ | shumate_symbol_event_set_location (ShumateLocation *location, | |
| 228 | double lat, | ||
| 229 | double lon) | ||
| 230 | { | ||
| 231 | ✗ | g_warning ("Cannot change the location of a ShumateSymbolEvent"); | |
| 232 | ✗ | } | |
| 233 | |||
| 234 | static void | ||
| 235 | 1 | location_interface_init (ShumateLocationInterface *iface) | |
| 236 | { | ||
| 237 | 1 | iface->get_latitude = shumate_symbol_event_get_latitude; | |
| 238 | 1 | iface->get_longitude = shumate_symbol_event_get_longitude; | |
| 239 | 1 | iface->set_location = shumate_symbol_event_set_location; | |
| 240 | 1 | } | |
| 241 | |||
| 242 | /** | ||
| 243 | * shumate_symbol_event_get_layer: | ||
| 244 | * @self: a [class@SymbolEvent] | ||
| 245 | * | ||
| 246 | * Gets the name of the layer the clicked symbol is in, as named in the vector | ||
| 247 | * stylesheet. | ||
| 248 | * | ||
| 249 | * Note that this is distinct from the name of the layer in the vector tile | ||
| 250 | * schema. Some styles have multiple symbol layers derived from the same | ||
| 251 | * data source layer. | ||
| 252 | * | ||
| 253 | * Returns: (transfer none): the layer name | ||
| 254 | * | ||
| 255 | * Since: 1.1 | ||
| 256 | */ | ||
| 257 | const char * | ||
| 258 | ✗ | shumate_symbol_event_get_layer (ShumateSymbolEvent *self) | |
| 259 | { | ||
| 260 | ✗ | g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL); | |
| 261 | ✗ | return self->layer; | |
| 262 | } | ||
| 263 | |||
| 264 | /** | ||
| 265 | * shumate_symbol_event_get_source_layer: | ||
| 266 | * @self: a [class@SymbolEvent] | ||
| 267 | * | ||
| 268 | * Gets the name of the source layer the clicked feature is in, | ||
| 269 | * as named in the vector tile schema. | ||
| 270 | * | ||
| 271 | * Returns: (transfer none): the layer name | ||
| 272 | * | ||
| 273 | * Since: 1.1 | ||
| 274 | */ | ||
| 275 | const char * | ||
| 276 | ✗ | shumate_symbol_event_get_source_layer (ShumateSymbolEvent *self) | |
| 277 | { | ||
| 278 | ✗ | g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL); | |
| 279 | ✗ | return self->source_layer; | |
| 280 | } | ||
| 281 | |||
| 282 | /** | ||
| 283 | * shumate_symbol_event_get_feature_id: | ||
| 284 | * @self: a [class@SymbolEvent] | ||
| 285 | * | ||
| 286 | * Gets the feature ID as specified in the data source. The meaning of the | ||
| 287 | * ID, if any, is up to the source. | ||
| 288 | * | ||
| 289 | * Feature IDs in Mapbox Vector Tile format are integers, but they are | ||
| 290 | * formatted as a string here for futureproofing. | ||
| 291 | * | ||
| 292 | * Returns: (transfer none): the feature ID | ||
| 293 | * | ||
| 294 | * Since: 1.1 | ||
| 295 | */ | ||
| 296 | const char * | ||
| 297 | ✗ | shumate_symbol_event_get_feature_id (ShumateSymbolEvent *self) | |
| 298 | { | ||
| 299 | ✗ | g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL); | |
| 300 | ✗ | return self->feature_id; | |
| 301 | } | ||
| 302 | |||
| 303 | /** | ||
| 304 | * shumate_symbol_event_get_keys: | ||
| 305 | * @self: a [class@SymbolEvent] | ||
| 306 | * | ||
| 307 | * Gets a list of the keys of the source feature's tags. | ||
| 308 | * | ||
| 309 | * Returns: (transfer container): a list of the tag keys | ||
| 310 | * | ||
| 311 | * Since: 1.1 | ||
| 312 | */ | ||
| 313 | const GStrv | ||
| 314 | ✗ | shumate_symbol_event_get_keys (ShumateSymbolEvent *self) | |
| 315 | { | ||
| 316 | ✗ | g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL); | |
| 317 | ✗ | return (GStrv)g_hash_table_get_keys_as_array (self->tags, NULL); | |
| 318 | } | ||
| 319 | |||
| 320 | /** | ||
| 321 | * shumate_symbol_event_get_tag: | ||
| 322 | * @self: a [class@SymbolEvent] | ||
| 323 | * @tag_name: the tag to get | ||
| 324 | * | ||
| 325 | * Gets a tag from the source feature. | ||
| 326 | * | ||
| 327 | * The available tags depend on the vector tile schema and the source layer. | ||
| 328 | * Check the documentation for the tiles you're using to see what information | ||
| 329 | * is available. | ||
| 330 | * | ||
| 331 | * Returns: (transfer none): the tag value, formatted as a string | ||
| 332 | * | ||
| 333 | * Since: 1.1 | ||
| 334 | */ | ||
| 335 | const char * | ||
| 336 | ✗ | shumate_symbol_event_get_tag (ShumateSymbolEvent *self, | |
| 337 | const char *tag_name) | ||
| 338 | { | ||
| 339 | ✗ | g_return_val_if_fail (SHUMATE_IS_SYMBOL_EVENT (self), NULL); | |
| 340 | ✗ | return g_hash_table_lookup (self->tags, tag_name); | |
| 341 | } | ||
| 342 | |||
| 343 | ShumateSymbolEvent * | ||
| 344 | ✗ | shumate_symbol_event_new (const char *layer, | |
| 345 | const char *source_layer, | ||
| 346 | const char *feature_id, | ||
| 347 | GHashTable *tags) | ||
| 348 | { | ||
| 349 | ✗ | ShumateSymbolEvent *self = g_object_new (SHUMATE_TYPE_SYMBOL_EVENT, NULL); | |
| 350 | |||
| 351 | ✗ | self->layer = g_strdup (layer); | |
| 352 | ✗ | self->source_layer = g_strdup (source_layer); | |
| 353 | ✗ | self->feature_id = g_strdup (feature_id); | |
| 354 | ✗ | self->tags = g_hash_table_ref (tags); | |
| 355 | ✗ | self->n_press = 1; | |
| 356 | |||
| 357 | ✗ | return self; | |
| 358 | } | ||
| 359 | |||
| 360 | ShumateSymbolEvent * | ||
| 361 | ✗ | shumate_symbol_event_new_with_n_press (const char *layer, | |
| 362 | const char *source_layer, | ||
| 363 | const char *feature_id, | ||
| 364 | GHashTable *tags, | ||
| 365 | gint n_press) | ||
| 366 | { | ||
| 367 | ✗ | ShumateSymbolEvent *self = g_object_new (SHUMATE_TYPE_SYMBOL_EVENT, NULL); | |
| 368 | |||
| 369 | ✗ | self->layer = g_strdup (layer); | |
| 370 | ✗ | self->source_layer = g_strdup (source_layer); | |
| 371 | ✗ | self->feature_id = g_strdup (feature_id); | |
| 372 | ✗ | self->tags = g_hash_table_ref (tags); | |
| 373 | ✗ | self->n_press = n_press; | |
| 374 | |||
| 375 | ✗ | return self; | |
| 376 | } | ||
| 377 | |||
| 378 | void | ||
| 379 | ✗ | shumate_symbol_event_set_lat_lon (ShumateSymbolEvent *self, | |
| 380 | double lat, | ||
| 381 | double lon) | ||
| 382 | { | ||
| 383 | ✗ | self->lat = lat; | |
| 384 | ✗ | self->lon = lon; | |
| 385 | ✗ | } | |
| 386 | |||
| 387 | /** | ||
| 388 | * shumate_symbol_event_get_n_press: | ||
| 389 | * @self: a [class@SymbolEvent] | ||
| 390 | * | ||
| 391 | * Gets the number of clicks/presses that initiated the event. | ||
| 392 | * | ||
| 393 | * Returns: the number of presses | ||
| 394 | * | ||
| 395 | * Since: 1.5 | ||
| 396 | */ | ||
| 397 | gint | ||
| 398 | ✗ | shumate_symbol_event_get_n_press (ShumateSymbolEvent *self) | |
| 399 | { | ||
| 400 | ✗ | return self->n_press; | |
| 401 | } | ||
| 402 | |||
| 403 | /** | ||
| 404 | * shumate_symbol_event_set_n_press: | ||
| 405 | * @self: a [class@SymbolEvent] | ||
| 406 | * @n_press: the number of presses of the event | ||
| 407 | * | ||
| 408 | * Sets the number of clicks/presses that initiated the event. | ||
| 409 | * | ||
| 410 | * | ||
| 411 | * Since: 1.5 | ||
| 412 | */ | ||
| 413 | void | ||
| 414 | ✗ | shumate_symbol_event_set_n_press (ShumateSymbolEvent *self, gint n_press) | |
| 415 | { | ||
| 416 | ✗ | self->n_press = n_press; | |
| 417 | ✗ | } | |
| 418 |