[libshumate] marker-layer: Rework allocation



commit 9e138d2f5b6caabd12c7975d0cd8440d78e7f15a
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Mar 2 11:02:11 2021 -0300

    marker-layer: Rework allocation
    
    ShumateMarkerLayer performs size allocation in such a way that is not compliant
    to GTK4 requirements. The most important constraint is that widgets can't queue
    allocations during allocation, and ShumateMarkerLayer breaks that by showing
    and hiding widgets during allocation.
    
    Rework ShumateMarkerLayer to not call gtk_widget_show() nor gtk_widget_hide()
    during allocation. Instead, use gtk_widget_set_child_visible(), which prevents
    widgets from painting, and also allows us to skip allocating them.
    
    In addition to that, rework the calculations to determine the child allocation.
    They were incorrect, and didn't account for the center of the viewport correctly.

 shumate/shumate-marker-layer.c | 101 ++++++++++++++++++++++++-----------------
 1 file changed, 59 insertions(+), 42 deletions(-)
---
diff --git a/shumate/shumate-marker-layer.c b/shumate/shumate-marker-layer.c
index 8ef55e2..e2e0cee 100644
--- a/shumate/shumate-marker-layer.c
+++ b/shumate/shumate-marker-layer.c
@@ -111,10 +111,11 @@ set_marker_position (ShumateMarkerLayer *layer,
 {
   ShumateViewport *viewport;
   ShumateMapSource *map_source;
-  int x, y;
-  int width, height;
+  gboolean within_viewport;
   double lon, lat;
-  GtkAllocation allocation;
+  double x, y;
+  int marker_width, marker_height;
+  int width, height;
 
   g_assert (SHUMATE_IS_MARKER_LAYER (layer));
 
@@ -126,48 +127,28 @@ set_marker_position (ShumateMarkerLayer *layer,
   lon = shumate_location_get_longitude (SHUMATE_LOCATION (marker));
   lat = shumate_location_get_latitude (SHUMATE_LOCATION (marker));
 
-  x = shumate_viewport_longitude_to_widget_x (viewport, GTK_WIDGET (layer), lon);
-  y = shumate_viewport_latitude_to_widget_y (viewport, GTK_WIDGET (layer), lat);
-
-  gtk_widget_measure (GTK_WIDGET (marker), GTK_ORIENTATION_HORIZONTAL, -1, 0, &allocation.width, NULL, NULL);
-  gtk_widget_measure (GTK_WIDGET (marker), GTK_ORIENTATION_VERTICAL, -1, 0, &allocation.height, NULL, NULL);
   width = gtk_widget_get_width (GTK_WIDGET (layer));
   height = gtk_widget_get_height (GTK_WIDGET (layer));
-  if (x < 0 && -x < allocation.width/2)
-    {
-      allocation = (GtkAllocation){0, 0, 0, 0};
-      gtk_widget_size_allocate (GTK_WIDGET (marker), &allocation, -1);
-      gtk_widget_hide (GTK_WIDGET (marker));
-      return;
-    }
-  else if (y < 0 && -y < allocation.height/2)
-    {
-      allocation = (GtkAllocation){0, 0, 0, 0};
-      gtk_widget_size_allocate (GTK_WIDGET (marker), &allocation, -1);
-      gtk_widget_hide (GTK_WIDGET (marker));
-      return;
-    }
-  else if (x > width + allocation.width/2)
-    {
-      allocation = (GtkAllocation){0, 0, 0, 0};
-      gtk_widget_size_allocate (GTK_WIDGET (marker), &allocation, -1);
-      gtk_widget_hide (GTK_WIDGET (marker));
-      return;
-    }
-  else if (y > height + allocation.height/2)
-    {
-      allocation = (GtkAllocation){0, 0, 0, 0};
-      gtk_widget_size_allocate (GTK_WIDGET (marker), &allocation, -1);
-      gtk_widget_hide (GTK_WIDGET (marker));
-      return;
-    }
-  else
+
+  x = roundf (shumate_viewport_longitude_to_widget_x (viewport, GTK_WIDGET (marker), lon) + width/2.f);
+  y = roundf (shumate_viewport_latitude_to_widget_y (viewport, GTK_WIDGET (marker), lat) + height/2.f);
+
+  gtk_widget_measure (GTK_WIDGET (marker), GTK_ORIENTATION_HORIZONTAL, -1, 0, &marker_width, NULL, NULL);
+  gtk_widget_measure (GTK_WIDGET (marker), GTK_ORIENTATION_VERTICAL, -1, 0, &marker_height, NULL, NULL);
+  within_viewport = x > -marker_width && x <= width &&
+                    y > -marker_height && y <= height &&
+                    marker_width < width && marker_height < height;
+
+  gtk_widget_set_child_visible (GTK_WIDGET (marker), within_viewport);
+
+  if (within_viewport)
     {
-      allocation.x = x - allocation.width/2;
-      allocation.y = y - allocation.height/2;
+      GtkAllocation marker_allocation;
 
-      gtk_widget_size_allocate (GTK_WIDGET (marker), &allocation, -1);
-      gtk_widget_show (GTK_WIDGET (marker));
+      gtk_widget_get_allocation (GTK_WIDGET (marker), &marker_allocation);
+
+      if (marker_allocation.x != (int)x || marker_allocation.y != (int)y)
+        gtk_widget_queue_allocate (GTK_WIDGET (layer));
     }
 }
 
@@ -221,8 +202,44 @@ shumate_marker_layer_size_allocate (GtkWidget *widget,
                                     int        baseline)
 {
   ShumateMarkerLayer *self = SHUMATE_MARKER_LAYER (widget);
+  ShumateViewport *viewport;
+  GtkAllocation allocation;
+  GtkWidget *child;
 
-  shumate_marker_layer_reposition_markers (self);
+  viewport = shumate_layer_get_viewport (SHUMATE_LAYER (self));
+
+  for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child))
+    {
+      gboolean within_viewport;
+      double lon, lat;
+      double x, y;
+
+      if (!gtk_widget_should_layout (child))
+        continue;
+
+      lon = shumate_location_get_longitude (SHUMATE_LOCATION (child));
+      lat = shumate_location_get_latitude (SHUMATE_LOCATION (child));
+
+      x = roundf (shumate_viewport_longitude_to_widget_x (viewport, child, lon) + width/2.f);
+      y = roundf (shumate_viewport_latitude_to_widget_y (viewport, child, lat) + height/2.f);
+
+      allocation.x = x;
+      allocation.y = y;
+
+      gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, 0, &allocation.width, NULL, NULL);
+      gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, 0, &allocation.height, NULL, NULL);
+
+      within_viewport = x > -allocation.width && x <= width &&
+                        y > -allocation.height && y <= height &&
+                        allocation.width < width && allocation.height < height;
+
+      gtk_widget_set_child_visible (child, within_viewport);
+
+      if (within_viewport)
+        gtk_widget_size_allocate (child, &allocation, -1);
+    }
 }
 
 static void


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