[gtk/wip/otte/canvas: 1/2] canvas: Use a signal for compute-bounds




commit bcd04595ddcbfc9cf77fcd6354201d14255228b4
Author: Benjamin Otte <otte redhat com>
Date:   Fri Jul 8 17:31:38 2022 +0200

    canvas: Use a signal for compute-bounds
    
    Profiling indicates that this is about 30% slower for this chunk of
    code, but considering that it bumped time taken in the Puzzle demo (with
    40.000 pieces) from 18% to 22%, it doesn't seem too relevant.
    
    The Puzzle demo does nothing but placing items and drawing them after
    all.

 demos/gtk-demo/canvas_intro.c     |  4 +-
 demos/gtk-demo/canvas_planarity.c |  4 +-
 demos/gtk-demo/canvas_puzzle.c    |  5 +--
 gtk/gtkcanvasitem.c               | 92 ++++++++++++++++++++-------------------
 gtk/gtkcanvasitem.h               |  8 ----
 5 files changed, 51 insertions(+), 62 deletions(-)
---
diff --git a/demos/gtk-demo/canvas_intro.c b/demos/gtk-demo/canvas_intro.c
index 4bf99fb3ec..0bc7f3cac6 100644
--- a/demos/gtk-demo/canvas_intro.c
+++ b/demos/gtk-demo/canvas_intro.c
@@ -52,9 +52,7 @@ bind_item (GtkListItemFactory *factory,
   gtk_canvas_item_set_widget (ci, gtk_canvas_item_get_item (ci));
 
   /* Set a function to compute the position */
-  gtk_canvas_item_set_compute_bounds (ci,
-                                      center_item,
-                                      NULL, NULL);
+  g_signal_connect (ci, "compute-bounds", G_CALLBACK (center_item), NULL);
 }
 
 GtkWidget *
diff --git a/demos/gtk-demo/canvas_planarity.c b/demos/gtk-demo/canvas_planarity.c
index f10c84fa34..99340bc80f 100644
--- a/demos/gtk-demo/canvas_planarity.c
+++ b/demos/gtk-demo/canvas_planarity.c
@@ -242,12 +242,12 @@ bind_item (GtkListItemFactory *factory,
       gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
       gtk_canvas_item_set_widget (ci, widget);
 
-      gtk_canvas_item_set_compute_bounds (ci, set_vertex_bounds, NULL, NULL);
+      g_signal_connect (ci, "compute-bounds", G_CALLBACK (set_vertex_bounds), NULL);
     }
   else if (PLANARITY_IS_EDGE (item))
     {
       gtk_canvas_item_set_widget (ci, gtk_diagonal_line_new ());
-      gtk_canvas_item_set_compute_bounds (ci, set_edge_bounds, NULL, NULL);
+      g_signal_connect (ci, "compute-bounds", G_CALLBACK (set_edge_bounds), NULL);
     }
 }
 
diff --git a/demos/gtk-demo/canvas_puzzle.c b/demos/gtk-demo/canvas_puzzle.c
index 4fe20c3327..13222d5a35 100644
--- a/demos/gtk-demo/canvas_puzzle.c
+++ b/demos/gtk-demo/canvas_puzzle.c
@@ -43,7 +43,6 @@ move_item (GtkGestureDrag *gesture,
   origin->vertical += y / gtk_widget_get_height (GTK_WIDGET (canvas));
   origin->horizontal = CLAMP (origin->horizontal, 0, 1);
   origin->vertical = CLAMP (origin->vertical, 0, 1);
-  g_print ("%g %g\n", origin->horizontal, origin->vertical);
 
   gtk_canvas_item_invalidate_bounds (ci);
 }
@@ -70,9 +69,7 @@ bind_item (GtkListItemFactory *factory,
   origin->vertical = g_random_double ();
   g_object_set_data_full (G_OBJECT (ci), "position", origin, g_free);
 
-  gtk_canvas_item_set_compute_bounds (ci,
-                                      set_position_from_origin,
-                                      NULL, NULL);
+  g_signal_connect (ci, "compute-bounds", G_CALLBACK (set_position_from_origin), NULL);
 }
 
 static GListModel *
diff --git a/gtk/gtkcanvasitem.c b/gtk/gtkcanvasitem.c
index e19c9017e1..38ff9549a1 100644
--- a/gtk/gtkcanvasitem.c
+++ b/gtk/gtkcanvasitem.c
@@ -25,6 +25,8 @@
 #include "gtkcanvasbox.h"
 #include "gtkintl.h"
 #include "gtklistitemfactoryprivate.h"
+#include "gtkmarshalers.h"
+#include "gtkprivate.h"
 #include "gtkwidget.h"
 
 /**
@@ -41,9 +43,6 @@ struct _GtkCanvasItem
   GtkCanvas *canvas;
   gpointer item;
   GtkWidget *widget;
-  GtkCanvasItemComputeBoundsFunc compute_bounds_func;
-  gpointer user_data;
-  GDestroyNotify user_destroy;
 
   GtkCanvasBox bounds;
   GtkCanvasBox allocation;
@@ -61,9 +60,15 @@ enum
   N_PROPS
 };
 
+enum {
+  COMPUTE_BOUNDS,
+  LAST_SIGNAL
+};
+
 G_DEFINE_FINAL_TYPE (GtkCanvasItem, gtk_canvas_item, G_TYPE_OBJECT)
 
 static GParamSpec *properties[N_PROPS] = { NULL, };
+static guint signals[LAST_SIGNAL] = { 0 };
 
 static void
 gtk_canvas_item_dispose (GObject *object)
@@ -76,11 +81,6 @@ gtk_canvas_item_dispose (GObject *object)
   g_assert (self->item == NULL);
   g_assert (self->widget == NULL);
 
-  if (self->user_destroy)
-    self->user_destroy (self->user_data);
-  self->user_destroy = NULL;
-  self->user_data = NULL;
-
   G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
 }
 
@@ -172,6 +172,41 @@ gtk_canvas_item_class_init (GtkCanvasItemClass *klass)
                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
 
   g_object_class_install_properties (gobject_class, N_PROPS, properties);
+
+  /**
+   * GtkCanvasItem::compute-bounds
+   * @self: the `GtkCanvasItem`
+   * @bounds: (type Gtk.CanvasBox) (out caller-allocates): return
+   *   location for the bounds
+   *
+   * Emitted to determine the bounds for the widget of this canvasitem
+   * during a size allocation cycle.
+   *
+   * A handler for this signal should fill @bounds with
+   * the desired box to place the widget in.
+   *
+   * If the size depends on other items and cannot be computed yet,
+   * handlers should return %FALSE and the signal will then be emitted
+   * again once more items have been allocated.
+   *
+   * Because of that signal handlers are expected to be pure - not set
+   * any properties or have other side effects - and idempotent - 
+   * return the same result if called multiple times in order.
+   *
+   * returns: %TRUE if @bounds was set successfully
+   */
+  signals[COMPUTE_BOUNDS] =
+    g_signal_new (I_("compute-bounds"),
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  _gtk_boolean_handled_accumulator, NULL,
+                  _gtk_marshal_BOOLEAN__BOXED,
+                  G_TYPE_BOOLEAN, 1,
+                  GTK_TYPE_CANVAS_BOX | G_SIGNAL_TYPE_STATIC_SCOPE);
+  g_signal_set_va_marshaller (signals[COMPUTE_BOUNDS],
+                              G_TYPE_FROM_CLASS (gobject_class),
+                              _gtk_marshal_BOOLEAN__BOXEDv);
 }
 
 static void
@@ -206,15 +241,14 @@ gboolean
 gtk_canvas_item_allocate (GtkCanvasItem *self,
                           gboolean       force)
 {
+  gboolean result;
   int w, h;
 
   g_assert (!self->has_allocation);
 
-  if (!self->compute_bounds_func)
-    {
-      gtk_canvas_box_init (&self->bounds, 0, 0, 0, 0, 0.5, 0.5);
-    }
-  else if (!self->compute_bounds_func (self, &self->bounds, self->user_data))
+  g_signal_emit (self, signals[COMPUTE_BOUNDS], 0, &self->bounds, &result);
+
+  if (!result)
     {
       if (!force)
         return FALSE;
@@ -328,38 +362,6 @@ gtk_canvas_item_get_item (GtkCanvasItem *self)
   return self->item;
 }
 
-/**
- * gtk_canvas_item_set_compute_bounds:
- * @self: a `GtkCanvasItem`
- * @compute_bounds_func: the function to compute bounds
- * @user_data: (nullable): user data to pass to @compute_bounds_func
- * @user_destroy: destroy notify for @user_data
- *
- * Sets the function to call to compute bounds during allocation.
- *
- * This function may be called multiple times if it returned %FALSE
- * previously.
- *
- * Because of that the function is expected to be pure - not set
- * any properties or have other side effects - and idempotent - 
- * return the same result if called multiple times in order.
- */
-void
-gtk_canvas_item_set_compute_bounds (GtkCanvasItem                  *self,
-                                    GtkCanvasItemComputeBoundsFunc  compute_bounds_func,
-                                    gpointer                        user_data,
-                                    GDestroyNotify                  user_destroy)
-{
-  g_return_if_fail (GTK_IS_CANVAS_ITEM (self));
-
-  if (self->user_destroy)
-    self->user_destroy (self->user_data);
-
-  self->compute_bounds_func = compute_bounds_func;
-  self->user_data = user_data;
-  self->user_destroy = user_destroy;
-}
-
 void
 gtk_canvas_item_invalidate_bounds (GtkCanvasItem *self)
 {
diff --git a/gtk/gtkcanvasitem.h b/gtk/gtkcanvasitem.h
index 488656aa2f..9db1d0bf94 100644
--- a/gtk/gtkcanvasitem.h
+++ b/gtk/gtkcanvasitem.h
@@ -35,9 +35,6 @@ G_BEGIN_DECLS
 GDK_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (GtkCanvasItem, gtk_canvas_item, GTK, CANVAS_ITEM, GObject)
 
-typedef gboolean        (* GtkCanvasItemComputeBoundsFunc)      (GtkCanvasItem          *ci,
-                                                                 GtkCanvasBox           *out_box,
-                                                                 gpointer                user_data);
 GDK_AVAILABLE_IN_ALL
 GtkCanvas *             gtk_canvas_item_get_canvas              (GtkCanvasItem          *self);
 GDK_AVAILABLE_IN_ALL
@@ -49,11 +46,6 @@ void                    gtk_canvas_item_set_widget              (GtkCanvasItem
 GDK_AVAILABLE_IN_ALL
 GtkWidget *             gtk_canvas_item_get_widget              (GtkCanvasItem          *self);
 
-GDK_AVAILABLE_IN_ALL
-void                    gtk_canvas_item_set_compute_bounds      (GtkCanvasItem          *self,
-                                                                 GtkCanvasItemComputeBoundsFunc 
compute_bounds_func,
-                                                                 gpointer                user_data,
-                                                                 GDestroyNotify          user_destroy);
 GDK_AVAILABLE_IN_ALL
 void                    gtk_canvas_item_invalidate_bounds       (GtkCanvasItem          *self);
 


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