stack: port to progress tracker

This commit is contained in:
Matt Watson 2016-02-29 22:24:39 -08:00
parent 46b120b35e
commit 3909f818c4

View File

@ -27,6 +27,7 @@
#include "gtkintl.h"
#include "gtkcsscustomgadgetprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkprogresstrackerprivate.h"
#include "gtkwidgetprivate.h"
#include <math.h>
#include <string.h>
@ -143,10 +144,8 @@ typedef struct {
GtkStackChildInfo *last_visible_child;
cairo_surface_t *last_visible_surface;
GtkAllocation last_visible_surface_allocation;
gdouble transition_pos;
guint tick_id;
gint64 start_time;
gint64 end_time;
GtkProgressTracker tracker;
gint last_visible_widget_width;
gint last_visible_widget_height;
@ -765,16 +764,6 @@ gtk_stack_set_child_property (GtkContainer *container,
}
}
/* From clutter-easing.c, based on Robert Penner's
* infamous easing equations, MIT license.
*/
static double
ease_out_cubic (double t)
{
double p = t - 1;
return p * p * p + 1;
}
static inline gboolean
is_left_transition (GtkStackTransitionType transition_type)
{
@ -863,12 +852,12 @@ get_bin_window_x (GtkStack *stack,
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
int x = 0;
if (priv->transition_pos < 1.0)
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
{
if (is_left_transition (priv->active_transition_type))
x = allocation->width * (1 - ease_out_cubic (priv->transition_pos));
x = allocation->width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
if (is_right_transition (priv->active_transition_type))
x = -allocation->width * (1 - ease_out_cubic (priv->transition_pos));
x = -allocation->width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
}
return x;
@ -881,25 +870,22 @@ get_bin_window_y (GtkStack *stack,
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
int y = 0;
if (priv->transition_pos < 1.0)
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
{
if (is_up_transition (priv->active_transition_type))
y = allocation->height * (1 - ease_out_cubic (priv->transition_pos));
y = allocation->height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
if (is_down_transition(priv->active_transition_type))
y = -allocation->height * (1 - ease_out_cubic (priv->transition_pos));
y = -allocation->height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
}
return y;
}
static gboolean
gtk_stack_set_transition_position (GtkStack *stack,
gdouble pos)
static void
gtk_stack_progress_updated (GtkStack *stack)
{
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
gboolean done;
priv->transition_pos = pos;
gtk_widget_queue_draw (GTK_WIDGET (stack));
if (!priv->vhomogeneous || !priv->hhomogeneous)
@ -914,9 +900,7 @@ gtk_stack_set_transition_position (GtkStack *stack,
get_bin_window_x (stack, &allocation), get_bin_window_y (stack, &allocation));
}
done = pos >= 1.0;
if (done)
if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
{
if (priv->last_visible_surface != NULL)
{
@ -930,8 +914,6 @@ gtk_stack_set_transition_position (GtkStack *stack,
priv->last_visible_child = NULL;
}
}
return done;
}
static gboolean
@ -941,20 +923,17 @@ gtk_stack_transition_cb (GtkWidget *widget,
{
GtkStack *stack = GTK_STACK (widget);
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
gint64 now;
gdouble t;
now = gdk_frame_clock_get_frame_time (frame_clock);
t = 1.0;
if (now < priv->end_time)
t = (now - priv->start_time) / (double) (priv->end_time - priv->start_time);
gtk_progress_tracker_advance_frame (&priv->tracker,
gdk_frame_clock_get_frame_time (frame_clock));
/* Finish animation early if not mapped anymore */
if (!gtk_widget_get_mapped (widget))
t = 1.0;
gtk_progress_tracker_finish (&priv->tracker);
if (gtk_stack_set_transition_position (stack, t))
gtk_stack_progress_updated (GTK_STACK (widget));
if (gtk_progress_tracker_get_state (&priv->tracker) == GTK_PROGRESS_STATE_AFTER)
{
priv->tick_id = 0;
g_object_notify_by_pspec (G_OBJECT (stack), stack_props[PROP_TRANSITION_RUNNING]);
@ -1037,17 +1016,19 @@ gtk_stack_start_transition (GtkStack *stack,
transition_duration != 0 &&
priv->last_visible_child != NULL)
{
priv->transition_pos = 0.0;
priv->start_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
priv->end_time = priv->start_time + (transition_duration * 1000);
priv->active_transition_type = effective_transition_type (stack, transition_type);
gtk_stack_schedule_ticks (stack);
gtk_progress_tracker_start (&priv->tracker,
priv->transition_duration * 1000,
0,
1.0);
}
else
{
gtk_stack_unschedule_ticks (stack);
priv->active_transition_type = GTK_STACK_TRANSITION_TYPE_NONE;
gtk_stack_set_transition_position (stack, 1.0);
gtk_progress_tracker_finish (&priv->tracker);
gtk_stack_progress_updated (GTK_STACK (widget));
}
}
@ -1962,6 +1943,7 @@ gtk_stack_draw_crossfade (GtkWidget *widget,
{
GtkStack *stack = GTK_STACK (widget);
GtkStackPrivate *priv = gtk_stack_get_instance_private (stack);
gdouble progress = gtk_progress_tracker_get_progress (&priv->tracker, FALSE);
cairo_push_group (cr);
gtk_container_propagate_draw (GTK_CONTAINER (stack),
@ -1969,8 +1951,8 @@ gtk_stack_draw_crossfade (GtkWidget *widget,
cr);
cairo_save (cr);
/* Multiply alpha by transition pos */
cairo_set_source_rgba (cr, 1, 1, 1, priv->transition_pos);
/* Multiply alpha by progress */
cairo_set_source_rgba (cr, 1, 1, 1, progress);
cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN);
cairo_paint (cr);
@ -1980,7 +1962,7 @@ gtk_stack_draw_crossfade (GtkWidget *widget,
priv->last_visible_surface_allocation.x,
priv->last_visible_surface_allocation.y);
cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
cairo_paint_with_alpha (cr, MAX (1.0 - priv->transition_pos, 0));
cairo_paint_with_alpha (cr, MAX (1.0 - progress, 0));
}
cairo_restore (cr);
@ -2009,22 +1991,22 @@ gtk_stack_draw_under (GtkWidget *widget,
{
case GTK_STACK_TRANSITION_TYPE_UNDER_DOWN:
y = 0;
height = allocation.height * (ease_out_cubic (priv->transition_pos));
height = allocation.height * (gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
pos_y = height;
break;
case GTK_STACK_TRANSITION_TYPE_UNDER_UP:
y = allocation.height * (1 - ease_out_cubic (priv->transition_pos));
y = allocation.height * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
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));
x = allocation.width * (1 - gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
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));
width = allocation.width * (gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE));
pos_x = width;
break;
default:
@ -2155,7 +2137,7 @@ gtk_stack_render (GtkCssGadget *gadget,
if (priv->visible_child)
{
if (priv->transition_pos < 1.0)
if (gtk_progress_tracker_get_state (&priv->tracker) != GTK_PROGRESS_STATE_AFTER)
{
if (priv->last_visible_surface == NULL &&
priv->last_visible_child != NULL)
@ -2428,13 +2410,13 @@ gtk_stack_measure (GtkCssGadget *gadget,
{
if (orientation == GTK_ORIENTATION_VERTICAL && !priv->vhomogeneous)
{
gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 1.0;
gdouble t = priv->interpolate_size ? gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE) : 1.0;
*minimum = LERP (*minimum, priv->last_visible_widget_height, t);
*natural = LERP (*natural, priv->last_visible_widget_height, t);
}
if (orientation == GTK_ORIENTATION_HORIZONTAL && !priv->hhomogeneous)
{
gdouble t = priv->interpolate_size ? ease_out_cubic (priv->transition_pos) : 1.0;
gdouble t = priv->interpolate_size ? gtk_progress_tracker_get_ease_out_cubic (&priv->tracker, FALSE) : 1.0;
*minimum = LERP (*minimum, priv->last_visible_widget_width, t);
*natural = LERP (*natural, priv->last_visible_widget_width, t);
}