From 9d0a42dc143daabe02c90b447bdff42e7f39e1b8 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 5 Mar 2019 20:44:45 +0100 Subject: 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. 10 - 30000 + 1000 page1 diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c index d7222f9e5e..d329d7b6e3 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 to the left + * @GTK_STACK_TRANSITION_TYPE_ROTATE_RIGHT: Pretend the pages are sides of a cube and rotate that cube to the right + * @GTK_STACK_TRANSITION_TYPE_ROTATE_LEFT_RIGHT: Pretend the pages are sides of a cube and rotate that cube to the left or right according to the children order * * 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 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 { -- cgit v1.2.1