LCOV - code coverage report
Current view: top level - shumate - shumate-marker-layer.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 150 260 57.7 %
Date: 2024-05-11 21:41:31 Functions: 22 32 68.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 44 130 33.8 %

           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                 :            :  * ShumateMarkerLayer:
      23                 :            :  *
      24                 :            :  * Displays markers on the map. It is responsible for positioning markers
      25                 :            :  * correctly, marker selections and group marker operations.
      26                 :            :  */
      27                 :            : 
      28                 :            : #include "shumate-marker-layer.h"
      29                 :            : #include "shumate-marker-private.h"
      30                 :            : #include "shumate-inspector-settings-private.h"
      31                 :            : 
      32                 :            : #include "shumate-enum-types.h"
      33                 :            : 
      34                 :            : #include <cairo/cairo-gobject.h>
      35                 :            : #include <glib.h>
      36                 :            : 
      37                 :            : enum
      38                 :            : {
      39                 :            :   PROP_SELECTION_MODE = 1,
      40                 :            :   N_PROPERTIES
      41                 :            : };
      42                 :            : 
      43                 :            : static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
      44                 :            : 
      45                 :            : enum
      46                 :            : {
      47                 :            :   MARKER_SELECTED,
      48                 :            :   MARKER_UNSELECTED,
      49                 :            :   LAST_SIGNAL
      50                 :            : };
      51                 :            : 
      52                 :            : static guint signals[LAST_SIGNAL];
      53                 :            : 
      54                 :            : 
      55                 :            : struct _ShumateMarkerLayer
      56                 :            : {
      57                 :            :   ShumateLayer parent_instance;
      58                 :            : 
      59                 :            :   GtkSelectionMode mode;
      60                 :            :   GList *selected;
      61                 :            : 
      62                 :            :   int n_children;
      63                 :            : };
      64                 :            : 
      65   [ +  +  +  - ]:        493 : G_DEFINE_TYPE (ShumateMarkerLayer, shumate_marker_layer, SHUMATE_TYPE_LAYER);
      66                 :            : 
      67                 :            : static void
      68                 :          0 : on_click_gesture_released (ShumateMarkerLayer *self,
      69                 :            :                            int                 n_press,
      70                 :            :                            double              x,
      71                 :            :                            double              y,
      72                 :            :                            GtkGestureClick    *gesture)
      73                 :            : {
      74                 :          0 :   GtkWidget *self_widget = GTK_WIDGET (self);
      75                 :          0 :   GtkWidget *child;
      76                 :          0 :   ShumateMarker *marker;
      77                 :            : 
      78                 :          0 :   child = gtk_widget_pick (self_widget, x, y, GTK_PICK_DEFAULT);
      79         [ #  # ]:          0 :   if (!child)
      80                 :            :     return;
      81                 :            : 
      82   [ #  #  #  # ]:          0 :   while (child != NULL && gtk_widget_get_parent (child) != self_widget)
      83                 :          0 :     child = gtk_widget_get_parent (child);
      84                 :            : 
      85                 :          0 :   marker = SHUMATE_MARKER (child);
      86         [ #  # ]:          0 :   if (!marker)
      87                 :            :     return;
      88                 :            : 
      89         [ #  # ]:          0 :   if (shumate_marker_is_selected (marker)) {
      90         [ #  # ]:          0 :     if (self->mode != GTK_SELECTION_BROWSE) {
      91                 :          0 :       shumate_marker_layer_unselect_marker (self, marker);
      92                 :            :     }
      93                 :            :   }
      94                 :            :   else {
      95                 :          0 :     shumate_marker_layer_select_marker (self, marker);
      96                 :            :   }
      97                 :            : }
      98                 :            : 
      99                 :            : static void
     100                 :        208 : update_marker_visibility (ShumateMarkerLayer *layer,
     101                 :            :                           ShumateMarker      *marker)
     102                 :            : {
     103                 :        208 :   ShumateViewport *viewport;
     104                 :        208 :   ShumateMapSource *map_source;
     105                 :        208 :   gboolean within_viewport;
     106                 :        208 :   double lon, lat;
     107                 :        208 :   double x, y;
     108                 :        208 :   int marker_width, marker_height;
     109                 :        208 :   int width, height;
     110                 :            : 
     111         [ +  - ]:        208 :   g_assert (SHUMATE_IS_MARKER_LAYER (layer));
     112                 :            : 
     113                 :        208 :   viewport = shumate_layer_get_viewport (SHUMATE_LAYER (layer));
     114                 :        208 :   map_source = shumate_viewport_get_reference_map_source (viewport);
     115         [ +  - ]:        208 :   if (!map_source)
     116                 :        208 :     return;
     117                 :            : 
     118                 :          0 :   lon = shumate_location_get_longitude (SHUMATE_LOCATION (marker));
     119                 :          0 :   lat = shumate_location_get_latitude (SHUMATE_LOCATION (marker));
     120                 :            : 
     121                 :          0 :   width = gtk_widget_get_width (GTK_WIDGET (layer));
     122                 :          0 :   height = gtk_widget_get_height (GTK_WIDGET (layer));
     123                 :            : 
     124                 :          0 :   gtk_widget_measure (GTK_WIDGET (marker), GTK_ORIENTATION_HORIZONTAL, -1, 0, &marker_width, NULL, NULL);
     125                 :          0 :   gtk_widget_measure (GTK_WIDGET (marker), GTK_ORIENTATION_VERTICAL, -1, 0, &marker_height, NULL, NULL);
     126                 :            : 
     127                 :          0 :   shumate_viewport_location_to_widget_coords (viewport, GTK_WIDGET (layer), lat, lon, &x, &y);
     128                 :          0 :   x = floorf (x - marker_width/2.f);
     129                 :          0 :   y = floorf (y - marker_height/2.f);
     130                 :            : 
     131         [ #  # ]:          0 :   within_viewport = x > -marker_width && x <= width &&
     132   [ #  #  #  #  :          0 :                     y > -marker_height && y <= height &&
                   #  # ]
     133   [ #  #  #  # ]:          0 :                     marker_width < width && marker_height < height;
     134                 :            : 
     135                 :          0 :   gtk_widget_set_child_visible (GTK_WIDGET (marker), within_viewport);
     136                 :            : 
     137         [ #  # ]:          0 :   if (within_viewport)
     138                 :            :     {
     139                 :          0 :       graphene_rect_t bounds;
     140                 :            : 
     141         [ #  # ]:          0 :       if (gtk_widget_compute_bounds (GTK_WIDGET (marker), GTK_WIDGET (layer), &bounds))
     142   [ #  #  #  # ]:          0 :         if (bounds.origin.x != (int)x || bounds.origin.y != (int)y)
     143                 :          0 :           gtk_widget_queue_allocate (GTK_WIDGET (layer));
     144                 :            :     }
     145                 :            : }
     146                 :            : 
     147                 :            : static void
     148                 :          0 : shumate_marker_layer_reposition_markers (ShumateMarkerLayer *self)
     149                 :            : {
     150                 :          0 :   GtkWidget *child;
     151                 :            : 
     152                 :          0 :   for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
     153         [ #  # ]:          0 :        child != NULL;
     154                 :          0 :        child = gtk_widget_get_next_sibling (child))
     155                 :            :     {
     156                 :          0 :       update_marker_visibility (self, SHUMATE_MARKER (child));
     157                 :            :     }
     158                 :          0 : }
     159                 :            : 
     160                 :            : static void
     161                 :          0 : on_viewport_changed (ShumateMarkerLayer *self,
     162                 :            :                      GParamSpec         *pspec,
     163                 :            :                      ShumateViewport    *view)
     164                 :            : {
     165         [ #  # ]:          0 :   g_assert (SHUMATE_IS_MARKER_LAYER (self));
     166                 :            : 
     167                 :          0 :   shumate_marker_layer_reposition_markers (self);
     168                 :          0 : }
     169                 :            : 
     170                 :            : static void
     171                 :          0 : shumate_marker_layer_size_allocate (GtkWidget *widget,
     172                 :            :                                     int        width,
     173                 :            :                                     int        height,
     174                 :            :                                     int        baseline)
     175                 :            : {
     176                 :          0 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (widget);
     177                 :          0 :   ShumateViewport *viewport;
     178                 :          0 :   GtkAllocation allocation;
     179                 :          0 :   GtkWidget *child;
     180                 :            : 
     181                 :          0 :   viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
     182                 :            : 
     183                 :          0 :   for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
     184         [ #  # ]:          0 :        child != NULL;
     185                 :          0 :        child = gtk_widget_get_next_sibling (child))
     186                 :            :     {
     187                 :          0 :       gboolean within_viewport;
     188                 :          0 :       double lon, lat;
     189                 :          0 :       double x, y;
     190                 :          0 :       int marker_width, marker_height;
     191                 :            : 
     192         [ #  # ]:          0 :       if (!gtk_widget_should_layout (child))
     193                 :          0 :         continue;
     194                 :            : 
     195                 :          0 :       lon = shumate_location_get_longitude (SHUMATE_LOCATION (child));
     196                 :          0 :       lat = shumate_location_get_latitude (SHUMATE_LOCATION (child));
     197                 :            : 
     198                 :          0 :       gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, 0, &marker_width, NULL, NULL);
     199                 :          0 :       gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, 0, &marker_height, NULL, NULL);
     200                 :            : 
     201                 :          0 :       shumate_viewport_location_to_widget_coords (viewport, widget, lat, lon, &x, &y);
     202                 :          0 :       x = floorf (x - marker_width/2.f);
     203                 :          0 :       y = floorf (y - marker_height/2.f);
     204                 :            : 
     205                 :          0 :       allocation.x = x;
     206                 :          0 :       allocation.y = y;
     207                 :          0 :       allocation.width = marker_width;
     208                 :          0 :       allocation.height = marker_height;
     209                 :            : 
     210         [ #  # ]:          0 :       within_viewport = x > -allocation.width && x <= width &&
     211   [ #  #  #  #  :          0 :                         y > -allocation.height && y <= height &&
                   #  # ]
     212   [ #  #  #  # ]:          0 :                         allocation.width < width && allocation.height < height;
     213                 :            : 
     214                 :          0 :       gtk_widget_set_child_visible (child, within_viewport);
     215                 :            : 
     216         [ #  # ]:          0 :       if (within_viewport)
     217                 :          0 :         gtk_widget_size_allocate (child, &allocation, -1);
     218                 :            :     }
     219                 :          0 : }
     220                 :            : 
     221                 :            : static void
     222                 :          0 : shumate_marker_layer_get_property (GObject    *object,
     223                 :            :                                    guint       property_id,
     224                 :            :                                    GValue     *value,
     225                 :            :                                    GParamSpec *pspec)
     226                 :            : {
     227                 :          0 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (object);
     228                 :            : 
     229         [ #  # ]:          0 :   switch (property_id)
     230                 :            :     {
     231                 :          0 :     case PROP_SELECTION_MODE:
     232                 :          0 :       g_value_set_enum (value, self->mode);
     233                 :          0 :       break;
     234                 :            : 
     235                 :          0 :     default:
     236                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     237                 :            :     }
     238                 :          0 : }
     239                 :            : 
     240                 :            : 
     241                 :            : static void
     242                 :          0 : shumate_marker_layer_set_property (GObject      *object,
     243                 :            :                                    guint         property_id,
     244                 :            :                                    const GValue *value,
     245                 :            :                                    GParamSpec   *pspec)
     246                 :            : {
     247                 :          0 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (object);
     248                 :            : 
     249         [ #  # ]:          0 :   switch (property_id)
     250                 :            :     {
     251                 :          0 :     case PROP_SELECTION_MODE:
     252                 :          0 :       shumate_marker_layer_set_selection_mode (self, g_value_get_enum (value));
     253                 :          0 :       break;
     254                 :            : 
     255                 :          0 :     default:
     256                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     257                 :            :     }
     258                 :          0 : }
     259                 :            : 
     260                 :            : 
     261                 :            : static void
     262                 :          2 : shumate_marker_layer_dispose (GObject *object)
     263                 :            : {
     264                 :          2 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (object);
     265                 :          2 :   ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
     266                 :          2 :   GtkWidget *child;
     267                 :            : 
     268                 :          2 :   g_signal_handlers_disconnect_by_data (viewport, self);
     269                 :            : 
     270         [ +  + ]:          6 :   while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
     271                 :          4 :     gtk_widget_unparent (child);
     272                 :            : 
     273                 :          2 :   G_OBJECT_CLASS (shumate_marker_layer_parent_class)->dispose (object);
     274                 :          2 : }
     275                 :            : 
     276                 :            : 
     277                 :            : static void
     278                 :          2 : shumate_marker_layer_finalize (GObject *object)
     279                 :            : {
     280                 :          2 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (object);
     281                 :            : 
     282                 :          2 :   g_list_free (self->selected);
     283                 :            : 
     284                 :          2 :   G_OBJECT_CLASS (shumate_marker_layer_parent_class)->finalize (object);
     285                 :          2 : }
     286                 :            : 
     287                 :            : static void
     288                 :         10 : shumate_marker_layer_constructed (GObject *object)
     289                 :            : {
     290                 :         10 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (object);
     291                 :         10 :   ShumateViewport *viewport;
     292                 :            : 
     293                 :         10 :   G_OBJECT_CLASS (shumate_marker_layer_parent_class)->constructed (object);
     294                 :            : 
     295                 :         10 :   viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
     296                 :         10 :   g_signal_connect_swapped (viewport, "notify", G_CALLBACK (on_viewport_changed), self);
     297                 :         10 : }
     298                 :            : 
     299                 :            : static char *
     300                 :          0 : shumate_marker_layer_get_debug_text (ShumateLayer *layer)
     301                 :            : {
     302                 :          0 :   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (layer);
     303                 :          0 :   return g_strdup_printf ("markers: %d, %d selected\n", self->n_children, g_list_length (self->selected));
     304                 :            : }
     305                 :            : 
     306                 :            : static void
     307                 :          3 : shumate_marker_layer_class_init (ShumateMarkerLayerClass *klass)
     308                 :            : {
     309                 :          3 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     310                 :          3 :   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
     311                 :          3 :   ShumateLayerClass *layer_class = SHUMATE_LAYER_CLASS (klass);
     312                 :            : 
     313                 :          3 :   object_class->dispose = shumate_marker_layer_dispose;
     314                 :          3 :   object_class->finalize = shumate_marker_layer_finalize;
     315                 :          3 :   object_class->get_property = shumate_marker_layer_get_property;
     316                 :          3 :   object_class->set_property = shumate_marker_layer_set_property;
     317                 :          3 :   object_class->constructed = shumate_marker_layer_constructed;
     318                 :            : 
     319                 :          3 :   widget_class->size_allocate = shumate_marker_layer_size_allocate;
     320                 :            : 
     321                 :          3 :   layer_class->get_debug_text = shumate_marker_layer_get_debug_text;
     322                 :            : 
     323                 :            :   /**
     324                 :            :    * ShumateMarkerLayer:selection-mode:
     325                 :            :    *
     326                 :            :    * Determines the type of selection that will be performed.
     327                 :            :    */
     328                 :          6 :   obj_properties[PROP_SELECTION_MODE] =
     329                 :          3 :     g_param_spec_enum ("selection-mode",
     330                 :            :                        "Selection Mode",
     331                 :            :                        "Determines the type of selection that will be performed.",
     332                 :            :                        GTK_TYPE_SELECTION_MODE,
     333                 :            :                        GTK_SELECTION_NONE,
     334                 :            :                        G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
     335                 :            : 
     336                 :          3 :   g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
     337                 :            : 
     338                 :            :   /**
     339                 :            :    * ShumateMarkerLayer::marker-selected:
     340                 :            :    * @self: The marker layer emitting the signal
     341                 :            :    * @marker: The marker that was selected
     342                 :            :    *
     343                 :            :    * Emitted when a marker in the layer is selected.
     344                 :            :    */
     345                 :          6 :   signals[MARKER_SELECTED] =
     346                 :          3 :     g_signal_new ("marker-selected",
     347                 :            :                   G_OBJECT_CLASS_TYPE (object_class),
     348                 :            :                   G_SIGNAL_RUN_LAST,
     349                 :            :                   0, NULL, NULL, NULL,
     350                 :            :                   G_TYPE_NONE,
     351                 :            :                   1, SHUMATE_TYPE_MARKER);
     352                 :            : 
     353                 :            :   /**
     354                 :            :    * ShumateMarkerLayer::marker-unselected:
     355                 :            :    * @self: The marker layer emitting the signal
     356                 :            :    * @marker: The marker that was unselected
     357                 :            :    *
     358                 :            :    * Emitted when a marker in the layer is unselected.
     359                 :            :    */
     360                 :          6 :   signals[MARKER_UNSELECTED] =
     361                 :          3 :     g_signal_new ("marker-unselected",
     362                 :            :                   G_OBJECT_CLASS_TYPE (object_class),
     363                 :            :                   G_SIGNAL_RUN_LAST,
     364                 :            :                   0, NULL, NULL, NULL,
     365                 :            :                   G_TYPE_NONE,
     366                 :            :                   1, SHUMATE_TYPE_MARKER);
     367                 :          3 : }
     368                 :            : 
     369                 :            : 
     370                 :            : static void
     371                 :         10 : shumate_marker_layer_init (ShumateMarkerLayer *self)
     372                 :            : {
     373                 :         10 :   GtkGesture *click_gesture;
     374                 :            : 
     375                 :         10 :   self->mode = GTK_SELECTION_NONE;
     376                 :            : 
     377                 :         10 :   click_gesture = gtk_gesture_click_new ();
     378                 :         10 :   gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (click_gesture));
     379                 :         10 :   g_signal_connect_swapped (click_gesture, "released", G_CALLBACK (on_click_gesture_released), self);
     380                 :         10 : }
     381                 :            : 
     382                 :            : /**
     383                 :            :  * shumate_marker_layer_new:
     384                 :            :  * @viewport: the @ShumateViewport
     385                 :            :  *
     386                 :            :  * Creates a new instance of [class@MarkerLayer].
     387                 :            :  *
     388                 :            :  * Returns: a new [class@MarkerLayer] ready to be used as a container for the markers.
     389                 :            :  */
     390                 :            : ShumateMarkerLayer *
     391                 :         10 : shumate_marker_layer_new (ShumateViewport *viewport)
     392                 :            : {
     393                 :         10 :   return g_object_new (SHUMATE_TYPE_MARKER_LAYER,
     394                 :            :                        "viewport", viewport,
     395                 :            :                        NULL);
     396                 :            : }
     397                 :            : 
     398                 :            : 
     399                 :            : /**
     400                 :            :  * shumate_marker_layer_new_full:
     401                 :            :  * @viewport: the @ShumateViewport
     402                 :            :  * @mode: Selection mode
     403                 :            :  *
     404                 :            :  * Creates a new instance of [class@MarkerLayer] with the specified selection mode.
     405                 :            :  *
     406                 :            :  * Returns: a new [class@MarkerLayer] ready to be used as a container for the markers.
     407                 :            :  */
     408                 :            : ShumateMarkerLayer *
     409                 :          0 : shumate_marker_layer_new_full (ShumateViewport *viewport,
     410                 :            :                                GtkSelectionMode mode)
     411                 :            : {
     412                 :          0 :   return g_object_new (SHUMATE_TYPE_MARKER_LAYER,
     413                 :            :                        "selection-mode", mode,
     414                 :            :                        "viewport", viewport,
     415                 :            :                        NULL);
     416                 :            : }
     417                 :            : 
     418                 :            : 
     419                 :            : static void
     420                 :          0 : marker_position_notify (ShumateMarker *marker,
     421                 :            :     G_GNUC_UNUSED GParamSpec *pspec,
     422                 :            :     ShumateMarkerLayer *layer)
     423                 :            : {
     424                 :          0 :   update_marker_visibility (layer, marker);
     425                 :          0 : }
     426                 :            : 
     427                 :            : 
     428                 :            : static void
     429                 :          0 : marker_move_by_cb (ShumateMarker *marker,
     430                 :            :     double dx,
     431                 :            :     double dy,
     432                 :            :     GdkEvent *event,
     433                 :            :     ShumateMarkerLayer *layer)
     434                 :            : {
     435                 :            :   /*ShumateMarkerLayerPrivate *priv = shumate_marker_layer_get_instance_private (layer);
     436                 :            :   ShumateView *view = self->view;
     437                 :            :   double x, y, lat, lon;
     438                 :            : 
     439                 :            :   x = shumate_view_longitude_to_x (view, shumate_location_get_longitude (SHUMATE_LOCATION (marker)));
     440                 :            :   y = shumate_view_latitude_to_y (view, shumate_location_get_latitude (SHUMATE_LOCATION (marker)));
     441                 :            : 
     442                 :            :   x += dx;
     443                 :            :   y += dy;
     444                 :            : 
     445                 :            :   lon = shumate_view_x_to_longitude (view, x);
     446                 :            :   lat = shumate_view_y_to_latitude (view, y);
     447                 :            : 
     448                 :            :   shumate_location_set_location (SHUMATE_LOCATION (marker), lat, lon);*/
     449                 :          0 : }
     450                 :            : 
     451                 :            : 
     452                 :            : /**
     453                 :            :  * shumate_marker_layer_add_marker:
     454                 :            :  * @self: a [class@MarkerLayer]
     455                 :            :  * @marker: a [class@Marker]
     456                 :            :  *
     457                 :            :  * Adds the marker to the layer.
     458                 :            :  */
     459                 :            : void
     460                 :        208 : shumate_marker_layer_add_marker (ShumateMarkerLayer *self,
     461                 :            :     ShumateMarker *marker)
     462                 :            : {
     463         [ +  - ]:        208 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     464         [ -  + ]:        208 :   g_return_if_fail (SHUMATE_IS_MARKER (marker));
     465                 :            : 
     466                 :        208 :   g_signal_connect_object (G_OBJECT (marker), "notify::latitude",
     467                 :            :       G_CALLBACK (marker_position_notify), self, 0);
     468                 :        208 :   g_signal_connect_object (G_OBJECT (marker), "notify::longitude",
     469                 :            :       G_CALLBACK (marker_position_notify), self, 0);
     470                 :            : 
     471                 :            :   /*g_signal_connect (G_OBJECT (marker), "drag-motion",
     472                 :            :       G_CALLBACK (marker_move_by_cb), layer);*/
     473                 :            : 
     474                 :        208 :   shumate_marker_set_selected (marker, FALSE);
     475                 :            : 
     476                 :        208 :   gtk_widget_insert_before (GTK_WIDGET(marker), GTK_WIDGET (self), NULL);
     477                 :        208 :   update_marker_visibility (self, marker);
     478                 :        208 :   self->n_children++;
     479                 :            : }
     480                 :            : 
     481                 :            : 
     482                 :            : /**
     483                 :            :  * shumate_marker_layer_remove_all:
     484                 :            :  * @self: a [class@MarkerLayer]
     485                 :            :  *
     486                 :            :  * Removes all markers from the layer.
     487                 :            :  */
     488                 :            : void
     489                 :          2 : shumate_marker_layer_remove_all (ShumateMarkerLayer *self)
     490                 :            : {
     491                 :          2 :   GtkWidget *child;
     492                 :            : 
     493         [ +  - ]:          2 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     494                 :            : 
     495                 :          2 :   child = gtk_widget_get_first_child (GTK_WIDGET (self));
     496         [ +  + ]:        202 :   while (child)
     497                 :            :     {
     498                 :        200 :       GtkWidget *next = gtk_widget_get_next_sibling (child);
     499                 :            : 
     500                 :        200 :       g_signal_handlers_disconnect_by_data (child, self);
     501                 :        200 :       gtk_widget_unparent (child);
     502                 :            : 
     503                 :        200 :       child = next;
     504                 :            :     }
     505                 :            : 
     506                 :          2 :   self->n_children = 0;
     507                 :            : }
     508                 :            : 
     509                 :            : 
     510                 :            : /**
     511                 :            :  * shumate_marker_layer_get_markers:
     512                 :            :  * @self: a [class@MarkerLayer]
     513                 :            :  *
     514                 :            :  * Gets a copy of the list of all markers inserted into the layer. You should
     515                 :            :  * free the list but not its contents.
     516                 :            :  *
     517                 :            :  * Returns: (transfer container) (element-type ShumateMarker): the list
     518                 :            :  */
     519                 :            : GList *
     520                 :          2 : shumate_marker_layer_get_markers (ShumateMarkerLayer *self)
     521                 :            : {
     522                 :          2 :   GList *list = NULL;
     523                 :          2 :   GtkWidget *child;
     524                 :            : 
     525         [ +  - ]:          2 :   g_return_val_if_fail (SHUMATE_IS_MARKER_LAYER (self), NULL);
     526                 :            : 
     527                 :          2 :   for (child = gtk_widget_get_last_child (GTK_WIDGET (self));
     528         [ +  + ]:          6 :        child != NULL;
     529                 :          4 :        child = gtk_widget_get_prev_sibling (child))
     530                 :            :     {
     531                 :          4 :       ShumateMarker *marker = SHUMATE_MARKER (child);
     532                 :          4 :       list = g_list_prepend (list, marker);
     533                 :            :     }
     534                 :            : 
     535                 :            :   return list;
     536                 :            : }
     537                 :            : 
     538                 :            : 
     539                 :            : /**
     540                 :            :  * shumate_marker_layer_get_selected:
     541                 :            :  * @self: a [class@MarkerLayer]
     542                 :            :  *
     543                 :            :  * Gets a list of selected markers in the layer.
     544                 :            :  *
     545                 :            :  * Returns: (transfer container) (element-type ShumateMarker): the list
     546                 :            :  */
     547                 :            : GList *
     548                 :          6 : shumate_marker_layer_get_selected (ShumateMarkerLayer *self)
     549                 :            : {
     550         [ +  - ]:          6 :   g_return_val_if_fail (SHUMATE_IS_MARKER_LAYER (self), FALSE);
     551                 :          6 :   return g_list_copy (self->selected);
     552                 :            : }
     553                 :            : 
     554                 :            : static void
     555                 :         20 : update_debug_text (ShumateMarkerLayer *self)
     556                 :            : {
     557         [ -  + ]:         20 :   if (shumate_inspector_settings_get_show_debug_overlay (shumate_inspector_settings_get_default ()))
     558                 :          0 :     gtk_widget_queue_draw (GTK_WIDGET (self));
     559                 :         20 : }
     560                 :            : 
     561                 :            : /**
     562                 :            :  * shumate_marker_layer_select_marker:
     563                 :            :  * @self: a [class@MarkerLayer]
     564                 :            :  * @marker: a [class@Marker] that is a child of @self
     565                 :            :  *
     566                 :            :  * Selects a marker in this layer.
     567                 :            :  *
     568                 :            :  * If [class@MarkerLayer]:selection-mode is %GTK_SELECTION_SINGLE or
     569                 :            :  * %GTK_SELECTION_BROWSE, all other markers will be unselected. If the mode is
     570                 :            :  * %GTK_SELECTION_NONE or @marker is not selectable, nothing will happen.
     571                 :            :  *
     572                 :            :  * Returns: %TRUE if the marker is now selected, otherwise %FALSE
     573                 :            :  */
     574                 :            : gboolean
     575                 :         14 : shumate_marker_layer_select_marker (ShumateMarkerLayer *self, ShumateMarker *marker)
     576                 :            : {
     577         [ +  - ]:         14 :   g_return_val_if_fail (SHUMATE_IS_MARKER_LAYER (self), FALSE);
     578         [ -  + ]:         14 :   g_return_val_if_fail (SHUMATE_IS_MARKER (marker), FALSE);
     579         [ -  + ]:         14 :   g_return_val_if_fail (gtk_widget_get_parent (GTK_WIDGET (marker)) == GTK_WIDGET (self), FALSE);
     580                 :            : 
     581         [ +  - ]:         14 :   if (!shumate_marker_get_selectable (marker)) {
     582                 :            :     return FALSE;
     583                 :            :   }
     584                 :            : 
     585         [ -  + ]:         14 :   if (shumate_marker_is_selected (marker)) {
     586                 :            :     return TRUE;
     587                 :            :   }
     588                 :            : 
     589   [ +  +  -  + ]:         14 :   switch (self->mode) {
     590                 :            :     case GTK_SELECTION_NONE:
     591                 :            :       return FALSE;
     592                 :            : 
     593                 :          4 :     case GTK_SELECTION_BROWSE:
     594                 :            :     case GTK_SELECTION_SINGLE:
     595                 :          4 :       shumate_marker_layer_unselect_all_markers (self);
     596                 :            : 
     597                 :            :       /* fall through */
     598                 :         10 :     case GTK_SELECTION_MULTIPLE:
     599                 :         10 :       self->selected = g_list_prepend (self->selected, marker);
     600                 :         10 :       shumate_marker_set_selected (marker, TRUE);
     601                 :         10 :       update_debug_text (self);
     602                 :         10 :       g_signal_emit (self, signals[MARKER_SELECTED], 0, marker);
     603                 :         10 :       return TRUE;
     604                 :            : 
     605                 :          0 :     default:
     606                 :          0 :       g_assert_not_reached ();
     607                 :            :   }
     608                 :            : }
     609                 :            : 
     610                 :            : 
     611                 :            : /**
     612                 :            :  * shumate_marker_layer_unselect_marker:
     613                 :            :  * @self: a [class@MarkerLayer]
     614                 :            :  * @marker: a [class@Marker] that is a child of @self
     615                 :            :  *
     616                 :            :  * Unselects a marker in this layer.
     617                 :            :  *
     618                 :            :  * This works even if [class@MarkerLayer]:selection-mode is
     619                 :            :  * %GTK_SELECTION_BROWSE. Browse mode only prevents user interaction, not the
     620                 :            :  * program, from unselecting a marker.
     621                 :            :  */
     622                 :            : void
     623                 :         10 : shumate_marker_layer_unselect_marker (ShumateMarkerLayer *self,
     624                 :            :                                       ShumateMarker      *marker)
     625                 :            : {
     626         [ +  - ]:         10 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     627         [ -  + ]:         10 :   g_return_if_fail (SHUMATE_IS_MARKER (marker));
     628         [ -  + ]:         10 :   g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (marker)) == GTK_WIDGET (self));
     629                 :            : 
     630         [ +  - ]:         10 :   if (!shumate_marker_is_selected (marker)) {
     631                 :            :     return;
     632                 :            :   }
     633                 :            : 
     634                 :         10 :   self->selected = g_list_remove (self->selected, marker);
     635                 :         10 :   shumate_marker_set_selected (marker, FALSE);
     636                 :         10 :   update_debug_text (self);
     637                 :         10 :   g_signal_emit (self, signals[MARKER_UNSELECTED], 0, marker);
     638                 :            : }
     639                 :            : 
     640                 :            : 
     641                 :            : /**
     642                 :            :  * shumate_marker_layer_remove_marker:
     643                 :            :  * @self: a [class@MarkerLayer]
     644                 :            :  * @marker: a [class@Marker]
     645                 :            :  *
     646                 :            :  * Removes the marker from the layer.
     647                 :            :  */
     648                 :            : void
     649                 :          2 : shumate_marker_layer_remove_marker (ShumateMarkerLayer *self,
     650                 :            :                                     ShumateMarker      *marker)
     651                 :            : {
     652         [ +  - ]:          2 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     653         [ -  + ]:          2 :   g_return_if_fail (SHUMATE_IS_MARKER (marker));
     654         [ -  + ]:          2 :   g_return_if_fail (gtk_widget_get_parent (GTK_WIDGET (marker)) == GTK_WIDGET (self));
     655                 :            : 
     656                 :          2 :   g_signal_handlers_disconnect_by_func (G_OBJECT (marker),
     657                 :            :       G_CALLBACK (marker_position_notify), self);
     658                 :            : 
     659                 :          2 :   g_signal_handlers_disconnect_by_func (marker,
     660                 :            :       G_CALLBACK (marker_move_by_cb), self);
     661                 :            : 
     662         [ -  + ]:          2 :   if (shumate_marker_is_selected (marker)) {
     663                 :          0 :     shumate_marker_layer_unselect_marker (self, marker);
     664                 :            :   }
     665                 :            : 
     666                 :          2 :   gtk_widget_unparent (GTK_WIDGET (marker));
     667                 :          2 :   self->n_children--;
     668                 :            : }
     669                 :            : 
     670                 :            : 
     671                 :            : /**
     672                 :            :  * shumate_marker_layer_unselect_all_markers:
     673                 :            :  * @self: a [class@MarkerLayer]
     674                 :            :  *
     675                 :            :  * Unselects all markers in the layer.
     676                 :            :  */
     677                 :            : void
     678                 :         10 : shumate_marker_layer_unselect_all_markers (ShumateMarkerLayer *self)
     679                 :            : {
     680                 :          0 :   g_autoptr(GList) prev_selected = NULL;
     681                 :            : 
     682         [ +  - ]:         10 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     683                 :            : 
     684                 :         10 :   prev_selected = g_list_copy (self->selected);
     685                 :            : 
     686         [ +  + ]:         20 :   for (GList *l = prev_selected; l != NULL; l = l->next) {
     687                 :         10 :     shumate_marker_layer_unselect_marker (self, SHUMATE_MARKER (l->data));
     688                 :            :   }
     689                 :            : }
     690                 :            : 
     691                 :            : 
     692                 :            : /**
     693                 :            :  * shumate_marker_layer_select_all_markers:
     694                 :            :  * @self: a [class@MarkerLayer]
     695                 :            :  *
     696                 :            :  * Selects all selectable markers in the layer.
     697                 :            :  */
     698                 :            : void
     699                 :          2 : shumate_marker_layer_select_all_markers (ShumateMarkerLayer *self)
     700                 :            : {
     701                 :          0 :   g_autoptr(GList) children = NULL;
     702                 :            : 
     703         [ +  - ]:          2 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     704                 :            : 
     705                 :          2 :   children = shumate_marker_layer_get_markers (self);
     706                 :            : 
     707         [ +  + ]:          6 :   for (GList *l = children; l != NULL; l = l->next) {
     708                 :          4 :     shumate_marker_layer_select_marker (self, SHUMATE_MARKER (l->data));
     709                 :            :   }
     710                 :            : }
     711                 :            : 
     712                 :            : 
     713                 :            : /**
     714                 :            :  * shumate_marker_layer_set_selection_mode:
     715                 :            :  * @self: a [class@MarkerLayer]
     716                 :            :  * @mode: a [enum@Gtk.SelectionMode] value
     717                 :            :  *
     718                 :            :  * Sets the selection mode of the layer.
     719                 :            :  *
     720                 :            :  * NOTE: changing selection mode to %GTK_SELECTION_NONE, %GTK_SELECTION_SINGLE
     721                 :            :  * or %GTK_SELECTION_BROWSE will clear all previously selected markers.
     722                 :            :  */
     723                 :            : void
     724                 :          8 : shumate_marker_layer_set_selection_mode (ShumateMarkerLayer *self,
     725                 :            :                                          GtkSelectionMode    mode)
     726                 :            : {
     727         [ +  - ]:          8 :   g_return_if_fail (SHUMATE_IS_MARKER_LAYER (self));
     728                 :            : 
     729         [ +  - ]:          8 :   if (self->mode == mode)
     730                 :            :     return;
     731                 :            : 
     732                 :          8 :   self->mode = mode;
     733                 :            : 
     734         [ +  + ]:          8 :   if (mode != GTK_SELECTION_MULTIPLE)
     735                 :          4 :     shumate_marker_layer_unselect_all_markers (self);
     736                 :            : 
     737                 :          8 :   g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_SELECTION_MODE]);
     738                 :            : }
     739                 :            : 
     740                 :            : 
     741                 :            : /**
     742                 :            :  * shumate_marker_layer_get_selection_mode:
     743                 :            :  * @self: a [class@MarkerLayer]
     744                 :            :  *
     745                 :            :  * Gets the selection mode of the layer.
     746                 :            :  *
     747                 :            :  * Returns: the selection mode of the layer.
     748                 :            :  */
     749                 :            : GtkSelectionMode
     750                 :          2 : shumate_marker_layer_get_selection_mode (ShumateMarkerLayer *self)
     751                 :            : {
     752         [ +  - ]:          2 :   g_return_val_if_fail (SHUMATE_IS_MARKER_LAYER (self), GTK_SELECTION_NONE);
     753                 :            : 
     754                 :          2 :   return self->mode;
     755                 :            : }

Generated by: LCOV version 1.14