[libhandy/wip/haecker-felix/flap-widget] Transition types



commit af5dbfd9c39b34f0e53bb56a302bb0777bc708e0
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Thu Nov 19 17:21:59 2020 +0500

    Transition types

 debian/libhandy-1-0.symbols |   2 +
 src/hdy-flap.c              | 258 ++++++++++++++++++++++++++++++++++++--------
 src/hdy-flap.h              |  12 +++
 3 files changed, 229 insertions(+), 43 deletions(-)
---
diff --git a/debian/libhandy-1-0.symbols b/debian/libhandy-1-0.symbols
index 719ab553..db0ba268 100644
--- a/debian/libhandy-1-0.symbols
+++ b/debian/libhandy-1-0.symbols
@@ -129,6 +129,7 @@ libhandy-1.so.0 libhandy-1-0 #MINVER#
  hdy_flap_get_locked@LIBHANDY_1_0 1.1.0
  hdy_flap_get_reveal_duration@LIBHANDY_1_0 1.1.0
  hdy_flap_get_reveal_flap@LIBHANDY_1_0 1.1.0
+ hdy_flap_get_transition_type@LIBHANDY_1_0 1.1.0
  hdy_flap_get_type@LIBHANDY_1_0 1.1.0
  hdy_flap_new@LIBHANDY_1_0 1.1.0
  hdy_flap_set_flap@LIBHANDY_1_0 1.1.0
@@ -138,6 +139,7 @@ libhandy-1.so.0 libhandy-1-0 #MINVER#
  hdy_flap_set_locked@LIBHANDY_1_0 1.1.0
  hdy_flap_set_reveal_duration@LIBHANDY_1_0 1.1.0
  hdy_flap_set_reveal_flap@LIBHANDY_1_0 1.1.0
+ hdy_flap_set_transition_type@LIBHANDY_1_0 1.1.0
  hdy_get_enable_animations@LIBHANDY_1_0 0.0.11
  hdy_header_bar_get_centering_policy@LIBHANDY_1_0 0.0.10
  hdy_header_bar_get_custom_title@LIBHANDY_1_0 0.0.10
diff --git a/src/hdy-flap.c b/src/hdy-flap.c
index 246b1c49..c16b91a2 100644
--- a/src/hdy-flap.c
+++ b/src/hdy-flap.c
@@ -33,9 +33,19 @@
  * in a #HdyFlap widget.
  */
 
+/**
+ * HdyFlapTransitionType:
+ * @HDY_FLAP_TRANSITION_TYPE_OVER: No transition
+ * @HDY_FLAP_TRANSITION_TYPE_UNDER: A cross-fade
+ * @HDY_FLAP_TRANSITION_TYPE_SLIDE: TBD
+ *
+ * These enumeration values describe the possible transitions between children
+ * in a #HdyFlap widget.
+ *
+ * New values may be added to this enum over time.
+ */
+
 #define HDY_SWIPE_BORDER 16
-#define FLAP_MOTION_FACTOR 1.0
-#define CONTENT_MOTION_FACTOR 0.0
 
 struct _HdyFlap
 {
@@ -51,6 +61,7 @@ struct _HdyFlap
   GtkAllocation content_allocation;
 
   HdyFlapFoldPolicy fold_policy;
+  HdyFlapTransitionType transition_type;
   GtkPackType flap_position;
   gboolean reveal_flap;
   gboolean locked;
@@ -84,7 +95,6 @@ G_DEFINE_TYPE_WITH_CODE (HdyFlap, hdy_flap, GTK_TYPE_CONTAINER,
 
 enum {
   PROP_0,
-
   PROP_FLAP,
   PROP_FOLD_POLICY,
   PROP_FLAP_POSITION,
@@ -93,11 +103,12 @@ enum {
   PROP_FOLDED,
   PROP_FOLD_DURATION,
   PROP_REVEAL_DURATION,
+  PROP_TRANSITION_TYPE,
 
   /* Overridden properties */
   PROP_ORIENTATION,
 
-  LAST_PROP = PROP_REVEAL_DURATION + 1,
+  LAST_PROP = PROP_ORIENTATION,
 };
 
 static GParamSpec *props[LAST_PROP];
@@ -355,14 +366,67 @@ unregister_window (HdyFlap    *self,
   *window = NULL;
 }
 
+static gboolean
+transition_is_content_above_flap (HdyFlap *self)
+{
+  switch (self->transition_type) {
+  case HDY_FLAP_TRANSITION_TYPE_OVER:
+  case HDY_FLAP_TRANSITION_TYPE_SLIDE:
+    return FALSE;
+
+  case HDY_FLAP_TRANSITION_TYPE_UNDER:
+    return TRUE;
+
+  default:
+    g_assert_not_reached ();
+  }
+}
+
+static gdouble
+transition_get_content_motion_factor (HdyFlap *self)
+{
+  switch (self->transition_type) {
+  case HDY_FLAP_TRANSITION_TYPE_OVER:
+    return 0;
+
+  case HDY_FLAP_TRANSITION_TYPE_SLIDE:
+  case HDY_FLAP_TRANSITION_TYPE_UNDER:
+    return 1;
+
+  default:
+    g_assert_not_reached ();
+  }
+}
+
+static gdouble
+transition_get_flap_motion_factor (HdyFlap *self)
+{
+  switch (self->transition_type) {
+  case HDY_FLAP_TRANSITION_TYPE_OVER:
+  case HDY_FLAP_TRANSITION_TYPE_SLIDE:
+    return 1;
+
+  case HDY_FLAP_TRANSITION_TYPE_UNDER:
+    return 0;
+
+  default:
+    g_assert_not_reached ();
+  }
+}
+
 static void
 restack_windows (HdyFlap *self)
 {
-  if (self->content_window)
+  gboolean content_above_flap = transition_is_content_above_flap (self);
+
+  if (self->content_window && !content_above_flap)
     gdk_window_raise (self->content_window);
 
   if (self->flap_window)
     gdk_window_raise (self->flap_window);
+
+  if (self->content_window && content_above_flap)
+    gdk_window_raise (self->content_window);
 }
 
 static inline GtkPackType
@@ -569,8 +633,8 @@ compute_allocation (HdyFlap       *self,
     return;
 
   if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
-    content_offset = (gint) round (MIN (self->fold_progress, self->reveal_progress) * CONTENT_MOTION_FACTOR 
* flap_alloc->width);
-    flap_offset = (gint) round ((self->reveal_progress - 1) * FLAP_MOTION_FACTOR * flap_alloc->width);
+    content_offset = (gint) round (MIN (self->fold_progress, self->reveal_progress) * 
transition_get_content_motion_factor (self) * flap_alloc->width);
+    flap_offset = (gint) round ((self->reveal_progress - 1) * transition_get_flap_motion_factor (self) * 
flap_alloc->width);
 
     if (self->flap_position == get_start_or_end (self)) {
       content_alloc->x = alloc->width - content_alloc->width + content_offset;
@@ -580,8 +644,8 @@ compute_allocation (HdyFlap       *self,
       flap_alloc->x = alloc->width - flap_alloc->width - flap_offset;
     }
   } else {
-    content_offset = (gint) round (MIN (self->fold_progress, self->reveal_progress) * CONTENT_MOTION_FACTOR 
* flap_alloc->height);
-    flap_offset = (gint) round ((self->reveal_progress - 1) * FLAP_MOTION_FACTOR * flap_alloc->height);
+    content_offset = (gint) round (MIN (self->fold_progress, self->reveal_progress) * 
transition_get_content_motion_factor (self) * flap_alloc->height);
+    flap_offset = (gint) round ((self->reveal_progress - 1) * transition_get_flap_motion_factor (self) * 
flap_alloc->height);
 
     if (self->flap_position == GTK_PACK_START) {
       content_alloc->y = alloc->height - content_alloc->height + content_offset;
@@ -763,39 +827,68 @@ hdy_flap_draw (GtkWidget *widget,
   gint shadow_x = 0, shadow_y = 0;
   gdouble progress;
   GtkPanDirection shadow_direction;
+  gboolean content_above_flap = transition_is_content_above_flap (self);
+  GtkAllocation *shadow_alloc;
+
+  if (self->content && !content_above_flap)
+    gtk_container_propagate_draw (GTK_CONTAINER (self),
+                                  self->content,
+                                  cr);
+
+  if (self->flap)
+    gtk_container_propagate_draw (GTK_CONTAINER (self),
+                                  self->flap,
+                                  cr);
+
+  if (self->content && content_above_flap)
+    gtk_container_propagate_draw (GTK_CONTAINER (self),
+                                  self->content,
+                                  cr);
+
+  if (!self->flap)
+    return GDK_EVENT_PROPAGATE;
+
+  shadow_alloc = content_above_flap ? &self->content_allocation : &self->flap_allocation;
 
   width = gtk_widget_get_allocated_width (widget);
   height = gtk_widget_get_allocated_height (widget);
 
   if (self->orientation == GTK_ORIENTATION_VERTICAL) {
-    if (self->flap_position == GTK_PACK_START) {
+    if ((self->flap_position == GTK_PACK_START) != content_above_flap) {
       shadow_direction = GTK_PAN_DIRECTION_UP;
-      shadow_y = self->flap_allocation.y + self->flap_allocation.height;
+      shadow_y = shadow_alloc->y + shadow_alloc->height;
     } else {
       shadow_direction = GTK_PAN_DIRECTION_DOWN;
-      shadow_y = self->flap_allocation.y - height;
+      shadow_y = shadow_alloc->y - height;
     }
   } else {
-    if (self->flap_position == get_start_or_end (self)) {
+    if ((self->flap_position == get_start_or_end (self)) != content_above_flap) {
       shadow_direction = GTK_PAN_DIRECTION_LEFT;
-      shadow_x = self->flap_allocation.x + self->flap_allocation.width;
+      shadow_x = shadow_alloc->x + shadow_alloc->width;
     } else {
       shadow_direction = GTK_PAN_DIRECTION_RIGHT;
-      shadow_x = self->flap_allocation.x - width;
+      shadow_x = shadow_alloc->x - width;
     }
   }
 
-  gtk_container_propagate_draw (GTK_CONTAINER (self),
-                                self->content,
-                                cr);
+  switch (self->transition_type) {
+  case HDY_FLAP_TRANSITION_TYPE_OVER:
+    progress = 1 - MIN (self->reveal_progress, self->fold_progress);
+    break;
+
+  case HDY_FLAP_TRANSITION_TYPE_UNDER:
+    progress = self->reveal_progress;
+    break;
 
-  gtk_container_propagate_draw (GTK_CONTAINER (self),
-                                self->flap,
-                                cr);
+  case HDY_FLAP_TRANSITION_TYPE_SLIDE:
+    progress = 1;
+    break;
 
-  progress = 1 - MIN (self->reveal_progress, self->fold_progress);
+  default:
+    g_assert_not_reached ();
+  }
 
-  if (progress < 1) {
+  if (progress < 1 && gtk_widget_get_mapped (self->flap)) {
     cairo_save (cr);
     cairo_translate (cr, shadow_x, shadow_y);
     hdy_shadow_helper_draw_shadow (self->shadow_helper, cr, width, height,
@@ -965,6 +1058,9 @@ hdy_flap_get_property (GObject    *object,
   case PROP_REVEAL_DURATION:
     g_value_set_uint (value, hdy_flap_get_reveal_duration (self));
     break;
+  case PROP_TRANSITION_TYPE:
+    g_value_set_enum (value, hdy_flap_get_transition_type (self));
+    break;
   case PROP_ORIENTATION:
     g_value_set_enum (value, self->orientation);
     break;
@@ -1003,6 +1099,9 @@ hdy_flap_set_property (GObject      *object,
   case PROP_REVEAL_DURATION:
     hdy_flap_set_reveal_duration (self, g_value_get_uint (value));
     break;
+  case PROP_TRANSITION_TYPE:
+    hdy_flap_set_transition_type (self, g_value_get_enum (value));
+    break;
   case PROP_ORIENTATION:
     set_orientation (self, g_value_get_enum (value));
     break;
@@ -1147,6 +1246,19 @@ hdy_flap_class_init (HdyFlapClass *klass)
                        250,
                        G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
+  /**
+   * HdyFlap:transition-type:
+   *
+   * Since: 1.1
+   */
+  props[PROP_TRANSITION_TYPE] =
+    g_param_spec_enum ("transition-type",
+                       _("Transition Type"),
+                       _("Transition Type"),
+                       HDY_TYPE_FLAP_TRANSITION_TYPE,
+                       HDY_FLAP_TRANSITION_TYPE_OVER,
+                       G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
   g_object_class_install_properties (object_class, LAST_PROP, props);
 
   g_object_class_override_property (object_class,
@@ -1162,6 +1274,7 @@ hdy_flap_init (HdyFlap *self)
   self->orientation = GTK_ORIENTATION_HORIZONTAL;
   self->flap_position = GTK_PACK_START;
   self->fold_policy = HDY_FLAP_FOLD_POLICY_AUTO;
+  self->transition_type = HDY_FLAP_TRANSITION_TYPE_OVER;
   self->reveal_flap = TRUE;
   self->locked = FALSE;
   self->reveal_progress = 1;
@@ -1271,7 +1384,7 @@ hdy_flap_get_swipe_area (HdySwipeable           *swipeable,
                          GdkRectangle           *rect)
 {
   HdyFlap *self = HDY_FLAP (swipeable);
-  GtkAllocation alloc;
+  GtkAllocation *alloc;
   gint width, height;
 
   if (!self->flap) {
@@ -1286,30 +1399,47 @@ hdy_flap_get_swipe_area (HdySwipeable           *swipeable,
   width = gtk_widget_get_allocated_width (GTK_WIDGET (self));
   height = gtk_widget_get_allocated_height (GTK_WIDGET (self));
 
-  alloc = self->flap_allocation;
+  if (transition_get_flap_motion_factor (self) >=1 &&
+      transition_get_content_motion_factor (self) >= 1) {
+    rect->x = 0;
+    rect->y = 0;
+    rect->width = width;
+    rect->height = height;
+
+    return;
+  }
+
+  alloc = transition_is_content_above_flap (self)
+    ? &self->content_allocation
+    : &self->flap_allocation;
 
   if (self->orientation == GTK_ORIENTATION_HORIZONTAL) {
-    if (self->flap_position == get_start_or_end (self)) {
-      rect->x = 0;
-      rect->width = MAX (alloc.x + alloc.width, HDY_SWIPE_BORDER);
-    } else {
-      rect->x = MIN (alloc.x, width - HDY_SWIPE_BORDER);
-      rect->width = width - rect->x;
-    }
+      if (alloc->x <= 0) {
+        rect->x = 0;
+        rect->width = MAX (alloc->width + alloc->x, HDY_SWIPE_BORDER);
+      } else if (alloc->x + alloc->width >= width) {
+        rect->width = MAX (width - alloc->x, HDY_SWIPE_BORDER);
+        rect->x = width - rect->width;
+      } else {
+        g_assert_not_reached ();
+      }
 
-    rect->y = alloc.y;
-    rect->height = alloc.height;
+    rect->y = alloc->y;
+    rect->height = alloc->height;
   } else {
-    if (self->flap_position == GTK_PACK_START) {
-      rect->y = 0;
-      rect->height = MAX (alloc.y + alloc.height, HDY_SWIPE_BORDER);
-    } else {
-      rect->y = MIN (alloc.y, height - HDY_SWIPE_BORDER);
-      rect->height = height - rect->y;
-    }
+      if (alloc->y <= 0) {
+        rect->y = 0;
+        rect->height = MAX (alloc->height + alloc->y, HDY_SWIPE_BORDER);
+      } else if (alloc->y + alloc->height >= height) {
+        rect->height = MAX (height - alloc->y, HDY_SWIPE_BORDER);
+        rect->y = height - rect->height;
+      } else {
+        g_assert_not_reached ();
+      }
+
 
-    rect->x = alloc.x;
-    rect->width = alloc.width;
+    rect->x = alloc->x;
+    rect->width = alloc->width;
   }
 }
 
@@ -1643,3 +1773,45 @@ hdy_flap_set_reveal_duration (HdyFlap *self,
 
   g_object_notify_by_pspec (G_OBJECT (self), props[PROP_REVEAL_DURATION]);
 }
+
+/**
+ * hdy_flap_get_transition_type:
+ * @self: a #HdyFlap
+ *
+ * Returns: current transition type.
+ *
+ * Since: 1.1
+ */
+HdyFlapTransitionType
+hdy_flap_get_transition_type (HdyFlap *self)
+{
+  g_return_val_if_fail (HDY_IS_FLAP (self), HDY_FLAP_TRANSITION_TYPE_OVER);
+
+  return self->transition_type;
+}
+
+/**
+ * hdy_flap_set_transition_type:
+ * @self: a #HdyFlap
+ * @transition_type: Duration for reveal animation
+ *
+ * Since: 1.1
+ */
+void
+hdy_flap_set_transition_type (HdyFlap               *self,
+                              HdyFlapTransitionType  transition_type)
+{
+  g_return_if_fail (HDY_IS_FLAP (self));
+
+  if (self->transition_type == transition_type)
+    return;
+
+  self->transition_type = transition_type;
+
+  restack_windows (self);
+
+  if (self->reveal_progress > 0 || (self->fold_progress > 0 && self->fold_progress < 1))
+    gtk_widget_queue_allocate (GTK_WIDGET (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TRANSITION_TYPE]);
+}
diff --git a/src/hdy-flap.h b/src/hdy-flap.h
index f5f3eb7b..9d16c11a 100644
--- a/src/hdy-flap.h
+++ b/src/hdy-flap.h
@@ -28,6 +28,12 @@ typedef enum {
   HDY_FLAP_FOLD_POLICY_AUTO,
 } HdyFlapFoldPolicy;
 
+typedef enum {
+  HDY_FLAP_TRANSITION_TYPE_OVER,
+  HDY_FLAP_TRANSITION_TYPE_UNDER,
+  HDY_FLAP_TRANSITION_TYPE_SLIDE,
+} HdyFlapTransitionType;
+
 HDY_AVAILABLE_IN_1_1
 GtkWidget *hdy_flap_new (void);
 
@@ -76,4 +82,10 @@ HDY_AVAILABLE_IN_1_1
 void  hdy_flap_set_reveal_duration (HdyFlap *self,
                                     guint    duration);
 
+HDY_AVAILABLE_IN_1_1
+HdyFlapTransitionType hdy_flap_get_transition_type (HdyFlap               *self);
+HDY_AVAILABLE_IN_1_1
+void                  hdy_flap_set_transition_type (HdyFlap               *self,
+                                                    HdyFlapTransitionType  transition_type);
+
 G_END_DECLS


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