[libhandy/wip/haecker-felix/flap-widget] Rewrite allocation
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libhandy/wip/haecker-felix/flap-widget] Rewrite allocation
- Date: Wed, 18 Nov 2020 17:21:04 +0000 (UTC)
commit 71f682842823f9aafaa8663dd837e8739861ac74
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Wed Nov 18 22:20:41 2020 +0500
Rewrite allocation
Support expand
src/hdy-flap.c | 330 ++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 235 insertions(+), 95 deletions(-)
---
diff --git a/src/hdy-flap.c b/src/hdy-flap.c
index c5f7ed66..4a5818de 100644
--- a/src/hdy-flap.c
+++ b/src/hdy-flap.c
@@ -200,25 +200,6 @@ animate_reveal (HdyFlap *self,
hdy_animation_start (self->reveal_animation);
}
-static void
-set_folded (HdyFlap *self,
- gboolean folded)
-{
- folded = !!folded;
-
- if (self->folded == folded)
- return;
-
- self->folded = folded;
-
- animate_fold (self);
-
- if (!self->locked)
- hdy_flap_set_reveal_flap (self, !self->folded);
-
- g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FOLDED]);
-}
-
static void
set_reveal_flap (HdyFlap *self,
gboolean reveal_flap,
@@ -242,6 +223,27 @@ set_reveal_flap (HdyFlap *self,
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REVEAL_FLAP]);
}
+static void
+set_folded (HdyFlap *self,
+ gboolean folded)
+{
+ folded = !!folded;
+
+ if (self->folded == folded)
+ return;
+
+ self->folded = folded;
+
+ gtk_widget_queue_allocate (GTK_WIDGET (self));
+
+ animate_fold (self);
+
+ if (!self->locked)
+ set_reveal_flap (self, !self->folded, self->fold_duration, TRUE);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_FOLDED]);
+}
+
static gint
adjust_for_overlay (HdyFlap *self,
gint value)
@@ -294,106 +296,237 @@ get_start_or_end (HdyFlap *self)
return is_rtl ? GTK_PACK_END : GTK_PACK_START;
}
-static gint
-get_flap_size (HdyFlap *self,
- GtkAllocation *alloc,
- GtkOrientation orientation)
+static inline void
+get_preferred_size (GtkWidget *widget,
+ GtkOrientation orientation,
+ gint *min,
+ gint *nat)
{
- GtkRequisition flap_min_size, flap_nat_size;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_widget_get_preferred_width (widget, min, nat);
+ else
+ gtk_widget_get_preferred_height (widget, min, nat);
+}
- if (!self->flap)
- return 0;
+static void
+compute_sizes (HdyFlap *self,
+ GtkAllocation *alloc,
+ gboolean folded,
+ gboolean revealed,
+ gint *flap_size,
+ gint *content_size)
+{
+ gboolean flap_expand, content_expand;
+ gint total, extra;
+ gint flap_nat, content_nat;
- gtk_widget_get_preferred_size (self->flap, &flap_min_size, &flap_nat_size);
+ if (!self->flap && !self->content)
+ return;
- if (orientation == GTK_ORIENTATION_HORIZONTAL) {
- if (self->orientation == orientation)
- return flap_min_size.width;
+ if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
+ total = alloc->width;
+ else
+ total = alloc->height;
- return alloc->width;
- } else {
- if (self->orientation == orientation)
- return flap_min_size.height;
+ if (!self->flap) {
+ *content_size = total;
+ *flap_size = 0;
- return alloc->height;
+ return;
}
-}
-static void
-allocate_flap (HdyFlap *self,
- GtkAllocation *alloc)
-{
- GtkAllocation flap_alloc;
- gint flap_size = get_flap_size (self, alloc, self->orientation);
-
- if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
- flap_alloc.y = 0;
- flap_alloc.height = alloc->height;
- flap_alloc.width = flap_size;
+ if (!revealed || folded) {
+ gboolean expand = gtk_widget_compute_expand (self->flap, self->orientation);
+ gint min;
- if (self->flap_position == get_start_or_end (self))
- flap_alloc.x = (gint) round (flap_size * self->reveal_progress) - flap_size;
+ if (expand)
+ *flap_size = total;
+ else if (revealed)
+ get_preferred_size (self->flap, self->orientation, NULL, flap_size);
else
- flap_alloc.x = alloc->width - (gint) round (flap_size * self->reveal_progress);
+ get_preferred_size (self->flap, self->orientation, flap_size, NULL);
- } else {
- flap_alloc.x = 0;
- flap_alloc.width = alloc->width;
- flap_alloc.height = flap_size;
+ *flap_size = MIN (*flap_size, total);
+ *content_size = total;
- if (self->flap_position == GTK_PACK_START)
- flap_alloc.y = (gint) round (flap_size * self->reveal_progress) - flap_size;
- else
- flap_alloc.y = alloc->height - (gint) round (flap_size * self->reveal_progress);
+ return;
}
- gtk_widget_set_child_visible (self->flap, self->reveal_progress > 0);
+ if (!self->content) {
+ *content_size = 0;
+ *flap_size = total;
- if (self->reveal_progress > 0)
- gtk_widget_size_allocate (self->flap, &flap_alloc);
-}
+ return;
+ }
-static void
-allocate_content (HdyFlap *self,
- GtkAllocation *alloc)
-{
- GtkRequisition content_min;
- GtkAllocation content_alloc;
- gint flap_size;
- gint offset;
+ get_preferred_size (self->flap, self->orientation, flap_size, &flap_nat);
+ get_preferred_size (self->content, self->orientation, content_size, &content_nat);
- if (!self->flap) {
- gtk_widget_size_allocate (self->content, alloc);
+ flap_expand = gtk_widget_compute_expand (self->flap, self->orientation);
+ content_expand = gtk_widget_compute_expand (self->content, self->orientation);
+
+ if (flap_expand && content_expand) {
+ *flap_size = MAX (total / 2, *flap_size);
+ *content_size = total - *flap_size;
return;
}
- gtk_widget_get_preferred_size (self->content, &content_min, NULL);
+ extra = total - *content_size - *flap_size;
+
+ if (flap_expand) {
+ *flap_size += extra;
+
+ return;
+ }
+
+ if (content_expand) {
+ *content_size += extra;
+
+ return;
+ }
- flap_size = get_flap_size (self, alloc, self->orientation);
- offset = adjust_for_overlay (self, flap_size);
+ if (extra > 0) {
+ GtkRequestedSize sizes[2];
+
+ sizes[0].data = self->flap;
+ sizes[0].minimum_size = *flap_size;
+ sizes[0].natural_size = flap_nat;
+
+ sizes[1].data = self->content;
+ sizes[1].minimum_size = *content_size;
+ sizes[1].natural_size = content_nat;
+
+ extra = gtk_distribute_natural_allocation (extra, 2, sizes);
+
+ *flap_size = sizes[0].minimum_size;
+ *content_size = sizes[1].minimum_size + extra;
+ }
+}
+
+static void
+compute_allocation (HdyFlap *self,
+ GtkAllocation *alloc,
+ gboolean folded,
+ gboolean revealed,
+ GtkAllocation *flap_alloc,
+ GtkAllocation *content_alloc)
+{
+ if (!self->flap && !self->content)
+ return;
+
+ content_alloc->x = 0;
+ content_alloc->y = 0;
+ flap_alloc->x = 0;
+ flap_alloc->y = 0;
if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
- content_alloc.y = 0;
- content_alloc.height = alloc->height;
- content_alloc.width = MAX (alloc->width - offset, content_min.width);
+ compute_sizes (self, alloc, folded, revealed,
+ &flap_alloc->width, &content_alloc->width);
+ flap_alloc->height = content_alloc->height = alloc->height;
+ } else {
+ compute_sizes (self, alloc, folded, revealed,
+ &flap_alloc->height, &content_alloc->height);
+ flap_alloc->width = content_alloc->width = alloc->width;
+ }
- if (self->flap_position == get_start_or_end (self))
- content_alloc.x = alloc->width - content_alloc.width;
- else
- content_alloc.x = 0;
+ if (!self->flap)
+ return;
+
+ if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
+ if (self->flap_position == get_start_or_end (self)) {
+ if (!folded && revealed)
+ content_alloc->x = flap_alloc->width;
+ else if (!revealed)
+ flap_alloc->x = -flap_alloc->width;
+ } else {
+ if (!revealed)
+ flap_alloc->x = alloc->width;
+ else if (folded)
+ flap_alloc->x = alloc->width - flap_alloc->width;
+ else
+ flap_alloc->x = content_alloc->width;
+ }
} else {
- content_alloc.x = 0;
- content_alloc.width = alloc->width;
- content_alloc.height = MAX (alloc->height - offset, content_min.height);
+ if (self->flap_position == GTK_PACK_START) {
+ if (!folded && revealed)
+ content_alloc->y = flap_alloc->height;
+ else if (!revealed)
+ flap_alloc->y = -flap_alloc->height;
+ } else {
+ if (!revealed)
+ flap_alloc->y = alloc->height;
+ else if (folded)
+ flap_alloc->y = alloc->height - flap_alloc->height;
+ else
+ flap_alloc->y = content_alloc->height;
+ }
+ }
+}
- if (self->flap_position == GTK_PACK_START)
- content_alloc.y = alloc->height - content_alloc.height;
- else
- content_alloc.y = 0;
+static inline void
+interpolate_allocation (GtkAllocation *from,
+ GtkAllocation *to,
+ gdouble t,
+ GtkAllocation *ret)
+{
+ ret->x = (gint) round (hdy_lerp (from->x, to->x, t));
+ ret->y = (gint) round (hdy_lerp (from->y, to->y, t));
+ ret->width = (gint) round (hdy_lerp (from->width, to->width, t));
+ ret->height = (gint) round (hdy_lerp (from->height, to->height, t));
+}
+
+static inline void
+interpolate_reveal (HdyFlap *self,
+ GtkAllocation *alloc,
+ gboolean folded,
+ GtkAllocation *flap_alloc,
+ GtkAllocation *content_alloc)
+{
+ if (self->reveal_progress <= 0) {
+ compute_allocation (self, alloc, folded, FALSE,
+ flap_alloc, content_alloc);
+ } else if (self->reveal_progress >= 1) {
+ compute_allocation (self, alloc, folded, TRUE,
+ flap_alloc, content_alloc);
+ } else {
+ GtkAllocation flap_revealed, content_revealed;
+ GtkAllocation flap_hidden, content_hidden;
+
+ compute_allocation (self, alloc, folded, TRUE,
+ &flap_revealed, &content_revealed);
+ compute_allocation (self, alloc, folded, FALSE,
+ &flap_hidden, &content_hidden);
+
+ interpolate_allocation (&flap_hidden, &flap_revealed,
+ self->reveal_progress, flap_alloc);
+ interpolate_allocation (&content_hidden, &content_revealed,
+ self->reveal_progress, content_alloc);
}
+}
+
+static inline void
+interpolate_fold (HdyFlap *self,
+ GtkAllocation *alloc,
+ GtkAllocation *flap_alloc,
+ GtkAllocation *content_alloc)
+{
+ if (self->fold_progress <= 0) {
+ interpolate_reveal (self, alloc, FALSE, flap_alloc, content_alloc);
+ } else if (self->fold_progress >= 1) {
+ interpolate_reveal (self, alloc, TRUE, flap_alloc, content_alloc);
+ } else {
+ GtkAllocation flap_folded, content_folded;
+ GtkAllocation flap_unfolded, content_unfolded;
- gtk_widget_size_allocate (self->content, &content_alloc);
+ interpolate_reveal (self, alloc, TRUE, &flap_folded, &content_folded);
+ interpolate_reveal (self, alloc, FALSE, &flap_unfolded, &content_unfolded);
+
+ interpolate_allocation (&flap_unfolded, &flap_folded,
+ self->fold_progress, flap_alloc);
+ interpolate_allocation (&content_unfolded, &content_folded,
+ self->fold_progress, content_alloc);
+ }
}
static void
@@ -401,6 +534,7 @@ hdy_flap_size_allocate (GtkWidget *widget,
GtkAllocation *alloc)
{
HdyFlap *self = HDY_FLAP (widget);
+ GtkAllocation flap_alloc, content_alloc;
gtk_widget_set_allocation (widget, alloc);
@@ -415,16 +549,22 @@ hdy_flap_size_allocate (GtkWidget *widget,
gtk_widget_get_preferred_size (self->content, &content_min, NULL);
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
- set_folded (self, alloc->width <= content_min.width + flap_min.width);
+ set_folded (self, alloc->width < content_min.width + flap_min.width);
else
- set_folded (self, alloc->height <= content_min.height + flap_min.height);
+ set_folded (self, alloc->height < content_min.height + flap_min.height);
}
+ interpolate_fold (self, alloc, &flap_alloc, &content_alloc);
+
if (self->content)
- allocate_content (self, alloc);
+ gtk_widget_size_allocate (self->content, &content_alloc);
- if (self->flap)
- allocate_flap (self, alloc);
+ if (self->flap) {
+ gtk_widget_set_child_visible (self->flap, self->reveal_progress > 0);
+
+ if (self->reveal_progress > 0)
+ gtk_widget_size_allocate (self->flap, &flap_alloc);
+ }
gtk_widget_set_clip (widget, alloc);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]