[gtk/cube-spin] stack: Add a cube spin transition



commit 76d6f1c68e801043065a78fb17e48226a96f53a1
Author: Benjamin Otte <otte redhat com>
Date:   Tue Mar 5 20:44:45 2019 +0100

    stack: Add a cube spin transition
    
    Add a transition to GtkStack that pretends pages
    are the sides or a cube, and switch them by
    rotating the cube.
    
    Use this transition in widget-factory.

 demos/widget-factory/widget-factory.c  |   2 +-
 demos/widget-factory/widget-factory.ui |   2 +-
 gtk/gtkstack.c                         | 109 ++++++++++++++++++++++++++++++++-
 gtk/gtkstack.h                         |   5 +-
 4 files changed, 113 insertions(+), 5 deletions(-)
---
diff --git a/demos/widget-factory/widget-factory.c b/demos/widget-factory/widget-factory.c
index dcd4760e97..08f9d5efb4 100644
--- a/demos/widget-factory/widget-factory.c
+++ b/demos/widget-factory/widget-factory.c
@@ -48,7 +48,7 @@ change_transition_state (GSimpleAction *action,
   GtkStackTransitionType transition;
 
   if (g_variant_get_boolean (state))
-    transition = GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT;
+    transition = GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT;
   else
     transition = GTK_STACK_TRANSITION_TYPE_NONE;
 
diff --git a/demos/widget-factory/widget-factory.ui b/demos/widget-factory/widget-factory.ui
index 67377698e7..8c3a7f6a50 100644
--- a/demos/widget-factory/widget-factory.ui
+++ b/demos/widget-factory/widget-factory.ui
@@ -426,7 +426,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
         <property name="margin">10</property>
         <child>
           <object class="GtkStack" id="toplevel_stack">
-            <property name="transition-duration">30000</property>
+            <property name="transition-duration">1000</property>
             <child>
               <object class="GtkStackPage">
                 <property name="name">page1</property>
diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c
index d7222f9e5e..5b814ee7df 100644
--- a/gtk/gtkstack.c
+++ b/gtk/gtkstack.c
@@ -104,6 +104,9 @@
  * @GTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP: Cover the old page sliding down or uncover the new page sliding 
up, according to order
  * @GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT: Cover the old page sliding left or uncover the new page 
sliding right, according to order
  * @GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT: Cover the old page sliding right or uncover the new page 
sliding left, according to order
+ * @GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT: Pretend the pages are sides of a cube and rotate that cube
+ * @GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT: Pretend the pages are sides of a cube and rotate that cube
+ * @GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT: Pretend the pages are sides of a cube and rotate that cube
  *
  * These enumeration values describe the possible transitions
  * between pages in a #GtkStack widget.
@@ -873,7 +876,8 @@ is_direction_dependent_transition (GtkStackTransitionType transition_type)
           transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN ||
           transition_type == GTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP ||
           transition_type == GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT ||
-          transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT);
+          transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT ||
+          transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT);
 }
 
 /* Returns simple transition type for a direction dependent transition, given
@@ -887,6 +891,8 @@ get_simple_transition_type (gboolean               new_child_first,
     {
     case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT:
       return new_child_first ? GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT : GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT;
+    case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT:
+      return new_child_first ? GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT : 
GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT;
     case GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN:
       return new_child_first ? GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN : GTK_STACK_TRANSITION_TYPE_SLIDE_UP;
     case GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN:
@@ -911,6 +917,8 @@ get_simple_transition_type (gboolean               new_child_first,
     case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT:
     case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
     case GTK_STACK_TRANSITION_TYPE_CROSSFADE:
+    case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT:
+    case GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT:
     default:
       return transition_type;
     }
@@ -1049,6 +1057,10 @@ effective_transition_type (GtkStack               *stack,
           return GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT;
         case GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT:
           return GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT;
+        case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT:
+          return GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT;
+        case GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT:
+          return GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT;
         case GTK_STACK_TRANSITION_TYPE_OVER_LEFT:
           return GTK_STACK_TRANSITION_TYPE_OVER_RIGHT;
         case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT:
@@ -1071,6 +1083,7 @@ effective_transition_type (GtkStack               *stack,
         case GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT:
         case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT:
         case GTK_STACK_TRANSITION_TYPE_CROSSFADE:
+        case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT:
         default:
           return transition_type;
         }
@@ -2045,7 +2058,6 @@ gtk_stack_forall (GtkContainer *container,
     }
 }
 
-#include <gsk/gskrendernodeprivate.h>
 static void
 gtk_stack_compute_expand (GtkWidget *widget,
                           gboolean  *hexpand_p,
@@ -2167,6 +2179,94 @@ gtk_stack_snapshot_under (GtkWidget   *widget,
     }
 }
 
+static void
+gtk_stack_snapshot_cube (GtkWidget   *widget,
+                         GtkSnapshot *snapshot)
+{
+  GtkStack *stack = GTK_STACK (widget);
+  GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
+  double progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
+
+  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT)
+    progress = 1 - progress;
+
+  if (priv->last_visible_node && progress > 0.5)
+    {
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 gtk_widget_get_width (widget) / 2.f,
+                                 gtk_widget_get_height (widget) / 2.f,
+                                 0));
+      gtk_snapshot_perspective (snapshot, 2 * gtk_widget_get_width (widget) / 1.f);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 0, 0,
+                                 - gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_rotate_3d (snapshot, -90 * progress, graphene_vec3_y_axis());
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 - gtk_widget_get_width (widget) / 2.f,
+                                 - gtk_widget_get_height (widget) / 2.f,
+                                 gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                              priv->last_visible_surface_allocation.x,
+                              priv->last_visible_surface_allocation.y));
+      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
+        gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      else
+        gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+      gtk_snapshot_restore (snapshot);
+    }
+
+  gtk_snapshot_save (snapshot);
+  gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                             gtk_widget_get_width (widget) / 2.f,
+                             gtk_widget_get_height (widget) / 2.f,
+                             0));
+  gtk_snapshot_perspective (snapshot, 2 * gtk_widget_get_width (widget) / 1.f);
+  gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                             0, 0,
+                             - gtk_widget_get_width (widget) / 2.f));
+  gtk_snapshot_rotate_3d (snapshot, 90 * (1.0 - progress), graphene_vec3_y_axis());
+  gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                             - gtk_widget_get_width (widget) / 2.f,
+                             - gtk_widget_get_height (widget) / 2.f,
+                             gtk_widget_get_width (widget) / 2.f));
+  gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                          priv->last_visible_surface_allocation.x,
+                          priv->last_visible_surface_allocation.y));
+
+  if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
+    gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+  else
+    gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+  gtk_snapshot_restore (snapshot);
+
+  if (priv->last_visible_node && progress <= 0.5)
+    {
+      gtk_snapshot_save (snapshot);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 gtk_widget_get_width (widget) / 2.f,
+                                 gtk_widget_get_height (widget) / 2.f,
+                                 0));
+      gtk_snapshot_perspective (snapshot, 2 * gtk_widget_get_width (widget) / 1.f);
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 0, 0,
+                                 - gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_rotate_3d (snapshot, -90 * progress, graphene_vec3_y_axis());
+      gtk_snapshot_translate_3d (snapshot, &GRAPHENE_POINT3D_INIT (
+                                 - gtk_widget_get_width (widget) / 2.f,
+                                 - gtk_widget_get_height (widget) / 2.f,
+                                 gtk_widget_get_width (widget) / 2.f));
+      gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (
+                              priv->last_visible_surface_allocation.x,
+                              priv->last_visible_surface_allocation.y));
+      if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT)
+        gtk_snapshot_append_node (snapshot, priv->last_visible_node);
+      else
+        gtk_widget_snapshot_child (widget, priv->visible_child->widget, snapshot);
+      gtk_snapshot_restore (snapshot);
+    }
+}
+
 static void
 gtk_stack_snapshot_slide (GtkWidget   *widget,
                           GtkSnapshot *snapshot)
@@ -2283,6 +2383,10 @@ gtk_stack_snapshot (GtkWidget   *widget,
             case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT:
              gtk_stack_snapshot_under (widget, snapshot);
               break;
+            case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT:
+             gtk_stack_snapshot_cube (widget, snapshot);
+              break;
             case GTK_STACK_TRANSITION_TYPE_NONE:
             case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT:
             case GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN:
@@ -2290,6 +2394,7 @@ gtk_stack_snapshot (GtkWidget   *widget,
             case GTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP:
             case GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT:
             case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT:
+            case GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT:
             default:
               g_assert_not_reached ();
             }
diff --git a/gtk/gtkstack.h b/gtk/gtkstack.h
index 658ef8bb6a..8f67b889c2 100644
--- a/gtk/gtkstack.h
+++ b/gtk/gtkstack.h
@@ -72,7 +72,10 @@ typedef enum {
   GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN,
   GTK_STACK_TRANSITION_TYPE_OVER_DOWN_UP,
   GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT,
-  GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT
+  GTK_STACK_TRANSITION_TYPE_OVER_RIGHT_LEFT,
+  GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT,
+  GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT,
+  GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT
 } GtkStackTransitionType;
 
 struct _GtkStack {


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