[gtk/wip/otte/canvas: 1/2] canvas: Completely rework bounds computation
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/canvas: 1/2] canvas: Completely rework bounds computation
- Date: Fri, 8 Jul 2022 05:37:32 +0000 (UTC)
commit ad2f4a27be8c205c0e5033a8170df7af248bd9d2
Author: Benjamin Otte <otte redhat com>
Date: Fri Jul 8 07:24:42 2022 +0200
canvas: Completely rework bounds computation
Instead of using a descriptive language to describe how to compute the
bounds, just set a vfunc and let the application provide a function.
That saves a lot of code - but makes the canvas rely on user code.
demos/gtk-demo/canvas_intro.c | 58 +++--
demos/gtk-demo/canvas_planarity.c | 127 +++++-----
demos/gtk-demo/canvas_puzzle.c | 68 ++---
gtk/gtk.h | 1 -
gtk/gtkcanvas.c | 106 +++-----
gtk/gtkcanvas.h | 2 +-
gtk/gtkcanvasbox.c | 203 ++-------------
gtk/gtkcanvasbox.h | 45 ++--
gtk/gtkcanvasboxprivate.h | 34 ---
gtk/gtkcanvasitem.c | 274 ++++++++++----------
gtk/gtkcanvasitem.h | 14 +-
gtk/gtkcanvasitemprivate.h | 8 +-
gtk/gtkcanvasvector.c | 181 --------------
gtk/gtkcanvasvector.h | 75 ------
gtk/gtkcanvasvectorimpl.c | 512 --------------------------------------
gtk/gtkcanvasvectorprivate.h | 115 ---------
gtk/gtktypes.h | 1 -
gtk/meson.build | 3 -
18 files changed, 372 insertions(+), 1455 deletions(-)
---
diff --git a/demos/gtk-demo/canvas_intro.c b/demos/gtk-demo/canvas_intro.c
index 2ef1846321..4bf99fb3ec 100644
--- a/demos/gtk-demo/canvas_intro.c
+++ b/demos/gtk-demo/canvas_intro.c
@@ -10,31 +10,51 @@
#define WIDTH 400
#define HEIGHT 300
+static gboolean
+center_item (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer unused)
+{
+ const GtkCanvasBox *viewport;
+ GtkWidget *widget;
+ int width, height;
+
+ /* We need to check if the viewport is available.
+ * If the canvas was scrolling, it might not be avaiable yet.
+ */
+ viewport = gtk_canvas_get_viewport (gtk_canvas_item_get_canvas (ci));
+ if (viewport == NULL)
+ return FALSE;
+
+ /* Measure the widget min for min so that it will line-break. */
+ widget = gtk_canvas_item_get_widget (ci);
+ gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, &width, NULL, NULL, NULL);
+ gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, width, &height, NULL, NULL, NULL);
+
+ /* Initialize the bounds for this widget:
+ * - the point is the center of the canvas' viewport
+ * - the size is the one we just computed
+ * - we want the origin point to be at the center
+ */
+ gtk_canvas_box_init (out_box,
+ viewport->size.width * 0.5,
+ viewport->size.height * 0.5,
+ 0, 0,
+ 0.5, 0.5);
+
+ return TRUE;
+}
+
static void
bind_item (GtkListItemFactory *factory,
GtkCanvasItem *ci)
{
- GtkCanvasVector *point;
- const GtkCanvasVector *size;
- GtkCanvasBox *box;
-
gtk_canvas_item_set_widget (ci, gtk_canvas_item_get_item (ci));
- /* Also center the item, so we do something interesting */
- point = gtk_canvas_vector_new (0, 0);
- box = gtk_canvas_box_new (point,
- gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
- 0.0, 0.0);
- gtk_canvas_vector_free (point);
-
- point = gtk_canvas_vector_new_from_box (box, 0.5, 0.5);
- gtk_canvas_box_free (box);
- size = gtk_canvas_vector_get_item_measure (ci, GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN);
- box = gtk_canvas_box_new (point, size, 0.5, 0.5);
- gtk_canvas_vector_free (point);
-
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
+ /* Set a function to compute the position */
+ gtk_canvas_item_set_compute_bounds (ci,
+ center_item,
+ NULL, NULL);
}
GtkWidget *
diff --git a/demos/gtk-demo/canvas_planarity.c b/demos/gtk-demo/canvas_planarity.c
index 93ab37571b..f10c84fa34 100644
--- a/demos/gtk-demo/canvas_planarity.c
+++ b/demos/gtk-demo/canvas_planarity.c
@@ -78,7 +78,7 @@ struct _PlanarityVertex
{
GObject parent_instance;
- graphene_point_t position;
+ GtkOrigin position;
};
#define PLANARITY_TYPE_VERTEX (planarity_vertex_get_type ())
@@ -97,14 +97,15 @@ planarity_vertex_init (PlanarityVertex *self)
}
static PlanarityVertex *
-planarity_vertex_new (float x,
- float y)
+planarity_vertex_new (float horizontal,
+ float vertical)
{
PlanarityVertex *self;
self = g_object_new (PLANARITY_TYPE_VERTEX, NULL);
- graphene_point_init (&self->position, x, y);
+ self->position.horizontal = horizontal;
+ self->position.vertical = vertical;
return self;
}
@@ -147,54 +148,83 @@ planarity_edge_new (PlanarityVertex *from,
return edge;
}
-static void
-set_item_position (GtkCanvasItem *ci)
+static gboolean
+set_vertex_bounds (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data)
{
PlanarityVertex *vertex = gtk_canvas_item_get_item (ci);
- GtkCanvasVector *point, *size;
- GtkCanvasBox *box, *viewport;
- float x = vertex->position.x;
- float y = vertex->position.y;
-
- point = gtk_canvas_vector_new (0, 0);
- viewport = gtk_canvas_box_new (point,
- gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
- 0.0, 0.0);
- gtk_canvas_vector_free (point);
-
- point = gtk_canvas_vector_new_from_box (viewport, x, y);
- gtk_canvas_box_free (viewport);
- size = gtk_canvas_vector_new (0, 0);
- box = gtk_canvas_box_new (point, size, x, y);
- gtk_canvas_vector_free (point);
- gtk_canvas_vector_free (size);
-
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
+ const GtkCanvasBox *viewport;
+
+ viewport = gtk_canvas_get_viewport (gtk_canvas_item_get_canvas (ci));
+ if (viewport == NULL)
+ return FALSE;
+
+ gtk_canvas_box_init (out_box,
+ viewport->size.width * vertex->position.horizontal,
+ viewport->size.height * vertex->position.vertical,
+ 0, 0,
+ vertex->position.horizontal,
+ vertex->position.vertical);
+
+ return TRUE;
}
static void
-move_item (GtkGestureDrag *gesture,
- double x,
- double y,
- GtkCanvasItem *ci)
+move_vertex (GtkGestureDrag *gesture,
+ double x,
+ double y,
+ GtkCanvasItem *ci)
{
GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
- GtkWidget *widget = gtk_canvas_item_get_widget (ci);
PlanarityVertex *vertex = gtk_canvas_item_get_item (ci);
- x /= (gtk_widget_get_width (GTK_WIDGET (canvas)) - gtk_widget_get_width (widget));
- y /= (gtk_widget_get_height (GTK_WIDGET (canvas)) - gtk_widget_get_height (widget));
+ x /= gtk_widget_get_width (GTK_WIDGET (canvas));
+ y /= gtk_widget_get_height (GTK_WIDGET (canvas));
+
+ vertex->position.horizontal = CLAMP (vertex->position.horizontal + x, 0, 1);
+ vertex->position.vertical = CLAMP (vertex->position.vertical + y, 0, 1);
- vertex->position = GRAPHENE_POINT_INIT (CLAMP (vertex->position.x + x, 0, 1), CLAMP (vertex->position.y +
y, 0, 1));
- set_item_position (ci);
+ gtk_canvas_item_invalidate_bounds (ci);
+}
+
+static gboolean
+set_edge_bounds (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data)
+{
+ PlanarityEdge *edge = gtk_canvas_item_get_item (ci);
+ GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
+ GtkCanvasItem *from_item, *to_item;
+ const GtkCanvasBox *from_box, *to_box;
+ graphene_rect_t from_rect, to_rect;
+ graphene_point_t from_center, to_center;
+
+ from_item = gtk_canvas_lookup_item (canvas, edge->from);
+ to_item = gtk_canvas_lookup_item (canvas, edge->to);
+ from_box = gtk_canvas_item_get_allocation (from_item);
+ to_box = gtk_canvas_item_get_allocation (to_item);
+ if (from_box == NULL || to_box == NULL)
+ return FALSE;
+
+ gtk_canvas_box_to_rect (from_box, &from_rect);
+ gtk_canvas_box_to_rect (to_box, &to_rect);
+ graphene_rect_get_center (&from_rect, &from_center);
+ graphene_rect_get_center (&to_rect, &to_center);
+
+ gtk_canvas_box_init (out_box,
+ from_center.x, from_center.y,
+ to_center.x - from_center.x,
+ to_center.y - from_center.y,
+ 0, 0);
+
+ return TRUE;
}
static void
bind_item (GtkListItemFactory *factory,
GtkCanvasItem *ci)
{
- GtkCanvasBox *box;
gpointer item;
item = gtk_canvas_item_get_item (ci);
@@ -207,34 +237,17 @@ bind_item (GtkListItemFactory *factory,
widget = gtk_image_new_from_icon_name ("media-record-symbolic");
gtk_image_set_icon_size (GTK_IMAGE (widget), GTK_ICON_SIZE_LARGE);
gesture = gtk_gesture_drag_new ();
- g_signal_connect (gesture, "drag-update", G_CALLBACK (move_item), ci);
- g_signal_connect (gesture, "drag-end", G_CALLBACK (move_item), ci);
+ g_signal_connect (gesture, "drag-update", G_CALLBACK (move_vertex), ci);
+ g_signal_connect (gesture, "drag-end", G_CALLBACK (move_vertex), ci);
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
gtk_canvas_item_set_widget (ci, widget);
- set_item_position (ci);
+ gtk_canvas_item_set_compute_bounds (ci, set_vertex_bounds, NULL, NULL);
}
else if (PLANARITY_IS_EDGE (item))
{
- GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
- PlanarityEdge *edge = PLANARITY_EDGE (item);
- GtkCanvasItem *from_item, *to_item;
- const GtkCanvasBox *from_box, *to_box;
- GtkCanvasVector *from_point, *to_point;
-
gtk_canvas_item_set_widget (ci, gtk_diagonal_line_new ());
-
- from_item = gtk_canvas_lookup_item (canvas, edge->from);
- to_item = gtk_canvas_lookup_item (canvas, edge->to);
- from_box = gtk_canvas_box_get_item_allocation (from_item);
- to_box = gtk_canvas_box_get_item_allocation (to_item);
- from_point = gtk_canvas_vector_new_from_box (from_box, 0.5, 0.5);
- to_point = gtk_canvas_vector_new_from_box (to_box, 0.5, 0.5);
- box = gtk_canvas_box_new_points (from_point, to_point);
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
- gtk_canvas_vector_free (from_point);
- gtk_canvas_vector_free (to_point);
+ gtk_canvas_item_set_compute_bounds (ci, set_edge_bounds, NULL, NULL);
}
}
diff --git a/demos/gtk-demo/canvas_puzzle.c b/demos/gtk-demo/canvas_puzzle.c
index f1ee30703b..4fe20c3327 100644
--- a/demos/gtk-demo/canvas_puzzle.c
+++ b/demos/gtk-demo/canvas_puzzle.c
@@ -9,32 +9,25 @@
#include "puzzlepiece.h"
-static void
-set_item_position (GtkCanvasItem *ci,
- float x,
- float y)
+static gboolean
+set_position_from_origin (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data)
{
- GtkCanvasVector *point, *size;
- GtkCanvasBox *box, *viewport;
-
- x = CLAMP (x, 0, 1);
- y = CLAMP (y, 0, 1);
-
- point = gtk_canvas_vector_new (0, 0);
- viewport = gtk_canvas_box_new (point,
- gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
- 0.0, 0.0);
- gtk_canvas_vector_free (point);
-
- point = gtk_canvas_vector_new_from_box (viewport, x, y);
- gtk_canvas_box_free (viewport);
- size = gtk_canvas_vector_new (0, 0);
- box = gtk_canvas_box_new (point, size, x, y);
- gtk_canvas_vector_free (point);
- gtk_canvas_vector_free (size);
-
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
+ GtkOrigin *origin = g_object_get_data (G_OBJECT (ci), "position");
+ const GtkCanvasBox *viewport = gtk_canvas_get_viewport (gtk_canvas_item_get_canvas (ci));
+
+ if (viewport == NULL)
+ return FALSE;
+
+ gtk_canvas_box_init (out_box,
+ viewport->size.width * origin->horizontal,
+ viewport->size.height * origin->vertical,
+ 0, 0,
+ origin->horizontal,
+ origin->vertical);
+
+ return TRUE;
}
static void
@@ -44,14 +37,15 @@ move_item (GtkGestureDrag *gesture,
GtkCanvasItem *ci)
{
GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
- graphene_rect_t bounds;
+ GtkOrigin *origin = g_object_get_data (G_OBJECT (ci), "position");
- if (!gtk_canvas_box_eval (gtk_canvas_item_get_bounds (ci), &bounds))
- return;
+ origin->horizontal += x / gtk_widget_get_width (GTK_WIDGET (canvas));
+ 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);
- set_item_position (ci,
- (bounds.origin.x + x) / (gtk_widget_get_width (GTK_WIDGET (canvas)) -
bounds.size.width),
- (bounds.origin.y + y) / (gtk_widget_get_height (GTK_WIDGET (canvas)) -
bounds.size.height));
+ gtk_canvas_item_invalidate_bounds (ci);
}
static void
@@ -60,6 +54,7 @@ bind_item (GtkListItemFactory *factory,
{
GtkWidget *widget;
GtkGesture *gesture;
+ GtkOrigin *origin;
widget = gtk_picture_new_for_paintable (gtk_canvas_item_get_item (ci));
gtk_picture_set_can_shrink (GTK_PICTURE (widget), FALSE);
@@ -69,8 +64,15 @@ bind_item (GtkListItemFactory *factory,
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
gtk_canvas_item_set_widget (ci, widget);
- /* Also center the item, so we do something interesting */
- set_item_position (ci, g_random_double (), g_random_double ());
+ /* Set a random position */
+ origin = g_new (GtkOrigin, 1);
+ origin->horizontal = g_random_double ();
+ 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);
}
static GListModel *
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 010d0fed01..051471c6f6 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -62,7 +62,6 @@
#include <gtk/gtkcanvas.h>
#include <gtk/gtkcanvasbox.h>
#include <gtk/gtkcanvasitem.h>
-#include <gtk/gtkcanvasvector.h>
#include <gtk/gtkcellarea.h>
#include <gtk/gtkcellareabox.h>
#include <gtk/gtkcellareacontext.h>
diff --git a/gtk/gtkcanvas.c b/gtk/gtkcanvas.c
index 2d5527ea08..2a78fddfa2 100644
--- a/gtk/gtkcanvas.c
+++ b/gtk/gtkcanvas.c
@@ -23,7 +23,6 @@
#include "gtkcanvasbox.h"
#include "gtkcanvasitemprivate.h"
-#include "gtkcanvasvectorprivate.h"
#include "gtkintl.h"
#include "gtklistitemfactory.h"
#include "gtkwidgetprivate.h"
@@ -53,7 +52,8 @@ struct _GtkCanvas
GtkCanvasItems items;
GHashTable *item_lookup;
- GtkCanvasVector viewport_size;
+ GtkCanvasBox viewport;
+ guint viewport_valid : 1;
};
enum
@@ -164,7 +164,6 @@ gtk_canvas_finalize (GObject *object)
GtkCanvas *self = GTK_CANVAS (object);
g_hash_table_unref (self->item_lookup);
- gtk_canvas_vector_finish (&self->viewport_size);
G_OBJECT_CLASS (gtk_canvas_parent_class)->finalize (object);
}
@@ -218,15 +217,17 @@ gtk_canvas_set_property (GObject *object,
}
static void
-gtk_canvas_validate_variables (GtkCanvas *self)
+gtk_canvas_invalidate_allocation (GtkCanvas *self)
{
int i;
+ self->viewport_valid = FALSE;
+
for (i = 0; i < gtk_canvas_items_get_size (&self->items); i++)
{
GtkCanvasItem *ci = gtk_canvas_items_get (&self->items, i);
- gtk_canvas_item_validate_variables (ci);
+ gtk_canvas_item_invalidate_allocation (ci);
}
}
@@ -240,9 +241,13 @@ gtk_canvas_allocate (GtkWidget *widget,
gboolean missing, force, success;
gsize i;
- gtk_canvas_validate_variables (self);
+ gtk_canvas_invalidate_allocation (self);
- gtk_canvas_vector_init_constant (gtk_canvas_vector_get_variable (&self->viewport_size), width, height);
+ self->viewport_valid = TRUE;
+ gtk_canvas_box_init (&self->viewport,
+ 0, 0,
+ width, height,
+ 0, 0);
force = FALSE;
do
@@ -254,71 +259,17 @@ gtk_canvas_allocate (GtkWidget *widget,
for (i = 0; i < gtk_canvas_items_get_size (&self->items); i++)
{
GtkCanvasItem *ci = gtk_canvas_items_get (&self->items, i);
- GtkWidget *child = gtk_canvas_item_get_widget (ci);
- const GtkCanvasBox *bounds;
- graphene_rect_t rect;
- int x, y, w, h;
- if (child == NULL || gtk_canvas_item_has_allocation (ci))
+ if (gtk_canvas_item_has_allocation (ci))
continue;
- bounds = gtk_canvas_item_get_bounds (ci);
- if (!gtk_canvas_box_eval (bounds, &rect))
- {
- if (force)
- {
- rect = *graphene_rect_zero ();
- /* XXX: set force to FALSE? */
- }
- else
- {
- missing = TRUE;
- continue;
- }
- }
-
- if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
- {
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL);
- w = MAX (w, ceil (ABS (rect.size.width)));
- gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL);
- h = MAX (h, ceil (ABS (rect.size.height)));
- }
- else
- {
- gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL);
- h = MAX (h, ceil (ABS (rect.size.height)));
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL);
- w = MAX (w, ceil (ABS (rect.size.width)));
- }
-
- if (rect.size.width < 0)
- w = -w;
- if (rect.size.height < 0)
- h = -h;
- if (ABS (w) > ABS (rect.size.width) || ABS (h) > ABS (rect.size.height))
- {
- graphene_vec2_t origin;
-
- if (!gtk_canvas_vector_eval (gtk_canvas_box_get_origin (bounds), &origin))
- graphene_vec2_init_from_vec2 (&origin, graphene_vec2_zero ());
-
- if (ABS (w) > ABS (rect.size.width))
- x = round (rect.origin.x + graphene_vec2_get_x (&origin) * (rect.size.width - w));
- else
- x = round (rect.origin.x);
- if (ABS (h) > ABS (rect.size.height))
- y = round (rect.origin.y + graphene_vec2_get_y (&origin) * (rect.size.height - h));
- else
- y = round (rect.origin.y);
- }
- else
+ if (!gtk_canvas_item_allocate (ci, force))
{
- x = round (rect.origin.x);
- y = round (rect.origin.y);
+ g_assert (!force);
+ missing = TRUE;
+ continue;
}
- gtk_canvas_item_allocate (ci, &GRAPHENE_RECT_INIT (x, y, w, h));
success = TRUE;
}
if (!success)
@@ -380,8 +331,6 @@ static void
gtk_canvas_init (GtkCanvas *self)
{
self->item_lookup = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- gtk_canvas_vector_init_variable (&self->viewport_size, "viewport.size");
}
/**
@@ -554,8 +503,23 @@ gtk_canvas_lookup_item (GtkCanvas *self,
return g_hash_table_lookup (self->item_lookup, item);
}
-const GtkCanvasVector *
-gtk_canvas_get_viewport_size (GtkCanvas *self)
+/**
+ * gtk_canvas_get_viewport:
+ * @self: a `GtkCanvas`
+ *
+ * Gets the viewport of the canvas. If no viewport is available,
+ * in particular if it has not been determined during size
+ * allocation, %NULL is returned.
+ *
+ * Returns: The viewport
+ **/
+const GtkCanvasBox *
+gtk_canvas_get_viewport (GtkCanvas *self)
{
- return &self->viewport_size;
+ g_return_val_if_fail (GTK_IS_CANVAS (self), NULL);
+
+ if (!self->viewport_valid)
+ return NULL;
+
+ return &self->viewport;
}
diff --git a/gtk/gtkcanvas.h b/gtk/gtkcanvas.h
index 75e8f8b093..98e7a398e8 100644
--- a/gtk/gtkcanvas.h
+++ b/gtk/gtkcanvas.h
@@ -54,7 +54,7 @@ GtkCanvasItem * gtk_canvas_lookup_item (GtkCanvas
gpointer item);
GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_get_viewport_size (GtkCanvas *self);
+const GtkCanvasBox * gtk_canvas_get_viewport (GtkCanvas *self);
G_END_DECLS
diff --git a/gtk/gtkcanvasbox.c b/gtk/gtkcanvasbox.c
index 56388c2bab..cb5a175afa 100644
--- a/gtk/gtkcanvasbox.c
+++ b/gtk/gtkcanvasbox.c
@@ -29,141 +29,12 @@
#include "config.h"
-#include "gtkcanvasboxprivate.h"
-
-/* {{{ Boilerplate */
+#include "gtkcanvasbox.h"
G_DEFINE_BOXED_TYPE (GtkCanvasBox, gtk_canvas_box,
gtk_canvas_box_copy,
gtk_canvas_box_free)
-void
-gtk_canvas_box_init (GtkCanvasBox *self,
- const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- const GtkCanvasVector *origin)
-{
- gtk_canvas_vector_init_copy (&self->point, point);
- gtk_canvas_vector_init_copy (&self->size, size);
- gtk_canvas_vector_init_copy (&self->origin, origin);
-}
-
-void
-gtk_canvas_box_init_copy (GtkCanvasBox *self,
- const GtkCanvasBox *source)
-{
- gtk_canvas_box_init (self, &source->point, &source->size, &source->origin);
-}
-
-void
-gtk_canvas_box_finish (GtkCanvasBox *self)
-{
- gtk_canvas_vector_finish (&self->point);
- gtk_canvas_vector_finish (&self->size);
- gtk_canvas_vector_finish (&self->origin);
-}
-
-void
-gtk_canvas_box_init_variable (GtkCanvasBox *self,
- const char *format,
- ...)
-{
- char *name;
- va_list args;
-
- va_start (args, format);
- name = g_strdup_vprintf (format, args);
- va_end (args);
-
- gtk_canvas_vector_init_variable (&self->point, "%s.point", name);
- gtk_canvas_vector_init_variable (&self->size, "%s.size", name);
- gtk_canvas_vector_init_variable (&self->origin, "%s.origin", name);
-
- g_free (name);
-}
-
-void
-gtk_canvas_box_update_variable (GtkCanvasBox *self,
- const GtkCanvasBox *other)
-{
- gtk_canvas_vector_init_copy (gtk_canvas_vector_get_variable (&self->point), &other->point);
- gtk_canvas_vector_init_copy (gtk_canvas_vector_get_variable (&self->size), &other->size);
- gtk_canvas_vector_init_copy (gtk_canvas_vector_get_variable (&self->origin), &other->origin);
-}
-
-/**
- * gtk_canvas_box_new_points:
- * @point1: the first point
- * @point2: the second point
- *
- * Creates a new box describing the rectangle between the two
- * points
- *
- * Returns: a new box
- **/
-GtkCanvasBox *
-gtk_canvas_box_new_points (const GtkCanvasVector *point1,
- const GtkCanvasVector *point2)
-{
- GtkCanvasVector size, origin;
- GtkCanvasBox *result;
- graphene_vec2_t minus_one;
-
- g_return_val_if_fail (point1 != NULL, NULL);
- g_return_val_if_fail (point2 != NULL, NULL);
-
- graphene_vec2_init (&minus_one, -1.f, -1.f);
- gtk_canvas_vector_init_sum (&size,
- graphene_vec2_one (),
- point2,
- &minus_one,
- point1,
- NULL);
- gtk_canvas_vector_init_constant (&origin, 0, 0);
- result = g_slice_new (GtkCanvasBox);
- gtk_canvas_box_init (result, (GtkCanvasVector *) point1, &size, &origin);
- gtk_canvas_vector_finish (&size);
- gtk_canvas_vector_finish (&origin);
-
- return result;
-}
-
-/**
- * gtk_canvas_box_new:
- * @point: the origin point of the box
- * @size: size of the box
- * @origin_x: x coordinate of origin
- * @origin_y: y coordinate of origin
- *
- * Creates a new box of the given size relative to the given point.
- * The origin describes where in the box the point is located.
- * (0, 0) means the point describes the top left of the box, (1, 1)
- * describes the bottom right, and (0.5, 0.5) is the center.
- *
- * Returns: a new box
- **/
-GtkCanvasBox *
-gtk_canvas_box_new (const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- float origin_x,
- float origin_y)
-{
- GtkCanvasBox *self;
- GtkCanvasVector origin;
-
- g_return_val_if_fail (point != NULL, NULL);
- g_return_val_if_fail (size != NULL, NULL);
-
- gtk_canvas_vector_init_constant (&origin, origin_x, origin_y);
-
- self = g_slice_new (GtkCanvasBox);
- gtk_canvas_box_init (self, point, size, &origin);
-
- gtk_canvas_vector_finish (&origin);
-
- return self;
-}
-
GtkCanvasBox *
gtk_canvas_box_copy (const GtkCanvasBox *self)
{
@@ -171,8 +42,7 @@ gtk_canvas_box_copy (const GtkCanvasBox *self)
g_return_val_if_fail (self != NULL, NULL);
- copy = g_slice_new (GtkCanvasBox);
- gtk_canvas_box_init_copy (copy, self);
+ copy = g_slice_dup (GtkCanvasBox, self);
return copy;
}
@@ -180,59 +50,32 @@ gtk_canvas_box_copy (const GtkCanvasBox *self)
void
gtk_canvas_box_free (GtkCanvasBox *self)
{
- gtk_canvas_box_finish (self);
-
g_slice_free (GtkCanvasBox, self);
}
-gboolean
-gtk_canvas_box_eval (const GtkCanvasBox *self,
- graphene_rect_t *rect)
-{
- graphene_vec2_t point, size, origin;
-
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (rect != NULL, FALSE);
-
- if (!gtk_canvas_vector_eval (&self->point, &point) ||
- !gtk_canvas_vector_eval (&self->size, &size) ||
- !gtk_canvas_vector_eval (&self->origin, &origin))
- {
- *rect = *graphene_rect_zero ();
- return FALSE;
- }
-
- graphene_vec2_multiply (&origin, &size, &origin);
- graphene_vec2_subtract (&point, &origin, &point);
-
- *rect = GRAPHENE_RECT_INIT (graphene_vec2_get_x (&point),
- graphene_vec2_get_y (&point),
- graphene_vec2_get_x (&size),
- graphene_vec2_get_y (&size));
-
- return TRUE;
-}
-
-const GtkCanvasVector *
-gtk_canvas_box_get_point (const GtkCanvasBox *self)
-{
- g_return_val_if_fail (self != NULL, NULL);
-
- return &self->point;
-}
-
-const GtkCanvasVector *
-gtk_canvas_box_get_size (const GtkCanvasBox *self)
+void
+gtk_canvas_box_init (GtkCanvasBox *self,
+ float point_x,
+ float point_y,
+ float width,
+ float height,
+ float origin_horizontal,
+ float origin_vertical)
{
- g_return_val_if_fail (self != NULL, NULL);
-
- return &self->size;
+ self->point.x = point_x;
+ self->point.y = point_y;
+ self->size.width = width;
+ self->size.height = height;
+ self->origin.horizontal = origin_horizontal;
+ self->origin.vertical = origin_vertical;
}
-const GtkCanvasVector *
-gtk_canvas_box_get_origin (const GtkCanvasBox *self)
+void
+gtk_canvas_box_to_rect (const GtkCanvasBox *self,
+ graphene_rect_t *rect)
{
- g_return_val_if_fail (self != NULL, NULL);
-
- return &self->origin;
+ rect->size = self->size;
+ rect->origin = GRAPHENE_POINT_INIT (self->point.x - self->origin.horizontal * self->size.width,
+ self->point.y - self->origin.vertical * self->size.height);
+ graphene_rect_normalize (rect);
}
diff --git a/gtk/gtkcanvasbox.h b/gtk/gtkcanvasbox.h
index 2f08699f5a..e9bba1bc83 100644
--- a/gtk/gtkcanvasbox.h
+++ b/gtk/gtkcanvasbox.h
@@ -30,6 +30,20 @@
G_BEGIN_DECLS
+typedef struct _GtkOrigin GtkOrigin;
+
+struct _GtkOrigin {
+ float horizontal;
+ float vertical;
+};
+
+struct _GtkCanvasBox
+{
+ graphene_point_t point;
+ graphene_size_t size;
+ GtkOrigin origin;
+};
+
#define GTK_TYPE_CANVAS_BOX (gtk_canvas_box_get_type ())
GDK_AVAILABLE_IN_ALL
@@ -41,30 +55,17 @@ GDK_AVAILABLE_IN_ALL
void gtk_canvas_box_free (GtkCanvasBox *self);
GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_box_get_point (const GtkCanvasBox *self) G_GNUC_PURE;
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_box_get_size (const GtkCanvasBox *self) G_GNUC_PURE;
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_box_get_origin (const GtkCanvasBox *self) G_GNUC_PURE;
-
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_canvas_box_eval (const GtkCanvasBox *self,
- graphene_rect_t *rect)
G_GNUC_WARN_UNUSED_RESULT;
-
-GDK_AVAILABLE_IN_ALL
-GtkCanvasBox * gtk_canvas_box_new (const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- float origin_x,
- float origin_y);
-GDK_AVAILABLE_IN_ALL
-GtkCanvasBox * gtk_canvas_box_new_points (const GtkCanvasVector *point1,
- const GtkCanvasVector *point2);
+void gtk_canvas_box_init (GtkCanvasBox *self,
+ float point_x,
+ float point_y,
+ float width,
+ float height,
+ float origin_horizontal,
+ float origin_vertical);
GDK_AVAILABLE_IN_ALL
-const GtkCanvasBox * gtk_canvas_box_get_item_bounds (GtkCanvasItem *item);
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasBox * gtk_canvas_box_get_item_allocation (GtkCanvasItem *item);
-
+void gtk_canvas_box_to_rect (const GtkCanvasBox *self,
+ graphene_rect_t *rect);
G_END_DECLS
#endif /* __GTK_BOX_H__ */
diff --git a/gtk/gtkcanvasitem.c b/gtk/gtkcanvasitem.c
index 0ed91e7291..e19c9017e1 100644
--- a/gtk/gtkcanvasitem.c
+++ b/gtk/gtkcanvasitem.c
@@ -22,7 +22,7 @@
#include "gtkcanvasitemprivate.h"
#include "gtkcanvas.h"
-#include "gtkcanvasboxprivate.h"
+#include "gtkcanvasbox.h"
#include "gtkintl.h"
#include "gtklistitemfactoryprivate.h"
#include "gtkwidget.h"
@@ -41,17 +41,19 @@ struct _GtkCanvasItem
GtkCanvas *canvas;
gpointer item;
GtkWidget *widget;
+ GtkCanvasItemComputeBoundsFunc compute_bounds_func;
+ gpointer user_data;
+ GDestroyNotify user_destroy;
+
GtkCanvasBox bounds;
- GtkCanvasBox bounds_var;
- GtkCanvasBox allocation_var;
+ GtkCanvasBox allocation;
- GtkCanvasVector size_vecs[4];
+ guint has_allocation : 1;
};
enum
{
PROP_0,
- PROP_BOUNDS,
PROP_CANVAS,
PROP_ITEM,
PROP_WIDGET,
@@ -74,23 +76,12 @@ gtk_canvas_item_dispose (GObject *object)
g_assert (self->item == NULL);
g_assert (self->widget == NULL);
- G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
-}
+ if (self->user_destroy)
+ self->user_destroy (self->user_data);
+ self->user_destroy = NULL;
+ self->user_data = NULL;
-static void
-gtk_canvas_item_finalize (GObject *object)
-{
- GtkCanvasItem *self = GTK_CANVAS_ITEM (object);
- int i;
-
- for (i = 0; i < 4; i++)
- gtk_canvas_vector_finish (&self->size_vecs[i]);
-
- gtk_canvas_box_finish (&self->bounds);
- gtk_canvas_box_finish (&self->bounds_var);
- gtk_canvas_box_finish (&self->allocation_var);
-
- G_OBJECT_CLASS (gtk_canvas_item_parent_class)->finalize (object);
+ G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
}
static void
@@ -103,10 +94,6 @@ gtk_canvas_item_get_property (GObject *object,
switch (property_id)
{
- case PROP_BOUNDS:
- g_value_set_boxed (value, &self->bounds);
- break;
-
case PROP_CANVAS:
g_value_set_object (value, self->canvas);
break;
@@ -135,10 +122,6 @@ gtk_canvas_item_set_property (GObject *object,
switch (property_id)
{
- case PROP_BOUNDS:
- gtk_canvas_item_set_bounds (self, g_value_get_boxed (value));
- break;
-
case PROP_WIDGET:
gtk_canvas_item_set_widget (self, g_value_get_object (value));
break;
@@ -155,20 +138,9 @@ gtk_canvas_item_class_init (GtkCanvasItemClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gtk_canvas_item_dispose;
- gobject_class->finalize = gtk_canvas_item_finalize;
gobject_class->get_property = gtk_canvas_item_get_property;
gobject_class->set_property = gtk_canvas_item_set_property;
- /**
- * GtkCanvasItem:bounds: (attributes org.gtk.Property.get=gtk_canvas_item_get_bounds
org.gtk.Property.set=gtk_canvas_item_set_bounds)
- *
- * The bounds to place the widget into.
- */
- properties[PROP_BOUNDS] =
- g_param_spec_boxed ("bounds", NULL, NULL,
- GTK_TYPE_CANVAS_BOX,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
/**
* GtkCanvasItem:canvas: (attributes org.gtk.Property.get=gtk_canvas_item_get_canvas
org.gtk.Property.set=gtk_canvas_item_set_canvas)
*
@@ -205,17 +177,6 @@ gtk_canvas_item_class_init (GtkCanvasItemClass *klass)
static void
gtk_canvas_item_init (GtkCanvasItem *self)
{
- gtk_canvas_vector_init_variable (&self->size_vecs[0], "item%p.min_for_min", self);
- gtk_canvas_vector_init_variable (&self->size_vecs[1], "item%p.min_for_nat", self);
- gtk_canvas_vector_init_variable (&self->size_vecs[2], "item%p.nat_for_min", self);
- gtk_canvas_vector_init_variable (&self->size_vecs[3], "item%p.nat_for_nat", self);
-
- gtk_canvas_vector_init_constant (&self->bounds.point, 0, 0);
- gtk_canvas_vector_init_copy (&self->bounds.size, &self->size_vecs[GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT]);
- gtk_canvas_vector_init_constant (&self->bounds.origin, 0.5, 0.5);
- gtk_canvas_box_init_variable (&self->bounds_var, "item%p.bounds", self);
- gtk_canvas_box_update_variable (&self->bounds_var, &self->bounds);
- gtk_canvas_box_init_variable (&self->allocation_var, "item%p.allocation", self);
}
GtkCanvasItem *
@@ -236,70 +197,72 @@ gtk_canvas_item_new (GtkCanvas *canvas,
}
void
-gtk_canvas_item_validate_variables (GtkCanvasItem *self)
+gtk_canvas_item_invalidate_allocation (GtkCanvasItem *self)
{
- int w[4], h[4], i;
+ self->has_allocation = FALSE;
+}
- if (self->widget == NULL)
+gboolean
+gtk_canvas_item_allocate (GtkCanvasItem *self,
+ gboolean force)
+{
+ int w, h;
+
+ g_assert (!self->has_allocation);
+
+ if (!self->compute_bounds_func)
{
- memset (w, 0, sizeof (w));
- memset (h, 0, sizeof (h));
+ gtk_canvas_box_init (&self->bounds, 0, 0, 0, 0, 0.5, 0.5);
}
- else
+ else if (!self->compute_bounds_func (self, &self->bounds, self->user_data))
+ {
+ if (!force)
+ return FALSE;
+ gtk_canvas_box_init (&self->bounds, 0, 0, 0, 0, 0.5, 0.5);
+ }
+
+ if (self->widget)
{
if (gtk_widget_get_request_mode (self->widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
{
- gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, -1, &w[0], &w[2], NULL, NULL);
- w[1] = w[0];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, w[0], &h[0], &h[1], NULL, NULL);
- w[3] = w[2];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, w[2], &h[2], &h[3], NULL, NULL);
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL);
+ w = MAX (w, ceil (ABS (self->bounds.size.width)));
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL);
+ h = MAX (h, ceil (ABS (self->bounds.size.height)));
}
else
{
- gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, -1, &h[0], &h[2], NULL, NULL);
- h[1] = h[0];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, h[0], &w[0], &w[1], NULL, NULL);
- h[3] = h[2];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, h[2], &w[2], &w[3], NULL, NULL);
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL);
+ h = MAX (h, ceil (ABS (self->bounds.size.height)));
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL);
+ w = MAX (w, ceil (ABS (self->bounds.size.width)));
}
- }
- for (i = 0; i < 4; i++)
+ if (self->bounds.size.width >= 0)
+ w = MAX (self->bounds.size.width, w);
+ else
+ w = MIN (self->bounds.size.width, -w);
+ if (self->bounds.size.height >= 0)
+ h = MAX (self->bounds.size.height, h);
+ else
+ h = MIN (self->bounds.size.height, -h);
+ }
+ else
{
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->size_vecs[i]),
- 0, 0);
+ w = 0;
+ h = 0;
}
- gtk_canvas_vector_init_invalid (
- gtk_canvas_vector_get_variable (&self->allocation_var.point));
- gtk_canvas_vector_init_invalid (
- gtk_canvas_vector_get_variable (&self->allocation_var.size));
- gtk_canvas_vector_init_invalid (
- gtk_canvas_vector_get_variable (&self->allocation_var.origin));
-}
+ gtk_canvas_box_init (&self->allocation,
+ round (self->bounds.point.x - self->bounds.origin.horizontal * w)
+ + self->bounds.origin.horizontal * w,
+ round (self->bounds.point.y - self->bounds.origin.vertical * h)
+ + self->bounds.origin.vertical * h,
+ w, h,
+ self->bounds.origin.horizontal, self->bounds.origin.vertical);
+ self->has_allocation = TRUE;
-void
-gtk_canvas_item_allocate (GtkCanvasItem *self,
- graphene_rect_t *rect)
-{
- graphene_vec2_t origin;
-
- if (!gtk_canvas_vector_eval (&self->bounds.origin, &origin))
- graphene_vec2_init_from_vec2 (&origin, graphene_vec2_zero ());
-
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->allocation_var.point),
- rect->origin.x + graphene_vec2_get_x (&origin) * rect->size.width,
- rect->origin.y + graphene_vec2_get_y (&origin) * rect->size.height);
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->allocation_var.size),
- rect->size.width, rect->size.height);
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->allocation_var.origin),
- graphene_vec2_get_x (&origin),
- graphene_vec2_get_y (&origin));
+ return TRUE;
}
void
@@ -312,13 +275,9 @@ gtk_canvas_item_allocate_widget (GtkCanvasItem *self,
if (self->widget == NULL)
return;
- if (!gtk_canvas_box_eval (&self->allocation_var, &allocation))
- {
- /* gtkcanvas.c will not call this function otherwise */
- g_assert_not_reached ();
- }
-
+ gtk_canvas_box_to_rect (&self->allocation, &allocation);
graphene_rect_normalize (&allocation);
+
gtk_widget_size_allocate (self->widget,
&(GtkAllocation) {
allocation.origin.x - dx,
@@ -331,32 +290,7 @@ gtk_canvas_item_allocate_widget (GtkCanvasItem *self,
gboolean
gtk_canvas_item_has_allocation (GtkCanvasItem *self)
{
- return !gtk_canvas_vector_is_invalid (gtk_canvas_vector_get_variable (&self->allocation_var.point));
-}
-
-const GtkCanvasVector *
-gtk_canvas_vector_get_item_measure (GtkCanvasItem *item,
- GtkCanvasItemMeasure measure)
-{
- g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL);
-
- return &item->size_vecs[measure];
-}
-
-const GtkCanvasBox *
-gtk_canvas_box_get_item_bounds (GtkCanvasItem *item)
-{
- g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL);
-
- return &item->bounds_var;
-}
-
-const GtkCanvasBox *
-gtk_canvas_box_get_item_allocation (GtkCanvasItem *item)
-{
- g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL);
-
- return &item->allocation_var;
+ return self->has_allocation;
}
/**
@@ -395,44 +329,98 @@ gtk_canvas_item_get_item (GtkCanvasItem *self)
}
/**
- * gtk_canvas_item_set_bounds: (attributes org.gtk.Method.set_property=bounds)
+ * gtk_canvas_item_set_compute_bounds:
* @self: a `GtkCanvasItem`
- * @bounds: (transfer none): the bounds to allocate the widget in
+ * @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.
*
- * Sets the box to allocate the widget into.
+ * 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_bounds (GtkCanvasItem *self,
- const GtkCanvasBox *bounds)
+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));
- g_return_if_fail (bounds != NULL);
- gtk_canvas_box_init_copy (&self->bounds, bounds);
- gtk_canvas_box_update_variable (&self->bounds_var, bounds);
+ 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)
+{
+ g_return_if_fail (GTK_IS_CANVAS_ITEM (self));
if (self->canvas)
gtk_widget_queue_allocate (GTK_WIDGET (self->canvas));
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BOUNDS]);
}
/**
- * gtk_canvas_item_get_bounds: (attributes org.gtk.Method.get_property=bounds)
+ * gtk_canvas_item_get_bounds:
* @self: a `GtkCanvasItem`
*
* Gets the bounds that are used to allocate the widget
*
- * Returns: (transfer none): The bounds
+ * If the bounds are not known yet - for example when called during the size
+ * allocation phase before this item has succesfully computed its bounds -
+ * this function returns %NULL.
+ *
+ * See also gtk_canvas_item_get_allocation().
+ *
+ * Returns: (transfer none) (nullable): The bounds
*/
const GtkCanvasBox *
gtk_canvas_item_get_bounds (GtkCanvasItem *self)
{
g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+ if (!self->has_allocation)
+ return NULL;
+
return &self->bounds;
}
+/**
+ * gtk_canvas_item_get_allocation:
+ * @self: a `GtkCanvasItem`
+ *
+ * Gets the allocation assigned to the widget.
+ *
+ * If the bounds are not known yet - for example when called during the size
+ * allocation phase before this item has succesfully computed its bounds -
+ * this function returns %NULL.
+ *
+ * Compared with gtk_canvas_item_get_bounds(), this function returns the actual
+ * box used to allocate the widget, which may be different from the bounds
+ * to conform to its size requirements.
+ *
+ * Returns: (transfer none) (nullable): The allocation
+ */
+const GtkCanvasBox *
+gtk_canvas_item_get_allocation (GtkCanvasItem *self)
+{
+ g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+
+ if (!self->has_allocation)
+ return NULL;
+
+ return &self->allocation;
+}
+
/**
* gtk_canvas_item_set_widget: (attributes org.gtk.Method.set_property=widget)
* @self: a `GtkCanvasItem`
diff --git a/gtk/gtkcanvasitem.h b/gtk/gtkcanvasitem.h
index 15f3ae7bf4..488656aa2f 100644
--- a/gtk/gtkcanvasitem.h
+++ b/gtk/gtkcanvasitem.h
@@ -35,6 +35,9 @@ 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
@@ -47,10 +50,17 @@ GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_canvas_item_get_widget (GtkCanvasItem *self);
GDK_AVAILABLE_IN_ALL
-void gtk_canvas_item_set_bounds (GtkCanvasItem *self,
- const GtkCanvasBox *box);
+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);
+
GDK_AVAILABLE_IN_ALL
const GtkCanvasBox * gtk_canvas_item_get_bounds (GtkCanvasItem *self);
+GDK_AVAILABLE_IN_ALL
+const GtkCanvasBox * gtk_canvas_item_get_allocation (GtkCanvasItem *self);
G_END_DECLS
diff --git a/gtk/gtkcanvasitemprivate.h b/gtk/gtkcanvasitemprivate.h
index cf1adbfc24..f52377cecd 100644
--- a/gtk/gtkcanvasitemprivate.h
+++ b/gtk/gtkcanvasitemprivate.h
@@ -3,16 +3,14 @@
#include "gtkcanvasitem.h"
-#include "gtkcanvasvectorprivate.h"
-
G_BEGIN_DECLS
GtkCanvasItem * gtk_canvas_item_new (GtkCanvas *canvas,
gpointer item);
-void gtk_canvas_item_validate_variables (GtkCanvasItem *self);
-void gtk_canvas_item_allocate (GtkCanvasItem *self,
- graphene_rect_t *rect);
+void gtk_canvas_item_invalidate_allocation (GtkCanvasItem *self);
+gboolean gtk_canvas_item_allocate (GtkCanvasItem *self,
+ gboolean force);
void gtk_canvas_item_allocate_widget (GtkCanvasItem *self,
float dx,
float dy);
diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h
index da949a6bd9..cbf6045163 100644
--- a/gtk/gtktypes.h
+++ b/gtk/gtktypes.h
@@ -40,7 +40,6 @@ typedef struct _GtkBuilderScope GtkBuilderScope;
typedef struct _GtkCanvas GtkCanvas;
typedef struct _GtkCanvasBox GtkCanvasBox;
typedef struct _GtkCanvasItem GtkCanvasItem;
-typedef struct _GtkCanvasVector GtkCanvasVector;
typedef struct _GtkCssStyleChange GtkCssStyleChange;
typedef struct _GtkEventController GtkEventController;
typedef struct _GtkGesture GtkGesture;
diff --git a/gtk/meson.build b/gtk/meson.build
index 594808de9e..35b2774400 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -32,7 +32,6 @@ gtk_private_sources = files([
'gtkbuilderprecompile.c',
'gtkbuiltinicon.c',
'gtkcellareaboxcontext.c',
- 'gtkcanvasvectorimpl.c',
'gtkcoloreditor.c',
'gtkcolorplane.c',
'gtkcolorpicker.c',
@@ -186,7 +185,6 @@ gtk_public_sources = files([
'gtkcanvas.c',
'gtkcanvasbox.c',
'gtkcanvasitem.c',
- 'gtkcanvasvector.c',
'gtkcellarea.c',
'gtkcellareabox.c',
'gtkcellareacontext.c',
@@ -481,7 +479,6 @@ gtk_public_headers = files([
'gtkcanvas.h',
'gtkcanvasbox.h',
'gtkcanvasitem.h',
- 'gtkcanvasvector.h',
'gtkcenterbox.h',
'gtkcenterlayout.h',
'gtkcellarea.h',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]