[libshumate] Make ShumateTile not a widget



commit 6abf6278d1fe44e570859f4605a631ec27f89361
Author: James Westman <james jwestman net>
Date:   Thu Aug 4 14:11:12 2022 +0000

    Make ShumateTile not a widget
    
    Fixes #49.

 shumate/shumate-map-layer.c | 96 ++++++++++++++++++++++-----------------------
 shumate/shumate-tile.c      | 70 +++++----------------------------
 shumate/shumate-tile.h      |  2 +-
 3 files changed, 58 insertions(+), 110 deletions(-)
---
diff --git a/shumate/shumate-map-layer.c b/shumate/shumate-map-layer.c
index 9a7ce98..b10ebd9 100644
--- a/shumate/shumate-map-layer.c
+++ b/shumate/shumate-map-layer.c
@@ -172,6 +172,14 @@ add_symbols (ShumateMapLayer  *self,
 
 static void recompute_grid (ShumateMapLayer *self);
 
+static void
+on_tile_notify_state (ShumateMapLayer          *self,
+                      G_GNUC_UNUSED GParamSpec *pspec,
+                      ShumateTile              *tile)
+{
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
 static void
 on_tile_filled (GObject      *source_object,
                 GAsyncResult *res,
@@ -221,8 +229,9 @@ add_tile (ShumateMapLayer  *self,
       g_hash_table_insert (self->tile_fill, g_object_ref (tile), cancellable);
     }
 
-  gtk_widget_insert_before (GTK_WIDGET (tile), GTK_WIDGET (self), NULL);
   g_hash_table_insert (self->tile_children, pos, g_object_ref (tile));
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+  g_signal_connect_object (tile, "notify::state", (GCallback)on_tile_notify_state, self, G_CONNECT_SWAPPED);
 }
 
 static void
@@ -241,15 +250,14 @@ remove_tile (ShumateMapLayer  *self,
   shumate_vector_symbol_container_remove_symbols (self->symbols, pos->x, pos->y, pos->zoom);
 #endif
 
-  gtk_widget_unparent (GTK_WIDGET (tile));
+  g_signal_handlers_disconnect_by_func (tile, on_tile_notify_state, self);
 }
 
 static void
 recompute_grid (ShumateMapLayer *self)
 {
   /* Computes which tile positions are visible, ensures that all the right
-   * tiles are added to the ShumateMapLayer widget, and removes tiles which are
-   * no longer visible. */
+   * tiles are loaded, and removes tiles which are no longer visible. */
 
   GHashTableIter iter;
   gpointer key, value;
@@ -376,6 +384,7 @@ queue_recompute_grid_in_idle (ShumateMapLayer *self)
                            "[shumate] recompute_grid_in_idle_cb");
 }
 
+
 static void
 on_view_longitude_changed (ShumateMapLayer *self,
                            GParamSpec      *pspec,
@@ -384,7 +393,6 @@ on_view_longitude_changed (ShumateMapLayer *self,
   g_assert (SHUMATE_IS_MAP_LAYER (self));
 
   recompute_grid (self);
-  gtk_widget_queue_allocate (GTK_WIDGET (self));
 }
 
 static void
@@ -395,7 +403,6 @@ on_view_latitude_changed (ShumateMapLayer *self,
   g_assert (SHUMATE_IS_MAP_LAYER (self));
 
   recompute_grid (self);
-  gtk_widget_queue_allocate (GTK_WIDGET (self));
 }
 
 static void
@@ -406,7 +413,6 @@ on_view_zoom_level_changed (ShumateMapLayer *self,
   g_assert (SHUMATE_IS_MAP_LAYER (self));
 
   recompute_grid (self);
-  gtk_widget_queue_allocate (GTK_WIDGET (self));
 }
 
 static void
@@ -416,7 +422,7 @@ on_view_rotation_changed (ShumateMapLayer *self,
 {
   g_assert (SHUMATE_IS_MAP_LAYER (self));
 
-  gtk_widget_queue_allocate (GTK_WIDGET (self));
+  recompute_grid (self);
 }
 
 static void
@@ -506,36 +512,7 @@ shumate_map_layer_size_allocate (GtkWidget *widget,
                                  int        baseline)
 {
   ShumateMapLayer *self = SHUMATE_MAP_LAYER (widget);
-  ShumateViewport *viewport;
   GtkAllocation child_allocation;
-  int tile_size;
-  int zoom_level;
-  double latitude, longitude;
-  int longitude_x, latitude_y;
-
-  GHashTableIter iter;
-  gpointer key, value;
-
-  viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
-  tile_size = shumate_map_source_get_tile_size (self->map_source);
-  zoom_level = (guint) shumate_viewport_get_zoom_level (viewport);
-  latitude = shumate_location_get_latitude (SHUMATE_LOCATION (viewport));
-  longitude = shumate_location_get_longitude (SHUMATE_LOCATION (viewport));
-  latitude_y = (guint) shumate_map_source_get_y (self->map_source, zoom_level, latitude);
-  longitude_x = (guint) shumate_map_source_get_x (self->map_source, zoom_level, longitude);
-
-  g_hash_table_iter_init (&iter, self->tile_children);
-  while (g_hash_table_iter_next (&iter, &key, &value))
-    {
-      TileGridPosition *pos = key;
-      ShumateTile *tile = value;
-
-      child_allocation.width = tile_size * pow (2, zoom_level - pos->zoom);
-      child_allocation.height = child_allocation.width;
-      child_allocation.x = -(longitude_x - width/2) + child_allocation.width * pos->x;
-      child_allocation.y = -(latitude_y - height/2) + child_allocation.height * pos->y;
-      gtk_widget_size_allocate (GTK_WIDGET (tile), &child_allocation, baseline);
-    }
 
 #ifdef SHUMATE_HAS_VECTOR_RENDERER
   /* gtk_widget_measure needs to be called during size_allocate, but we don't
@@ -550,10 +527,8 @@ shumate_map_layer_size_allocate (GtkWidget *widget,
   gtk_widget_size_allocate (GTK_WIDGET (self->symbols), &child_allocation, baseline);
 #endif
 
-  /* We can't recompute while allocating, so queue an idle callback to run
-   * the recomputation outside the allocation cycle.
-   */
-  queue_recompute_grid_in_idle (self);
+  /* Make sure the tile grid is up to date */
+  recompute_grid (self);
 }
 
 static void
@@ -595,25 +570,48 @@ shumate_map_layer_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
   ShumateMapLayer *self = SHUMATE_MAP_LAYER (widget);
   ShumateViewport *viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
   double zoom_level = shumate_viewport_get_zoom_level (viewport);
-  double extra_zoom = pow (2.0, fmod (zoom_level, 1.0));
   int width = gtk_widget_get_width (GTK_WIDGET (self));
   int height = gtk_widget_get_height (GTK_WIDGET (self));
   double rotation = shumate_viewport_get_rotation (viewport);
-  GtkWidget *child;
+  double latitude = shumate_location_get_latitude (SHUMATE_LOCATION (viewport));
+  double longitude = shumate_location_get_longitude (SHUMATE_LOCATION (viewport));
+  double latitude_y = shumate_map_source_get_y (self->map_source, zoom_level, latitude);
+  double longitude_x = shumate_map_source_get_x (self->map_source, zoom_level, longitude);
+  int tile_size = shumate_map_source_get_tile_size (self->map_source);
+
+  GHashTableIter iter;
+  gpointer key;
+  gpointer value;
 
   /* Scale and rotate around the center of the view */
   gtk_snapshot_save (snapshot);
   gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2.0, height / 2.0));
-  gtk_snapshot_scale (snapshot, extra_zoom, extra_zoom);
   gtk_snapshot_rotate (snapshot, rotation * 180 / G_PI);
   gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-width / 2.0, -height / 2.0));
 
-  for (child = gtk_widget_get_first_child (widget);
-       child != NULL;
-       child = gtk_widget_get_next_sibling (child))
+  g_hash_table_iter_init (&iter, self->tile_children);
+
+  while (g_hash_table_iter_next (&iter, &key, &value))
     {
-      if (SHUMATE_IS_TILE (child))
-        gtk_widget_snapshot_child (widget, child, snapshot);
+      TileGridPosition *pos = key;
+      ShumateTile *tile = value;
+      GdkPaintable *paintable = shumate_tile_get_paintable (tile);
+      double size = tile_size * pow (2, zoom_level - pos->zoom);
+
+      if (paintable == NULL)
+        continue;
+
+      gtk_snapshot_save (snapshot);
+
+      gtk_snapshot_translate (snapshot,
+                              &GRAPHENE_POINT_INIT (
+                                -(longitude_x - width/2.0) + size * pos->x,
+                                -(latitude_y - height/2.0) + size * pos->y
+                              ));
+
+      gdk_paintable_snapshot (paintable, snapshot, size, size);
+
+      gtk_snapshot_restore (snapshot);
     }
 
   gtk_snapshot_restore (snapshot);
diff --git a/shumate/shumate-tile.c b/shumate/shumate-tile.c
index 5cc99de..bbb1651 100644
--- a/shumate/shumate-tile.c
+++ b/shumate/shumate-tile.c
@@ -37,7 +37,7 @@
 
 struct _ShumateTile
 {
-  GtkWidget parent_instance;
+  GObject parent_instance;
 
   guint x; /* The x position on the map (in pixels) */
   guint y; /* The y position on the map (in pixels) */
@@ -51,7 +51,7 @@ struct _ShumateTile
   GPtrArray *symbols;
 };
 
-G_DEFINE_TYPE (ShumateTile, shumate_tile, GTK_TYPE_WIDGET);
+G_DEFINE_TYPE (ShumateTile, shumate_tile, G_TYPE_OBJECT);
 
 enum
 {
@@ -67,46 +67,6 @@ enum
 
 static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
 
-static void
-shumate_tile_snapshot (GtkWidget   *widget,
-                       GtkSnapshot *snapshot)
-{
-  ShumateTile *self = SHUMATE_TILE (widget);
-  GdkPaintable *paintable = self->paintable;
-
-  if (paintable)
-    {
-      gdk_paintable_snapshot (paintable,
-                              snapshot,
-                              gtk_widget_get_width (widget),
-                              gtk_widget_get_height (widget));
-    }
-}
-
-static GtkSizeRequestMode 
-shumate_tile_get_request_mode (GtkWidget *widget)
-{
-  return GTK_SIZE_REQUEST_CONSTANT_SIZE;
-}
-
-static void
-shumate_tile_measure (GtkWidget      *widget,
-                      GtkOrientation  orientation,
-                      int             for_size,
-                      int            *minimum,
-                      int            *natural,
-                      int            *minimum_baseline,
-                      int            *natural_baseline)
-{
-  ShumateTile *self = SHUMATE_TILE (widget);
-
-  if (minimum)
-    *minimum = 0;
-
-  if (natural)
-    *natural = self->size;
-}
-
 static void
 shumate_tile_get_property (GObject    *object,
                            guint       property_id,
@@ -211,15 +171,10 @@ static void
 shumate_tile_class_init (ShumateTileClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
   object_class->get_property = shumate_tile_get_property;
   object_class->set_property = shumate_tile_set_property;
   object_class->dispose = shumate_tile_dispose;
-
-  widget_class->snapshot = shumate_tile_snapshot;
-  widget_class->measure = shumate_tile_measure;
-  widget_class->get_request_mode = shumate_tile_get_request_mode;
   
   /**
    * ShumateTile:x:
@@ -305,7 +260,7 @@ shumate_tile_class_init (ShumateTileClass *klass)
   /**
    * ShumateTile:paintable:
    *
-   * The #GdkPaintable backing the tile
+   * The [class@Gdk.Paintable] backing the tile
    */
   obj_properties[PROP_PAINTABLE] =
     g_param_spec_object ("paintable",
@@ -317,8 +272,6 @@ shumate_tile_class_init (ShumateTileClass *klass)
   g_object_class_install_properties (object_class,
                                      N_PROPERTIES,
                                      obj_properties);
-
-  gtk_widget_class_set_css_name (widget_class, "map-tile");
 }
 
 
@@ -597,11 +550,11 @@ shumate_tile_set_fade_in (ShumateTile *self,
 
 /**
  * shumate_tile_get_paintable:
- * @self: the #ShumateTile
+ * @self: the [class@Tile]
  *
- * Get the #GdkPaintable representing this tile.
+ * Get the [class@Gdk.Paintable] representing this tile.
  *
- * Returns: (transfer none) (nullable): A #GdkPaintable
+ * Returns: (transfer none) (nullable): A [class@Gdk.Paintable]
  */
 GdkPaintable *
 shumate_tile_get_paintable (ShumateTile *self)
@@ -613,10 +566,10 @@ shumate_tile_get_paintable (ShumateTile *self)
 
 /**
  * shumate_tile_set_paintable:
- * @self: the #ShumateTile
- * @paintable: a #GdkPaintable
+ * @self: the [class@Tile]
+ * @paintable: a [class@Gdk.Paintable]
  *
- * Sets the #GdkPaintable representing this tile.
+ * Sets the [class@Gdk.Paintable] representing this tile.
  */
 void
 shumate_tile_set_paintable (ShumateTile  *self,
@@ -625,10 +578,7 @@ shumate_tile_set_paintable (ShumateTile  *self,
   g_return_if_fail (SHUMATE_TILE (self));
 
   if (g_set_object (&self->paintable, paintable))
-    {
-      g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_PAINTABLE]);
-      gtk_widget_queue_draw (GTK_WIDGET (self));
-    }
+    g_object_notify_by_pspec (G_OBJECT (self), obj_properties[PROP_PAINTABLE]);
 }
 
 
diff --git a/shumate/shumate-tile.h b/shumate/shumate-tile.h
index 4a31495..220d566 100644
--- a/shumate/shumate-tile.h
+++ b/shumate/shumate-tile.h
@@ -28,7 +28,7 @@
 G_BEGIN_DECLS
 
 #define SHUMATE_TYPE_TILE shumate_tile_get_type ()
-G_DECLARE_FINAL_TYPE (ShumateTile, shumate_tile, SHUMATE, TILE, GtkWidget)
+G_DECLARE_FINAL_TYPE (ShumateTile, shumate_tile, SHUMATE, TILE, GObject)
 
 /**
  * ShumateState:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]