From 98b78ed5da0c63df49a31f199b8147f45f40952b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 31 Aug 2013 12:00:47 -0400 Subject: [PATCH] GtkStack: Add more transition types This adds new 'over' and 'under' transitions which work by moving the new page over the previous one, or moving the previous page off to reveal the new one. We also add an over/under combination that is going to be used in GtkAboutDialog. https://bugzilla.gnome.org/show_bug.cgi?id=707187 --- gtk/gtkstack.c | 155 +++++++++++++++++++++++++++++++++++++++++++------ gtk/gtkstack.h | 11 +++- 2 files changed, 147 insertions(+), 19 deletions(-) diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c index cee970ab28..de1ead82f7 100644 --- a/gtk/gtkstack.c +++ b/gtk/gtkstack.c @@ -58,9 +58,20 @@ * @GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN: Slide from top down * @GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT: Slide from left or right according to the children order * @GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN: Slide from top down or bottom up according to the order + * @GTK_STACK_TRANSITION_TYPE_OVER_UP: Cover the old page by sliding up. Since 3.12 + * @GTK_STACK_TRANSITION_TYPE_OVER_DOWN: Cover the old page by sliding down. Since: 3.12 + * @GTK_STACK_TRANSITION_TYPE_OVER_LEFT: Cover the old page by sliding to the left. Since: 3.12 + * @GTK_STACK_TRANSITION_TYPE_OVER_RIGHT: Cover the old page by sliding to the right. Since: 3.12 + * @GTK_STACK_TRANSITION_TYPE_UNDER_UP: Uncover the new page by sliding up. Since 3.12 + * @GTK_STACK_TRANSITION_TYPE_UNDER_DOWN: Uncover the new page by sliding down. Since: 3.12 + * @GTK_STACK_TRANSITION_TYPE_UNDER_LEFT: Uncover the new page by sliding to the left. Since: 3.12 + * @GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT: Uncover the new page by sliding to the right. Since: 3.12 + * @GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN: Cover the old page or uncover the new page, according to order. Since: 3.12 * * These enumeration values describe the possible transitions * between pages in a #GtkStack widget. + * + * New values may be added to this enumeration over time. */ /* TODO: @@ -668,9 +679,12 @@ get_bin_window_x (GtkStack *stack, if (priv->transition_pos < 1.0) { - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT) + if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_LEFT) x = allocation->width * (1 - ease_out_cubic (priv->transition_pos)); - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT) + if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT) + x = -allocation->width * (1 - ease_out_cubic (priv->transition_pos)); } @@ -686,9 +700,11 @@ get_bin_window_y (GtkStack *stack, if (priv->transition_pos < 1.0) { - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP) + if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP) y = allocation->height * (1 - ease_out_cubic (priv->transition_pos)); - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN) + if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_DOWN) y = -allocation->height * (1 - ease_out_cubic (priv->transition_pos)); } @@ -709,7 +725,11 @@ gtk_stack_set_transition_position (GtkStack *stack, (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT || priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT || priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP || - priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN)) + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_DOWN || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_LEFT || + priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT)) { GtkAllocation allocation; gtk_widget_get_allocation (GTK_WIDGET (stack), &allocation); @@ -806,6 +826,14 @@ effective_transition_type (GtkStack *stack, return GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT; else if (transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT) return GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT; + else if (transition_type == GTK_STACK_TRANSITION_TYPE_OVER_LEFT) + return GTK_STACK_TRANSITION_TYPE_OVER_RIGHT; + else if (transition_type == GTK_STACK_TRANSITION_TYPE_OVER_RIGHT) + return GTK_STACK_TRANSITION_TYPE_OVER_LEFT; + else if (transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_LEFT) + return GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT; + else if (transition_type == GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT) + return GTK_STACK_TRANSITION_TYPE_UNDER_LEFT; } return transition_type; @@ -895,12 +923,14 @@ set_visible_child (GtkStack *stack, if ((child_info == NULL || priv->last_visible_child == NULL) && (transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT || - transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN)) + transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN || + transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN)) { transition_type = GTK_STACK_TRANSITION_TYPE_NONE; } else if (transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT || - transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN) + transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN || + transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN) { gboolean i_first = FALSE; for (l = priv->children; l != NULL; l = g_list_next (l)) @@ -918,10 +948,14 @@ set_visible_child (GtkStack *stack, { transition_type = i_first ? GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT : GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT; } - if (transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN) + else if (transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN) { transition_type = i_first ? GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN : GTK_STACK_TRANSITION_TYPE_SLIDE_UP; } + else if (transition_type == GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN) + { + transition_type = i_first ? GTK_STACK_TRANSITION_TYPE_UNDER_DOWN : GTK_STACK_TRANSITION_TYPE_OVER_UP; + } } gtk_widget_queue_resize (GTK_WIDGET (stack)); @@ -1466,6 +1500,64 @@ gtk_stack_draw_crossfade (GtkWidget *widget, cairo_paint (cr); } +static void +gtk_stack_draw_under (GtkWidget *widget, + cairo_t *cr) +{ + GtkStack *stack = GTK_STACK (widget); + GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); + GtkAllocation allocation; + gint x, y, width, height, pos_x, pos_y; + + gtk_widget_get_allocation (widget, &allocation); + x = y = 0; + width = allocation.width; + height = allocation.height; + pos_x = pos_y = 0; + + switch (priv->active_transition_type) + { + case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN: + y = 0; + height = allocation.height * (ease_out_cubic (priv->transition_pos)); + pos_y = height; + break; + case GTK_STACK_TRANSITION_TYPE_UNDER_UP: + y = allocation.height * (1 - ease_out_cubic (priv->transition_pos)); + height = allocation.height - y; + pos_y = y - allocation.height; + break; + case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT: + x = allocation.width * (1 - ease_out_cubic (priv->transition_pos)); + width = allocation.width - x; + pos_x = x - allocation.width; + break; + case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT: + x = 0; + width = allocation.width * (ease_out_cubic (priv->transition_pos)); + pos_x = width; + break; + default: + g_assert_not_reached (); + } + + cairo_save (cr); + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + + gtk_container_propagate_draw (GTK_CONTAINER (stack), + priv->visible_child->widget, + cr); + + cairo_restore (cr); + + if (priv->last_visible_surface) + { + cairo_set_source_surface (cr, priv->last_visible_surface, pos_x, pos_y); + cairo_paint (cr); + } +} + static void gtk_stack_draw_slide (GtkWidget *widget, cairo_t *cr) @@ -1479,18 +1571,34 @@ gtk_stack_draw_slide (GtkWidget *widget, gtk_widget_get_allocation (widget, &allocation); x = get_bin_window_x (stack, &allocation); - - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT) - x -= allocation.width; - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT) - x += allocation.width; - y = get_bin_window_y (stack, &allocation); - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_UP) - y -= allocation.height; - if (priv->active_transition_type == GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN) - y += allocation.height; + switch (priv->active_transition_type) + { + case GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT: + x -= allocation.width; + break; + case GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT: + x += allocation.width; + break; + case GTK_STACK_TRANSITION_TYPE_SLIDE_UP: + y -= allocation.height; + break; + case GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN: + y += allocation.height; + break; + case GTK_STACK_TRANSITION_TYPE_OVER_UP: + case GTK_STACK_TRANSITION_TYPE_OVER_DOWN: + y = 0; + break; + case GTK_STACK_TRANSITION_TYPE_OVER_LEFT: + case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT: + x = 0; + break; + default: + g_assert_not_reached (); + break; + } if (priv->last_visible_surface && gtk_cairo_should_draw_window (cr, priv->view_window)) @@ -1548,8 +1656,19 @@ gtk_stack_draw (GtkWidget *widget, case GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT: case GTK_STACK_TRANSITION_TYPE_SLIDE_UP: case GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN: + case GTK_STACK_TRANSITION_TYPE_OVER_UP: + case GTK_STACK_TRANSITION_TYPE_OVER_DOWN: + case GTK_STACK_TRANSITION_TYPE_OVER_LEFT: + case GTK_STACK_TRANSITION_TYPE_OVER_RIGHT: gtk_stack_draw_slide (widget, cr); break; + case GTK_STACK_TRANSITION_TYPE_UNDER_UP: + case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN: + case GTK_STACK_TRANSITION_TYPE_UNDER_LEFT: + case GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT: + if (gtk_cairo_should_draw_window (cr, priv->bin_window)) + gtk_stack_draw_under (widget, cr); + break; default: g_assert_not_reached (); } diff --git a/gtk/gtkstack.h b/gtk/gtkstack.h index 77d7337105..2c967aa67b 100644 --- a/gtk/gtkstack.h +++ b/gtk/gtkstack.h @@ -45,7 +45,16 @@ typedef enum { GTK_STACK_TRANSITION_TYPE_SLIDE_UP, GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN, GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT, - GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN + GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN, + GTK_STACK_TRANSITION_TYPE_OVER_UP, + GTK_STACK_TRANSITION_TYPE_OVER_DOWN, + GTK_STACK_TRANSITION_TYPE_OVER_LEFT, + GTK_STACK_TRANSITION_TYPE_OVER_RIGHT, + GTK_STACK_TRANSITION_TYPE_UNDER_UP, + GTK_STACK_TRANSITION_TYPE_UNDER_DOWN, + GTK_STACK_TRANSITION_TYPE_UNDER_LEFT, + GTK_STACK_TRANSITION_TYPE_UNDER_RIGHT, + GTK_STACK_TRANSITION_TYPE_OVER_UP_DOWN } GtkStackTransitionType; struct _GtkStack {