LCOV - code coverage report
Current view: top level - shumate - shumate-marker.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 64 139 46.0 %
Date: 2024-05-11 21:41:31 Functions: 13 21 61.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 16 56 28.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2008 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                 :            :  * ShumateMarker:
      23                 :            :  *
      24                 :            :  * Markers represent points of interest on a map. Markers need to be
      25                 :            :  * placed on a layer (a [class@MarkerLayer]). Layers have to be added to a
      26                 :            :  * [class@Map] for the markers to show on the map.
      27                 :            :  *
      28                 :            :  * A marker is nothing more than a regular [class@Gtk.Widget]. You can draw on
      29                 :            :  * it what ever you want. Set the marker's position on the map using
      30                 :            :  * [method@Location.set_location].
      31                 :            :  *
      32                 :            :  * This is a base class of all markers. A typical usage of a marker is for
      33                 :            :  * instance to add a [class@Gtk.Image] with a pin image and add the
      34                 :            :  * [class@Gtk.GestureClick] controller to listen to click events and show
      35                 :            :  * a [class@Gtk.Popover] with the description of the marker.
      36                 :            :  */
      37                 :            : 
      38                 :            : #include "shumate-marker.h"
      39                 :            : #include "shumate-marker-private.h"
      40                 :            : 
      41                 :            : #include "shumate.h"
      42                 :            : #include "shumate-marshal.h"
      43                 :            : #include "shumate-tile.h"
      44                 :            : 
      45                 :            : #include <glib.h>
      46                 :            : #include <glib-object.h>
      47                 :            : #include <gtk/gtk.h>
      48                 :            : 
      49                 :            : enum
      50                 :            : {
      51                 :            :   PROP_SELECTABLE = 1,
      52                 :            :   PROP_CHILD,
      53                 :            :   N_PROPERTIES,
      54                 :            : 
      55                 :            :   PROP_LONGITUDE,
      56                 :            :   PROP_LATITUDE,
      57                 :            : };
      58                 :            : 
      59                 :            : static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
      60                 :            : 
      61                 :            : typedef struct
      62                 :            : {
      63                 :            :   double lon;
      64                 :            :   double lat;
      65                 :            : 
      66                 :            :   gboolean selected;
      67                 :            : 
      68                 :            :   gboolean selectable;
      69                 :            : 
      70                 :            :   float click_x;
      71                 :            :   float click_y;
      72                 :            :   gboolean moved;
      73                 :            : 
      74                 :            :   GtkWidget *child;
      75                 :            : } ShumateMarkerPrivate;
      76                 :            : 
      77                 :            : static void location_interface_init (ShumateLocationInterface *iface);
      78                 :            : static void buildable_interface_init (GtkBuildableIface *iface);
      79                 :            : 
      80   [ +  +  +  - ]:       1246 : G_DEFINE_TYPE_WITH_CODE (ShumateMarker, shumate_marker, GTK_TYPE_WIDGET,
      81                 :            :     G_ADD_PRIVATE (ShumateMarker)
      82                 :            :     G_IMPLEMENT_INTERFACE (SHUMATE_TYPE_LOCATION, location_interface_init)
      83                 :            :     G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_interface_init));
      84                 :            : 
      85                 :            : static GtkBuildableIface *parent_buildable_iface;
      86                 :            : 
      87                 :            : static void
      88                 :          0 : shumate_marker_set_location (ShumateLocation *location,
      89                 :            :                              double           latitude,
      90                 :            :                              double           longitude)
      91                 :            : {
      92                 :          0 :   ShumateMarker *marker = (ShumateMarker *) location;
      93                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
      94                 :            : 
      95         [ #  # ]:          0 :   g_assert (SHUMATE_IS_MARKER (location));
      96                 :            : 
      97   [ #  #  #  # ]:          0 :   priv->lon = CLAMP (longitude, SHUMATE_MIN_LONGITUDE, SHUMATE_MAX_LONGITUDE);
      98   [ #  #  #  # ]:          0 :   priv->lat = CLAMP (latitude, SHUMATE_MIN_LATITUDE, SHUMATE_MAX_LATITUDE);
      99                 :            : 
     100                 :          0 :   g_object_notify (G_OBJECT (location), "latitude");
     101                 :          0 :   g_object_notify (G_OBJECT (location), "longitude");
     102                 :          0 : }
     103                 :            : 
     104                 :            : 
     105                 :            : static double
     106                 :          0 : shumate_marker_get_latitude (ShumateLocation *location)
     107                 :            : {
     108                 :          0 :   ShumateMarker *marker = (ShumateMarker *) location;
     109                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     110                 :            : 
     111         [ #  # ]:          0 :   g_assert (SHUMATE_IS_MARKER (location));
     112                 :            : 
     113                 :          0 :   return priv->lat;
     114                 :            : }
     115                 :            : 
     116                 :            : 
     117                 :            : static double
     118                 :          0 : shumate_marker_get_longitude (ShumateLocation *location)
     119                 :            : {
     120                 :          0 :   ShumateMarker *marker = (ShumateMarker *) location;
     121                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     122                 :            : 
     123         [ #  # ]:          0 :   g_assert (SHUMATE_IS_MARKER (location));
     124                 :            : 
     125                 :          0 :   return priv->lon;
     126                 :            : }
     127                 :            : 
     128                 :            : static void
     129                 :          0 : shumate_marker_add_child (GtkBuildable *buildable,
     130                 :            :                           GtkBuilder   *builder,
     131                 :            :                           GObject      *child,
     132                 :            :                           const char   *type)
     133                 :            : {
     134   [ #  #  #  #  :          0 :   if (GTK_IS_WIDGET (child))
             #  #  #  # ]
     135                 :          0 :     shumate_marker_set_child (SHUMATE_MARKER (buildable), GTK_WIDGET (child));
     136                 :            :   else
     137                 :          0 :     parent_buildable_iface->add_child (buildable, builder, child, type);
     138                 :          0 : }
     139                 :            : 
     140                 :            : static void
     141                 :          0 : shumate_marker_get_property (GObject *object,
     142                 :            :     guint prop_id,
     143                 :            :     GValue *value,
     144                 :            :     GParamSpec *pspec)
     145                 :            : {
     146                 :          0 :   ShumateMarker *marker = SHUMATE_MARKER (object);
     147                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     148                 :            : 
     149   [ #  #  #  #  :          0 :   switch (prop_id)
                      # ]
     150                 :            :     {
     151                 :          0 :     case PROP_LONGITUDE:
     152                 :          0 :       g_value_set_double (value, priv->lon);
     153                 :          0 :       break;
     154                 :            : 
     155                 :          0 :     case PROP_LATITUDE:
     156                 :          0 :       g_value_set_double (value, priv->lat);
     157                 :          0 :       break;
     158                 :            : 
     159                 :          0 :     case PROP_SELECTABLE:
     160                 :          0 :       g_value_set_boolean (value, priv->selectable);
     161                 :          0 :       break;
     162                 :            : 
     163                 :          0 :     case PROP_CHILD:
     164                 :          0 :       g_value_set_object (value, priv->child);
     165                 :          0 :       break;
     166                 :            : 
     167                 :          0 :     default:
     168                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     169                 :            :     }
     170                 :          0 : }
     171                 :            : 
     172                 :            : 
     173                 :            : static void
     174                 :          0 : shumate_marker_set_property (GObject *object,
     175                 :            :     guint prop_id,
     176                 :            :     const GValue *value,
     177                 :            :     GParamSpec *pspec)
     178                 :            : {
     179                 :          0 :   ShumateMarker *marker = SHUMATE_MARKER (object);
     180                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     181                 :            : 
     182   [ #  #  #  #  :          0 :   switch (prop_id)
                      # ]
     183                 :            :     {
     184                 :          0 :     case PROP_LONGITUDE:
     185                 :            :       {
     186                 :          0 :         double lon = g_value_get_double (value);
     187                 :          0 :         shumate_marker_set_location (SHUMATE_LOCATION (marker), priv->lat, lon);
     188                 :          0 :         break;
     189                 :            :       }
     190                 :            : 
     191                 :          0 :     case PROP_LATITUDE:
     192                 :            :       {
     193                 :          0 :         double lat = g_value_get_double (value);
     194                 :          0 :         shumate_marker_set_location (SHUMATE_LOCATION (marker), lat, priv->lon);
     195                 :          0 :         break;
     196                 :            :       }
     197                 :            : 
     198                 :          0 :     case PROP_SELECTABLE:
     199                 :            :       {
     200                 :          0 :         gboolean bvalue = g_value_get_boolean (value);
     201                 :          0 :         shumate_marker_set_selectable (marker, bvalue);
     202                 :          0 :         break;
     203                 :            :       }
     204                 :            : 
     205                 :          0 :     case PROP_CHILD:
     206                 :            :       {
     207                 :          0 :         GtkWidget *child = g_value_get_object (value);
     208                 :          0 :         shumate_marker_set_child (marker, child);
     209                 :          0 :         break;
     210                 :            :       }
     211                 :            : 
     212                 :          0 :     default:
     213                 :          0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     214                 :            :     }
     215                 :          0 : }
     216                 :            : 
     217                 :            : static void
     218                 :        206 : shumate_marker_dispose (GObject *object)
     219                 :            : {
     220                 :        206 :   ShumateMarker *marker = SHUMATE_MARKER (object);
     221                 :            : 
     222                 :        206 :   shumate_marker_set_child (marker, NULL);
     223                 :            : 
     224                 :        206 :   G_OBJECT_CLASS (shumate_marker_parent_class)->dispose (object);
     225                 :        206 : }
     226                 :            : 
     227                 :            : static void
     228                 :          5 : shumate_marker_class_init (ShumateMarkerClass *klass)
     229                 :            : {
     230                 :          5 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     231                 :          5 :   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
     232                 :            : 
     233                 :          5 :   object_class->get_property = shumate_marker_get_property;
     234                 :          5 :   object_class->set_property = shumate_marker_set_property;
     235                 :          5 :   object_class->dispose = shumate_marker_dispose;
     236                 :            : 
     237                 :            :   /**
     238                 :            :    * ShumateMarker:child:
     239                 :            :    *
     240                 :            :    * The child widget of the marker
     241                 :            :    */
     242                 :         10 :   obj_properties[PROP_CHILD] =
     243                 :          5 :     g_param_spec_object ("child",
     244                 :            :                          "Child",
     245                 :            :                           "The child widget of the marker",
     246                 :            :                           GTK_TYPE_WIDGET,
     247                 :            :                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
     248                 :            : 
     249                 :            :   /**
     250                 :            :    * ShumateMarker:selectable:
     251                 :            :    *
     252                 :            :    * The selectable state of the marker
     253                 :            :    */
     254                 :         10 :   obj_properties[PROP_SELECTABLE] =
     255                 :          5 :     g_param_spec_boolean ("selectable",
     256                 :            :                           "Selectable",
     257                 :            :                           "The draggable state of the marker",
     258                 :            :                           FALSE,
     259                 :            :                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
     260                 :            : 
     261                 :          5 :   g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
     262                 :            : 
     263                 :          5 :   g_object_class_override_property (object_class,
     264                 :            :       PROP_LONGITUDE,
     265                 :            :       "longitude");
     266                 :            : 
     267                 :          5 :   g_object_class_override_property (object_class,
     268                 :            :       PROP_LATITUDE,
     269                 :            :       "latitude");
     270                 :            : 
     271                 :          5 :   gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
     272                 :          5 :   gtk_widget_class_set_css_name (widget_class, "map-marker");
     273                 :          5 : }
     274                 :            : 
     275                 :            : static void
     276                 :        210 : shumate_marker_init (ShumateMarker *self)
     277                 :            : {
     278                 :        210 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (self);
     279                 :            : 
     280                 :        210 :   priv->lat = 0;
     281                 :        210 :   priv->lon = 0;
     282                 :        210 :   priv->selected = FALSE;
     283                 :        210 :   priv->selectable = TRUE;
     284                 :        210 : }
     285                 :            : 
     286                 :            : static void
     287                 :          5 : location_interface_init (ShumateLocationInterface *iface)
     288                 :            : {
     289                 :          5 :   iface->get_latitude = shumate_marker_get_latitude;
     290                 :          5 :   iface->get_longitude = shumate_marker_get_longitude;
     291                 :          5 :   iface->set_location = shumate_marker_set_location;
     292                 :          5 : }
     293                 :            : 
     294                 :            : static void
     295                 :          5 : buildable_interface_init (GtkBuildableIface *iface)
     296                 :            : {
     297                 :          5 :   parent_buildable_iface = g_type_interface_peek_parent (iface);
     298                 :          5 :   iface->add_child = shumate_marker_add_child;
     299                 :          5 : }
     300                 :            : 
     301                 :            : /**
     302                 :            :  * shumate_marker_new:
     303                 :            :  *
     304                 :            :  * Creates an instance of #ShumateMarker.
     305                 :            :  *
     306                 :            :  * Returns: a new #ShumateMarker.
     307                 :            :  */
     308                 :            : ShumateMarker *
     309                 :          2 : shumate_marker_new (void)
     310                 :            : {
     311                 :          2 :   return SHUMATE_MARKER (g_object_new (SHUMATE_TYPE_MARKER, NULL));
     312                 :            : }
     313                 :            : 
     314                 :            : /**
     315                 :            :  * shumate_marker_is_selected:
     316                 :            :  * @marker: a #ShumateMarker
     317                 :            :  *
     318                 :            :  * Checks whether the marker is selected.
     319                 :            :  *
     320                 :            :  * Returns: %TRUE if the marker is selected, otherwise %FALSE
     321                 :            :  */
     322                 :            : gboolean
     323                 :         50 : shumate_marker_is_selected (ShumateMarker *marker)
     324                 :            : {
     325                 :         50 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     326                 :            : 
     327         [ +  - ]:         50 :   g_return_val_if_fail (SHUMATE_IS_MARKER (marker), FALSE);
     328                 :            : 
     329                 :         50 :   return priv->selected;
     330                 :            : }
     331                 :            : 
     332                 :            : 
     333                 :            : /**
     334                 :            :  * shumate_marker_set_selectable:
     335                 :            :  * @marker: a #ShumateMarker
     336                 :            :  * @value: the selectable state
     337                 :            :  *
     338                 :            :  * Sets the marker as selectable or not.
     339                 :            :  */
     340                 :            : void
     341                 :          0 : shumate_marker_set_selectable (ShumateMarker *marker,
     342                 :            :                                gboolean       value)
     343                 :            : {
     344                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     345                 :            : 
     346         [ #  # ]:          0 :   g_return_if_fail (SHUMATE_IS_MARKER (marker));
     347                 :            : 
     348                 :          0 :   priv->selectable = value;
     349                 :            : 
     350                 :          0 :   g_object_notify_by_pspec (G_OBJECT (marker), obj_properties[PROP_SELECTABLE]);
     351                 :            : }
     352                 :            : 
     353                 :            : 
     354                 :            : /**
     355                 :            :  * shumate_marker_get_selectable:
     356                 :            :  * @marker: a #ShumateMarker
     357                 :            :  *
     358                 :            :  * Checks whether the marker is selectable.
     359                 :            :  *
     360                 :            :  * Returns: the selectable or not state of the marker.
     361                 :            :  */
     362                 :            : gboolean
     363                 :         16 : shumate_marker_get_selectable (ShumateMarker *marker)
     364                 :            : {
     365                 :         16 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     366                 :            : 
     367         [ +  - ]:         16 :   g_return_val_if_fail (SHUMATE_IS_MARKER (marker), FALSE);
     368                 :            : 
     369                 :         16 :   return priv->selectable;
     370                 :            : }
     371                 :            : 
     372                 :            : /**
     373                 :            :  * shumate_marker_get_child:
     374                 :            :  * @marker: a #ShumateMarker
     375                 :            :  *
     376                 :            :  * Retrieves the current child of @marker.
     377                 :            :  *
     378                 :            :  * Returns: (transfer none) (nullable): a #GtkWidget.
     379                 :            :  */
     380                 :            : GtkWidget *
     381                 :          0 : shumate_marker_get_child (ShumateMarker *marker)
     382                 :            : {
     383                 :          0 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     384                 :            : 
     385         [ #  # ]:          0 :   g_return_val_if_fail (SHUMATE_IS_MARKER (marker), NULL);
     386                 :            : 
     387                 :          0 :   return priv->child;
     388                 :            : }
     389                 :            : 
     390                 :            : /**
     391                 :            :  * shumate_marker_set_child:
     392                 :            :  * @marker: a #ShumateMarker
     393                 :            :  * @child: (nullable): a #GtkWidget
     394                 :            :  *
     395                 :            :  * Sets the child widget of @marker.
     396                 :            :  */
     397                 :            : void
     398                 :        210 : shumate_marker_set_child (ShumateMarker *marker,
     399                 :            :                           GtkWidget     *child)
     400                 :            : {
     401                 :        210 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     402                 :            : 
     403         [ +  - ]:        210 :   g_return_if_fail (SHUMATE_IS_MARKER (marker));
     404                 :            : 
     405         [ +  + ]:        210 :   if (priv->child == child)
     406                 :            :     return;
     407                 :            : 
     408         [ +  + ]:          4 :   g_clear_pointer (&priv->child, gtk_widget_unparent);
     409                 :            : 
     410                 :          4 :   priv->child = child;
     411                 :            : 
     412         [ +  + ]:          4 :   if (priv->child)
     413                 :          2 :     gtk_widget_set_parent (priv->child, GTK_WIDGET (marker));
     414                 :            : 
     415                 :          4 :   g_object_notify_by_pspec (G_OBJECT (marker), obj_properties[PROP_CHILD]);
     416                 :            : }
     417                 :            : 
     418                 :            : /**
     419                 :            :  * PRIVATE:shumate_marker_set_selected:
     420                 :            :  * @marker: a #ShumateMarker
     421                 :            :  * @value: %TRUE to select the marker, %FALSE to unselect it
     422                 :            :  *
     423                 :            :  * Sets the selected state flag of the marker widget.
     424                 :            :  */
     425                 :            : void
     426                 :        228 : shumate_marker_set_selected (ShumateMarker *marker, gboolean value)
     427                 :            : {
     428                 :        228 :   ShumateMarkerPrivate *priv = shumate_marker_get_instance_private (marker);
     429                 :            : 
     430         [ +  + ]:        228 :   if (priv->selected == value)
     431                 :            :     return;
     432                 :            : 
     433                 :         20 :   priv->selected = value;
     434                 :            : 
     435         [ +  + ]:         20 :   if (value) {
     436                 :         10 :     gtk_widget_set_state_flags (GTK_WIDGET (marker),
     437                 :            :                                 GTK_STATE_FLAG_SELECTED, FALSE);
     438                 :            :   } else {
     439                 :         10 :     gtk_widget_unset_state_flags (GTK_WIDGET (marker),
     440                 :            :                                   GTK_STATE_FLAG_SELECTED);
     441                 :            :   }
     442                 :            : }

Generated by: LCOV version 1.14