[libadwaita] squeezer: Add the allow-none property



commit d459e69fd72969392fbda161ea67ce8e623ff6a6
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Fri Jul 23 15:27:20 2021 +0200

    squeezer: Add the allow-none property
    
    This allow squeezing beyond the last child's minimum width, showing no
    child if so.

 src/adw-squeezer.c    | 105 ++++++++++++++++++++++++++++++++++++++++++++------
 src/adw-squeezer.h    |   6 +++
 tests/test-squeezer.c |  19 +++++++++
 3 files changed, 118 insertions(+), 12 deletions(-)
---
diff --git a/src/adw-squeezer.c b/src/adw-squeezer.c
index 92d654b8..d6ece707 100644
--- a/src/adw-squeezer.c
+++ b/src/adw-squeezer.c
@@ -86,6 +86,8 @@ struct _AdwSqueezer
 
   gboolean homogeneous;
 
+  gboolean allow_none;
+
   AdwSqueezerTransitionType transition_type;
   guint transition_duration;
 
@@ -113,6 +115,7 @@ enum  {
   PROP_0,
   PROP_HOMOGENEOUS,
   PROP_VISIBLE_CHILD,
+  PROP_ALLOW_NONE,
   PROP_TRANSITION_DURATION,
   PROP_TRANSITION_TYPE,
   PROP_TRANSITION_RUNNING,
@@ -448,7 +451,7 @@ adw_squeezer_start_transition (AdwSqueezer               *self,
       adw_get_enable_animations (widget) &&
       transition_type != ADW_SQUEEZER_TRANSITION_TYPE_NONE &&
       transition_duration != 0 &&
-      self->last_visible_child != NULL) {
+      (self->last_visible_child != NULL || self->allow_none)) {
     self->active_transition_type = transition_type;
     self->first_frame_skipped = FALSE;
     adw_squeezer_schedule_ticks (self);
@@ -485,7 +488,7 @@ set_visible_child (AdwSqueezer               *self,
     return;
 
   /* If none, pick the first visible. */
-  if (!page) {
+  if (!page && !self->allow_none) {
     GList *l;
 
     for (l = self->children; l; l = l->next) {
@@ -500,7 +503,7 @@ set_visible_child (AdwSqueezer               *self,
   if (page == self->visible_child)
     return;
 
-  if (self->pages) {
+  if (page != NULL && self->pages) {
     guint position;
     GList *l;
 
@@ -698,6 +701,9 @@ adw_squeezer_get_property (GObject    *object,
   case PROP_VISIBLE_CHILD:
     g_value_set_object (value, adw_squeezer_get_visible_child (self));
     break;
+  case PROP_ALLOW_NONE:
+    g_value_set_boolean (value, adw_squeezer_get_allow_none (self));
+    break;
   case PROP_TRANSITION_DURATION:
     g_value_set_uint (value, adw_squeezer_get_transition_duration (self));
     break;
@@ -740,6 +746,9 @@ adw_squeezer_set_property (GObject      *object,
   case PROP_HOMOGENEOUS:
     adw_squeezer_set_homogeneous (self, g_value_get_boolean (value));
     break;
+  case PROP_ALLOW_NONE:
+    adw_squeezer_set_allow_none (self, g_value_get_boolean (value));
+    break;
   case PROP_TRANSITION_DURATION:
     adw_squeezer_set_transition_duration (self, g_value_get_uint (value));
     break;
@@ -827,9 +836,10 @@ adw_squeezer_snapshot_crossfade (GtkWidget   *widget,
 
   gtk_snapshot_pop (snapshot);
 
-  gtk_widget_snapshot_child (widget,
-                             self->visible_child->widget,
-                             snapshot);
+  if (self->visible_child)
+    gtk_widget_snapshot_child (widget,
+                               self->visible_child->widget,
+                               snapshot);
   gtk_snapshot_pop (snapshot);
 }
 
@@ -840,7 +850,7 @@ adw_squeezer_snapshot (GtkWidget   *widget,
 {
   AdwSqueezer *self = ADW_SQUEEZER (widget);
 
-  if (self->visible_child) {
+  if (self->visible_child || self->allow_none) {
     if (gtk_progress_tracker_get_state (&self->tracker) != GTK_PROGRESS_STATE_AFTER) {
       gtk_snapshot_push_clip (snapshot,
                               &GRAPHENE_RECT_INIT(
@@ -860,10 +870,11 @@ adw_squeezer_snapshot (GtkWidget   *widget,
         }
 
       gtk_snapshot_pop (snapshot);
-    } else
+    } else if (self->visible_child) {
       gtk_widget_snapshot_child (widget,
                                  self->visible_child->widget,
                                  snapshot);
+    }
   }
 }
 
@@ -913,6 +924,9 @@ adw_squeezer_size_allocate (GtkWidget *widget,
     }
   }
 
+  if (l == NULL && self->allow_none)
+    page = NULL;
+
   set_visible_child (self, page,
                      self->transition_type,
                      self->transition_duration);
@@ -1003,17 +1017,21 @@ adw_squeezer_measure (GtkWidget      *widget,
     gtk_widget_measure (child, orientation, for_size,
                         &child_min, &child_nat, NULL, NULL);
 
-    if (self->orientation == orientation)
-      min = min == 0 ? child_min : MIN (min, child_min);
-    else
+    if (self->orientation == orientation) {
+      if (self->allow_none)
+        min = 0;
+      else
+        min = min == 0 ? child_min : MIN (min, child_min);
+    } else {
       min = MAX (min, child_min);
+    }
 
     nat = MAX (nat, child_nat);
   }
 
   if (self->orientation != orientation && !self->homogeneous &&
       self->interpolate_size &&
-      self->last_visible_child != NULL) {
+      (self->last_visible_child != NULL || self->allow_none)) {
     double t = gtk_progress_tracker_get_ease_out_cubic (&self->tracker, FALSE);
 
     if (orientation == GTK_ORIENTATION_VERTICAL) {
@@ -1117,6 +1135,24 @@ adw_squeezer_class_init (AdwSqueezerClass *klass)
                          GTK_TYPE_WIDGET,
                          G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * AdwSqueezer:allow-none: (attributes org.gtk.Property.get=adw_squeezer_get_allow_none 
org.gtk.Property.set=adw_squeezer_set_allow_none)
+   *
+   * Whether to allow squeezing beyond the last child's minimum size.
+   *
+   * If set to `TRUE`, the squeezer can shrink to the point where no child can
+   * be shown. This is functionally equivalent to appending a widget with 0x0
+   * minimum size.
+   *
+   * Since: 1.0
+   */
+  props[PROP_ALLOW_NONE] =
+    g_param_spec_boolean ("allow-none",
+                          "Allow none",
+                          "Whether to allow squeezing beyond the last child's minimum size",
+                          FALSE,
+                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
   /**
    * AdwSqueezer:transition-duration: (attributes org.gtk.Property.get=adw_squeezer_get_transition_duration 
org.gtk.Property.set=adw_squeezer_set_transition_duration)
    *
@@ -1488,6 +1524,51 @@ adw_squeezer_set_homogeneous (AdwSqueezer *self,
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HOMOGENEOUS]);
 }
 
+/**
+ * adw_squeezer_get_allow_none: (attributes org.gtk.Method.get_property=allow-none)
+ * @self: a `AdwSqueezer`
+ *
+ * Gets whether to allow squeezing beyond the last child's minimum size.
+ *
+ * Returns: whether @self allows squeezing beyond the last child
+ *
+ * Since: 1.0
+ */
+gboolean
+adw_squeezer_get_allow_none (AdwSqueezer *self)
+{
+  g_return_val_if_fail (ADW_IS_SQUEEZER (self), FALSE);
+
+  return self->allow_none;
+}
+
+/**
+ * adw_squeezer_set_allow_none: (attributes org.gtk.Method.set_property=allow-none)
+ * @self: a `AdwSqueezer`
+ * @allow_none: whether @self allows squeezing beyond the last child
+ *
+ * Sets whether to allow squeezing beyond the last child's minimum size.
+ *
+ * Since: 1.0
+ */
+void
+adw_squeezer_set_allow_none (AdwSqueezer *self,
+                             gboolean     allow_none)
+{
+  g_return_if_fail (ADW_IS_SQUEEZER (self));
+
+  allow_none = !!allow_none;
+
+  if (self->allow_none == allow_none)
+    return;
+
+  self->allow_none = allow_none;
+
+  gtk_widget_queue_resize (GTK_WIDGET (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ALLOW_NONE]);
+}
+
 /**
  * adw_squeezer_get_transition_duration: (attributes org.gtk.Method.get_property=transition-duration)
  * @self: a `AdwSqueezer`
diff --git a/src/adw-squeezer.h b/src/adw-squeezer.h
index edbfd9f4..fb486d6b 100644
--- a/src/adw-squeezer.h
+++ b/src/adw-squeezer.h
@@ -61,6 +61,12 @@ ADW_AVAILABLE_IN_ALL
 void     adw_squeezer_set_homogeneous (AdwSqueezer *self,
                                        gboolean     homogeneous);
 
+ADW_AVAILABLE_IN_ALL
+gboolean adw_squeezer_get_allow_none (AdwSqueezer *self);
+ADW_AVAILABLE_IN_ALL
+void     adw_squeezer_set_allow_none (AdwSqueezer *self,
+                                      gboolean     allow_none);
+
 ADW_AVAILABLE_IN_ALL
 guint adw_squeezer_get_transition_duration (AdwSqueezer *self);
 ADW_AVAILABLE_IN_ALL
diff --git a/tests/test-squeezer.c b/tests/test-squeezer.c
index 32bda716..5996d854 100644
--- a/tests/test-squeezer.c
+++ b/tests/test-squeezer.c
@@ -25,6 +25,24 @@ test_adw_squeezer_homogeneous (void)
 }
 
 
+static void
+test_adw_squeezer_allow_none (void)
+{
+  g_autoptr (AdwSqueezer) squeezer = NULL;
+
+  squeezer = g_object_ref_sink (ADW_SQUEEZER (adw_squeezer_new ()));
+  g_assert_nonnull (squeezer);
+
+  g_assert_true (adw_squeezer_get_allow_none (squeezer));
+
+  adw_squeezer_set_allow_none (squeezer, FALSE);
+  g_assert_false (adw_squeezer_get_allow_none (squeezer));
+
+  adw_squeezer_set_allow_none (squeezer, TRUE);
+  g_assert_true (adw_squeezer_get_allow_none (squeezer));
+}
+
+
 static void
 test_adw_squeezer_transition_duration (void)
 {
@@ -147,6 +165,7 @@ main (int   argc,
   adw_init ();
 
   g_test_add_func("/Adwaita/ViewSwitcher/homogeneous", test_adw_squeezer_homogeneous);
+  g_test_add_func("/Adwaita/ViewSwitcher/allow_none", test_adw_squeezer_allow_none);
   g_test_add_func("/Adwaita/ViewSwitcher/transition_duration", test_adw_squeezer_transition_duration);
   g_test_add_func("/Adwaita/ViewSwitcher/transition_type", test_adw_squeezer_transition_type);
   g_test_add_func("/Adwaita/ViewSwitcher/transition_running", test_adw_squeezer_transition_running);


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