[gtk/wip/otte/canvas: 26/36] canvas: Add variables to canvasitems
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/canvas: 26/36] canvas: Add variables to canvasitems
- Date: Tue, 5 Jul 2022 05:41:42 +0000 (UTC)
commit e848ead629fa52d47815d09905cbbaa98885ee86
Author: Benjamin Otte <otte redhat com>
Date: Sun Jul 3 05:30:20 2022 +0200
canvas: Add variables to canvasitems
This allows referencing the actual allocation as well as the bounds.
gtk/gtkcanvas.c | 114 ++++++++++++++++++++++++++++++++-------------
gtk/gtkcanvasbox.c | 17 +++++++
gtk/gtkcanvasbox.h | 5 ++
gtk/gtkcanvasboxprivate.h | 4 ++
gtk/gtkcanvasitem.c | 54 ++++++++++++++++++++-
gtk/gtkcanvasitemprivate.h | 4 ++
gtk/gtkcanvasvec2.c | 6 +++
gtk/gtkcanvasvec2private.h | 6 ++-
8 files changed, 174 insertions(+), 36 deletions(-)
---
diff --git a/gtk/gtkcanvas.c b/gtk/gtkcanvas.c
index a1aef6f566..33a8a4973d 100644
--- a/gtk/gtkcanvas.c
+++ b/gtk/gtkcanvas.c
@@ -238,54 +238,104 @@ gtk_canvas_allocate (GtkWidget *widget,
int baseline)
{
GtkCanvas *self = GTK_CANVAS (widget);
+ gboolean missing, force, success;
gsize i;
gtk_canvas_validate_variables (self);
gtk_canvas_vec2_init_constant (gtk_canvas_vec2_get_variable (&self->viewport_size), width, height);
+ force = FALSE;
+ do
+ {
+ /* Try to allocate items in a loop */
+ success = FALSE;
+ missing = FALSE;
+
+ 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;
+ float origin_x, origin_y;
+ graphene_rect_t rect;
+ int x, y, w, h;
+
+ if (child == NULL || gtk_canvas_item_has_allocation (ci, NULL))
+ 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 (rect.size.width));
+ gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL);
+ h = MAX (h, ceil (rect.size.height));
+ }
+ else
+ {
+ gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL);
+ h = MAX (h, ceil (rect.size.height));
+ gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL);
+ w = MAX (w, ceil (rect.size.width));
+ }
+
+ gtk_canvas_box_get_origin (bounds, &origin_x, &origin_y);
+ if (w > rect.size.width)
+ x = round (rect.origin.x + origin_x * (rect.size.width - w));
+ else
+ x = round (rect.origin.x);
+ if (h > rect.size.height)
+ y = round (rect.origin.y + origin_y * (rect.size.height - h));
+ else
+ y = round (rect.origin.y);
+
+ gtk_canvas_item_allocate (ci, &GRAPHENE_RECT_INIT (x, y, w, h));
+ success = TRUE;
+ }
+ if (!success)
+ {
+ /* We didn't allocate a single widget in this loop, do something! */
+ g_warning ("Could not allocate all Canvas items");
+ force = TRUE;
+ }
+ }
+ while (missing);
+
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;
- float origin_x, origin_y;
- graphene_rect_t rect;
- int x, y, w, h;
+ graphene_rect_t allocation;
if (child == NULL)
continue;
- bounds = gtk_canvas_item_get_bounds (ci);
- if (!gtk_canvas_box_eval (bounds, &rect))
- rect = *graphene_rect_zero ();
-
- if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+ if (!gtk_canvas_item_has_allocation (ci, &allocation))
{
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL);
- w = MAX (w, ceil (rect.size.width));
- gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL);
- h = MAX (h, ceil (rect.size.height));
+ g_assert_not_reached ();
}
- else
- {
- gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL);
- h = MAX (h, ceil (rect.size.height));
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL);
- w = MAX (w, ceil (rect.size.width));
- }
-
- gtk_canvas_box_get_origin (bounds, &origin_x, &origin_y);
- if (w > rect.size.width)
- x = round (rect.origin.x + origin_x * (rect.size.width - w));
- else
- x = round (rect.origin.x);
- if (h > rect.size.height)
- y = round (rect.origin.y + origin_y * (rect.size.height - h));
- else
- y = round (rect.origin.y);
-
- gtk_widget_size_allocate (child, &(GtkAllocation) { x, y, w, h }, -1);
+ gtk_widget_size_allocate (child,
+ &(GtkAllocation) {
+ allocation.origin.x,
+ allocation.origin.y,
+ allocation.size.width,
+ allocation.size.height
+ }, -1);
}
}
diff --git a/gtk/gtkcanvasbox.c b/gtk/gtkcanvasbox.c
index 52dac1f7cc..774be46110 100644
--- a/gtk/gtkcanvasbox.c
+++ b/gtk/gtkcanvasbox.c
@@ -62,6 +62,23 @@ gtk_canvas_box_finish (GtkCanvasBox *self)
gtk_canvas_vec2_finish (&self->size);
}
+void
+gtk_canvas_box_init_variable (GtkCanvasBox *self)
+{
+ gtk_canvas_vec2_init_variable (&self->point);
+ gtk_canvas_vec2_init_variable (&self->size);
+ graphene_vec2_init (&self->origin, 0, 0);
+}
+
+void
+gtk_canvas_box_update_variable (GtkCanvasBox *self,
+ const GtkCanvasBox *other)
+{
+ gtk_canvas_vec2_init_copy (gtk_canvas_vec2_get_variable (&self->point), &other->point);
+ gtk_canvas_vec2_init_copy (gtk_canvas_vec2_get_variable (&self->size), &other->size);
+ graphene_vec2_init_from_vec2 (&self->origin, &other->origin);
+}
+
/**
* gtk_canvas_box_new_points:
* @point1: the first point
diff --git a/gtk/gtkcanvasbox.h b/gtk/gtkcanvasbox.h
index 0fede6dcca..4bbfde583a 100644
--- a/gtk/gtkcanvasbox.h
+++ b/gtk/gtkcanvasbox.h
@@ -62,6 +62,11 @@ GDK_AVAILABLE_IN_ALL
GtkCanvasBox * gtk_canvas_box_new_points (const GtkCanvasPoint *point1,
const GtkCanvasPoint *point2);
+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);
+
G_END_DECLS
#endif /* __GTK_BOX_H__ */
diff --git a/gtk/gtkcanvasboxprivate.h b/gtk/gtkcanvasboxprivate.h
index 99e7e7f084..0660f8761f 100644
--- a/gtk/gtkcanvasboxprivate.h
+++ b/gtk/gtkcanvasboxprivate.h
@@ -23,6 +23,10 @@ void gtk_canvas_box_init_copy (GtkCanvasBox
const GtkCanvasBox *source);
void gtk_canvas_box_finish (GtkCanvasBox *self);
+void gtk_canvas_box_init_variable (GtkCanvasBox *self);
+void gtk_canvas_box_update_variable (GtkCanvasBox *self,
+ const GtkCanvasBox *other);
+
G_END_DECLS
#endif /* __GTK_CANVAS_BOX_PRIVATE_H__ */
diff --git a/gtk/gtkcanvasitem.c b/gtk/gtkcanvasitem.c
index b5def0b8ba..d911c66095 100644
--- a/gtk/gtkcanvasitem.c
+++ b/gtk/gtkcanvasitem.c
@@ -42,6 +42,8 @@ struct _GtkCanvasItem
gpointer item;
GtkWidget *widget;
GtkCanvasBox bounds;
+ GtkCanvasBox bounds_var;
+ GtkCanvasBox allocation_var;
GtkCanvasVec2 size_vecs[4];
};
@@ -72,8 +74,6 @@ gtk_canvas_item_dispose (GObject *object)
g_assert (self->item == NULL);
g_assert (self->widget == NULL);
- gtk_canvas_box_finish (&self->bounds);
-
G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
}
@@ -86,6 +86,10 @@ gtk_canvas_item_finalize (GObject *object)
for (i = 0; i < 4; i++)
gtk_canvas_vec2_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);
}
@@ -209,6 +213,9 @@ gtk_canvas_item_init (GtkCanvasItem *self)
gtk_canvas_vec2_init_constant (&self->bounds.point, 0, 0);
gtk_canvas_vec2_init_copy (&self->bounds.size, &self->size_vecs[GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT]);
graphene_vec2_init (&self->bounds.origin, 0, 0);
+ gtk_canvas_box_init_variable (&self->bounds_var);
+ gtk_canvas_box_update_variable (&self->bounds_var, &self->bounds);
+ gtk_canvas_box_init_variable (&self->allocation_var);
}
GtkCanvasItem *
@@ -264,6 +271,35 @@ gtk_canvas_item_validate_variables (GtkCanvasItem *self)
gtk_canvas_vec2_get_variable (&self->size_vecs[i]),
0, 0);
}
+
+ gtk_canvas_vec2_init_invalid (
+ gtk_canvas_vec2_get_variable (&self->allocation_var.point));
+ gtk_canvas_vec2_init_invalid (
+ gtk_canvas_vec2_get_variable (&self->allocation_var.size));
+}
+
+void
+gtk_canvas_item_allocate (GtkCanvasItem *self,
+ graphene_rect_t *rect)
+{
+ gtk_canvas_vec2_init_constant (
+ gtk_canvas_vec2_get_variable (&self->allocation_var.point),
+ rect->origin.x + graphene_vec2_get_x (&self->bounds.origin) * rect->size.width,
+ rect->origin.y + graphene_vec2_get_y (&self->bounds.origin) * rect->size.height);
+ gtk_canvas_vec2_init_constant (
+ gtk_canvas_vec2_get_variable (&self->allocation_var.size),
+ rect->size.width, rect->size.height);
+ graphene_vec2_init_from_vec2 (&self->allocation_var.origin, &self->bounds.origin);
+}
+
+gboolean
+gtk_canvas_item_has_allocation (GtkCanvasItem *self,
+ graphene_rect_t *rect)
+{
+ if (rect == NULL)
+ return !gtk_canvas_vec2_is_invalid (gtk_canvas_vec2_get_variable (&self->allocation_var.point));
+
+ return gtk_canvas_box_eval (&self->allocation_var, rect);
}
const GtkCanvasVec2 *
@@ -273,6 +309,18 @@ gtk_canvas_item_get_measure_vec2 (GtkCanvasItem *self,
return &self->size_vecs[measure];
}
+const GtkCanvasBox *
+gtk_canvas_box_get_item_bounds (GtkCanvasItem *item)
+{
+ return &item->bounds_var;
+}
+
+const GtkCanvasBox *
+gtk_canvas_box_get_item_allocation (GtkCanvasItem *item)
+{
+ return &item->allocation_var;
+}
+
/**
* gtk_canvas_item_get_canvas: (attributes org.gtk.Method.get_property=canvas)
* @self: a `GtkCanvasItem`
@@ -323,6 +371,8 @@ gtk_canvas_item_set_bounds (GtkCanvasItem *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->canvas)
gtk_widget_queue_allocate (GTK_WIDGET (self->canvas));
diff --git a/gtk/gtkcanvasitemprivate.h b/gtk/gtkcanvasitemprivate.h
index 49724204ff..d50c68a569 100644
--- a/gtk/gtkcanvasitemprivate.h
+++ b/gtk/gtkcanvasitemprivate.h
@@ -12,6 +12,10 @@ GtkCanvasItem * gtk_canvas_item_new (GtkCanvas
gpointer item);
void gtk_canvas_item_validate_variables (GtkCanvasItem *self);
+void gtk_canvas_item_allocate (GtkCanvasItem *self,
+ graphene_rect_t *rect);
+gboolean gtk_canvas_item_has_allocation (GtkCanvasItem *self,
+ graphene_rect_t *rect);
const GtkCanvasVec2 * gtk_canvas_item_get_measure_vec2 (GtkCanvasItem *self,
GtkCanvasItemMeasurement measure);
diff --git a/gtk/gtkcanvasvec2.c b/gtk/gtkcanvasvec2.c
index dfba1b10b0..5965d3ba30 100644
--- a/gtk/gtkcanvasvec2.c
+++ b/gtk/gtkcanvasvec2.c
@@ -77,6 +77,12 @@ gtk_canvas_vec2_init_invalid (GtkCanvasVec2 *vec2)
vec2->class = >K_CANVAS_VEC2_INVALID_CLASS;
}
+gboolean
+gtk_canvas_vec2_is_invalid (GtkCanvasVec2 *vec2)
+{
+ return vec2->class == >K_CANVAS_VEC2_INVALID_CLASS;
+}
+
/* }}} */
/* {{{ CONSTANT */
diff --git a/gtk/gtkcanvasvec2private.h b/gtk/gtkcanvasvec2private.h
index b8ad4875b8..85470356fc 100644
--- a/gtk/gtkcanvasvec2private.h
+++ b/gtk/gtkcanvasvec2private.h
@@ -91,8 +91,10 @@ void gtk_canvas_vec2_init_sum (GtkCanvasVec2
const graphene_vec2_t *scale,
...) G_GNUC_NULL_TERMINATED;
-void gtk_canvas_vec2_init_variable (GtkCanvasVec2 *vec2);
-GtkCanvasVec2 * gtk_canvas_vec2_get_variable (GtkCanvasVec2 *vec2);
+void gtk_canvas_vec2_init_variable (GtkCanvasVec2 *vec2);
+GtkCanvasVec2 * gtk_canvas_vec2_get_variable (GtkCanvasVec2 *vec2);
+
+gboolean gtk_canvas_vec2_is_invalid (GtkCanvasVec2 *vec2);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]