Compare commits

...

6 Commits

Author SHA1 Message Date
Emmanuele Bassi
bb37613711 WIP: Create an animation manager for GtkWindow 2019-07-30 17:11:59 +01:00
Emmanuele Bassi
908ebf2b23 WIP: Add GtkAnimationManager
A private class that keeps track of all in flight animations for a top
level.
2019-07-30 17:11:59 +01:00
Emmanuele Bassi
715dd26260 WIP: Add GtkPropertyAnimation
A GtkAnimation subclass that interpolates a GObject property.
2019-07-30 17:11:59 +01:00
Emmanuele Bassi
83d41b32e9 WIP: Add GtkAnimation base class
A base class for describing an animation.
2019-07-30 17:11:59 +01:00
Emmanuele Bassi
9bf52a274c Port easing GtkCssValue to GtkTimingFunction
We can share the logic, parsing, and serialization code.
2019-07-30 17:11:59 +01:00
Emmanuele Bassi
4aae883fe8 Add GtkTimingFunction
A timing function converts and input value into an output value
according to a known easing curve.

See also: https://drafts.csswg.org/css-easing/
2019-07-30 17:11:59 +01:00
21 changed files with 2013 additions and 275 deletions

View File

@@ -232,6 +232,7 @@
#include <gtk/gtktexttag.h>
#include <gtk/gtktexttagtable.h>
#include <gtk/gtktextview.h>
#include <gtk/gtktimingfunction.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtktoggletoolbutton.h>
#include <gtk/gtktoolbar.h>

279
gtk/gtkanimation.c Normal file
View File

@@ -0,0 +1,279 @@
/* gtkanimation.c: An animation
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:gtkanimation
* @Title: GtkAnimation
* @Short_description: The base class for animations
*
* ...
*/
#include "config.h"
#include "gtkanimationprivate.h"
#include "gtkintl.h"
#include "gtktypebuiltins.h"
typedef struct {
double duration;
double delay;
GtkAnimationDirection direction;
int repeat_count;
gboolean auto_reverse;
GtkTimingFunction *timing;
} GtkAnimationPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkAnimation, gtk_animation, G_TYPE_OBJECT)
enum {
PROP_DURATION = 1,
PROP_DELAY,
PROP_DIRECTION,
PROP_REPEAT_COUNT,
PROP_AUTO_REVERSE,
PROP_TIMING_FUNCTION,
N_PROPS
};
static GParamSpec *animation_props[N_PROPS];
static void
gtk_animation_finalize (GObject *gobject)
{
G_OBJECT_CLASS (gtk_animation_parent_class)->finalize (gobject);
}
static void
gtk_animation_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkAnimation *self = GTK_ANIMATION (gobject);
switch (prop_id)
{
case PROP_DURATION:
gtk_animation_set_duration (self, g_value_get_double (value));
break;
case PROP_DELAY:
gtk_animation_set_delay (self, g_value_get_double (value));
break;
case PROP_DIRECTION:
gtk_animation_set_direction (self, g_value_get_enum (value));
break;
case PROP_REPEAT_COUNT:
break;
case PROP_AUTO_REVERSE:
break;
case PROP_TIMING_FUNCTION:
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_animation_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkAnimation *self = GTK_ANIMATION (gobject);
GtkAnimationPrivate *priv = gtk_animation_get_instance_private (self);
switch (prop_id)
{
case PROP_DURATION:
break;
case PROP_DELAY:
break;
case PROP_DIRECTION:
break;
case PROP_REPEAT_COUNT:
break;
case PROP_AUTO_REVERSE:
break;
case PROP_TIMING_FUNCTION:
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gtk_animation_class_init (GtkAnimationClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gtk_animation_set_property:
gobject_class->get_property = gtk_animation_get_property;
gobject_class->finalize = gtk_animation_finalize;
animation_props[PROP_DURATION] =
g_param_spec_uint64 ("duration",
P_("Duration"),
P_("The duration of the animation, in milliseconds"),
0, G_MAXUINT64, 0,
G_PARAM_READ_WRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
animation_props[PROP_DELAY] =
g_param_spec_uint64 ("delay",
P_("Delay"),
P_("The delay before the animation starts, in milliseconds"),
0, G_MAXUINT64, 0,
G_PARAM_READ_WRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
animation_props[PROP_DIRECTION] =
g_param_spec_enum ("direction",
P_("Direction"),
P_("The direction of the animation's progress"),
GTK_TYPE_ANIMATION_DIRECTION,
GTK_ANIMATION_DIRECTION_FORWARD,
G_PARAM_READ_WRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, N_PROPS, animation_props);
}
static void
gtk_animation_init (GtkAnimation *self)
{
}
/*< private >
* gtk_animation_advance:
* @animation: a #GtkAnimation
* @frame_time: the frame time, coming from the frame clock
*
* Advances the given @animation by @frame_time milliseconds.
*/
void
gtk_animation_advance (GtkAnimation *animation,
gint64 frame_time)
{
}
void
gtk_animation_set_duration (GtkAnimation *animation,
guint64 milliseconds)
{
}
guint64
gtk_animation_get_duration (GtkAnimation *animation)
{
}
void
gtk_animation_set_delay (GtkAnimation *animation,
double seconds)
{
}
double
gtk_animation_get_delay (GtkAnimation *animation)
{
}
void
gtk_animation_set_direction (GtkAnimation *animation,
GtkAnimationDirection direction)
{
}
GtkAnimationDirection
gtk_animation_get_direction (GtkAnimation *animation)
{
}
void
gtk_animation_set_repeat_count (GtkAnimation *animation,
int repeats)
{
}
int
gtk_animation_get_repeat_count (GtkAnimation *animation)
{
}
void
gtk_animation_set_auto_reverse (GtkAnimation *animation,
gboolean auto_reverse)
{
}
gboolean
gtk_animation_get_auto_reverse (GtkAnimation *animation)
{
}
void
gtk_animation_set_timing_function (GtkAnimation *animation,
GtkTimingFunction *function)
{
}
GtkTimingFunction *
gtk_animation_get_timing_function (GtkAnimation *animation)
{
}
double
gtk_animation_get_elapsed_time (GtkAnimation *animation)
{
}
double
gtk_animation_get_progress (GtkAnimation *animation)
{
}
double
gtk_animation_get_total_duration (GtkAnimation *animation)
{
}
int
gtk_animation_get_current_repeat (GtkAnimation *animation)
{
}

87
gtk/gtkanimation.h Normal file
View File

@@ -0,0 +1,87 @@
/* gtkanimation.h: A class representing an animation
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gtk/gtktypes.h>
#include <gtk/gtkenums.h>
#include <gtk/gtktimingfunction.h>
G_BEGIN_DECLS
#define GTK_TYPE_ANIMATION (gtk_animation_get_type())
/**
* GtkAnimation:
*
* A base type for representing an animation.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (GtkAnimation, gtk_animation, GTK, ANIMATION, GObject)
/**
* double:
*
* A type used to represent elapsed time in seconds.
*/
typedef double double;
/* Properties */
GDK_AVAILABLE_IN_ALL
void gtk_animation_set_duration (GtkAnimation *animation,
double duration);
GDK_AVAILABLE_IN_ALL
double gtk_animation_get_duration (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
void gtk_animation_set_delay (GtkAnimation *animation,
double delay);
GDK_AVAILABLE_IN_ALL
double gtk_animation_get_delay (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
void gtk_animation_set_direction (GtkAnimation *animation,
GtkAnimationDirection direction);
GDK_AVAILABLE_IN_ALL
GtkAnimationDirection gtk_animation_get_direction (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
void gtk_animation_set_repeat_count (GtkAnimation *animation,
int repeats);
GDK_AVAILABLE_IN_ALL
int gtk_animation_get_repeat_count (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
void gtk_animation_set_auto_reverse (GtkAnimation *animation,
gboolean auto_reverse);
GDK_AVAILABLE_IN_ALL
gboolean gtk_animation_get_auto_reverse (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
void gtk_animation_set_timing_function (GtkAnimation *animation,
GtkTimingFunction *function);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_animation_get_timing_function (GtkAnimation *animation);
/* State query */
GDK_AVAILABLE_IN_ALL
double gtk_animation_get_elapsed_time (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
double gtk_animation_get_progress (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
double gtk_animation_get_total_duration (GtkAnimation *animation);
GDK_AVAILABLE_IN_ALL
int gtk_animation_get_current_repeat (GtkAnimation *animation);
G_END_DECLS

37
gtk/gtkanimationmanager.c Normal file
View File

@@ -0,0 +1,37 @@
#include "config.h"
#include "gtkanimationmanagerprivate.h"
struct _GtkAnimationManager
{
GObject parent_instance;
GdkFrameClock *frame_clock;
gint64 last_frame_time;
};
G_DEFINE_TYPE (GtkAnimationManager, gtk_animation_manager, G_TYPE_OBJECT)
static void
gtk_animation_manager_class_init (GtkAnimationManagerClass *klass)
{
}
static void
gtk_animation_manager_init (GtkAnimationManager *self)
{
}
GtkAnimationManager *
gtk_animation_manager_new (void)
{
return g_object_new (GTK_TYPE_ANIMATION_MANAGER, NULL);
}
void
gtk_animation_manager_set_frame_clock (GtkAnimationManager *self,
GdkFrameClock *frame_clock)
{
}

View File

@@ -0,0 +1,38 @@
/* gtkanimationmanagerprivate.h: Animation manager
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gtk/gtktypes.h>
G_BEGIN_DECLS
#define GTK_TYPE_ANIMATION_MANAGER (gtk_animation_manager_get_type())
G_DECLARE_FINAL_TYPE (GtkAnimationManager, gtk_animation_manager, GTK, ANIMATION_MANAGER, GObject)
GtkAnimationManager *
gtk_animation_manager_new (void);
void
gtk_animation_manager_set_frame_clock (GtkAnimationManager *self,
GdkFrameClock *frame_clock);
G_END_DECLS

41
gtk/gtkanimationprivate.h Normal file
View File

@@ -0,0 +1,41 @@
/* gtkanimationprivate.h: Animation type
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "gtkanimation.h"
G_BEGIN_DECLS
struct _GtkAnimationClass
{
GObjectClass parent_class;
void (* start) (GtkAnimation *animation);
void (* advance) (GtkAnimation *animation,
gint64 frame_time);
void (* stop) (GtkAnimation *animation,
gboolean is_finished);
void (* iteration) (GtkAnimation *animation);
};
void gtk_animation_advance (GtkAnimation *animation,
gint64 frame_time);
G_END_DECLS

View File

@@ -18,34 +18,19 @@
#include "config.h"
#include "gtkcsseasevalueprivate.h"
#include "gtktimingfunctionprivate.h"
#include <math.h>
typedef enum {
GTK_CSS_EASE_CUBIC_BEZIER,
GTK_CSS_EASE_STEPS
} GtkCssEaseType;
struct _GtkCssValue {
GTK_CSS_VALUE_BASE
GtkCssEaseType type;
union {
struct {
double x1;
double y1;
double x2;
double y2;
} cubic;
struct {
guint steps;
gboolean start;
} steps;
} u;
GtkTimingFunction *tm;
};
static void
gtk_css_value_ease_free (GtkCssValue *value)
{
gtk_timing_function_unref (value->tm);
g_slice_free (GtkCssValue, value);
}
@@ -63,23 +48,7 @@ static gboolean
gtk_css_value_ease_equal (const GtkCssValue *ease1,
const GtkCssValue *ease2)
{
if (ease1->type != ease2->type)
return FALSE;
switch (ease1->type)
{
case GTK_CSS_EASE_CUBIC_BEZIER:
return ease1->u.cubic.x1 == ease2->u.cubic.x1 &&
ease1->u.cubic.y1 == ease2->u.cubic.y1 &&
ease1->u.cubic.x2 == ease2->u.cubic.x2 &&
ease1->u.cubic.y2 == ease2->u.cubic.y2;
case GTK_CSS_EASE_STEPS:
return ease1->u.steps.steps == ease2->u.steps.steps &&
ease1->u.steps.start == ease2->u.steps.start;
default:
g_assert_not_reached ();
return FALSE;
}
return gtk_timing_function_equal (ease1->tm, ease2->tm);
}
static GtkCssValue *
@@ -95,43 +64,7 @@ static void
gtk_css_value_ease_print (const GtkCssValue *ease,
GString *string)
{
switch (ease->type)
{
case GTK_CSS_EASE_CUBIC_BEZIER:
if (ease->u.cubic.x1 == 0.25 && ease->u.cubic.y1 == 0.1 &&
ease->u.cubic.x2 == 0.25 && ease->u.cubic.y2 == 1.0)
g_string_append (string, "ease");
else if (ease->u.cubic.x1 == 0.0 && ease->u.cubic.y1 == 0.0 &&
ease->u.cubic.x2 == 1.0 && ease->u.cubic.y2 == 1.0)
g_string_append (string, "linear");
else if (ease->u.cubic.x1 == 0.42 && ease->u.cubic.y1 == 0.0 &&
ease->u.cubic.x2 == 1.0 && ease->u.cubic.y2 == 1.0)
g_string_append (string, "ease-in");
else if (ease->u.cubic.x1 == 0.0 && ease->u.cubic.y1 == 0.0 &&
ease->u.cubic.x2 == 0.58 && ease->u.cubic.y2 == 1.0)
g_string_append (string, "ease-out");
else if (ease->u.cubic.x1 == 0.42 && ease->u.cubic.y1 == 0.0 &&
ease->u.cubic.x2 == 0.58 && ease->u.cubic.y2 == 1.0)
g_string_append (string, "ease-in-out");
else
g_string_append_printf (string, "cubic-bezier(%g,%g,%g,%g)",
ease->u.cubic.x1, ease->u.cubic.y1,
ease->u.cubic.x2, ease->u.cubic.y2);
break;
case GTK_CSS_EASE_STEPS:
if (ease->u.steps.steps == 1)
{
g_string_append (string, ease->u.steps.start ? "step-start" : "step-end");
}
else
{
g_string_append_printf (string, "steps(%u%s)", ease->u.steps.steps, ease->u.steps.start ? ",start" : "");
}
break;
default:
g_assert_not_reached ();
break;
}
gtk_timing_function_print (ease->tm, string);
}
static const GtkCssValueClass GTK_CSS_VALUE_EASE = {
@@ -145,42 +78,12 @@ static const GtkCssValueClass GTK_CSS_VALUE_EASE = {
};
GtkCssValue *
_gtk_css_ease_value_new_cubic_bezier (double x1,
double y1,
double x2,
double y2)
_gtk_css_ease_value_new_ease (void)
{
GtkCssValue *value;
g_return_val_if_fail (x1 >= 0.0, NULL);
g_return_val_if_fail (x1 <= 1.0, NULL);
g_return_val_if_fail (x2 >= 0.0, NULL);
g_return_val_if_fail (x2 <= 1.0, NULL);
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_EASE);
value->type = GTK_CSS_EASE_CUBIC_BEZIER;
value->u.cubic.x1 = x1;
value->u.cubic.y1 = y1;
value->u.cubic.x2 = x2;
value->u.cubic.y2 = y2;
return value;
}
static GtkCssValue *
_gtk_css_ease_value_new_steps (guint n_steps,
gboolean start)
{
GtkCssValue *value;
g_return_val_if_fail (n_steps > 0, NULL);
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_EASE);
value->type = GTK_CSS_EASE_STEPS;
value->u.steps.steps = n_steps;
value->u.steps.start = start;
value->tm = gtk_ease ();
return value;
}
@@ -224,131 +127,19 @@ _gtk_css_ease_value_can_parse (GtkCssParser *parser)
return FALSE;
}
static guint
gtk_css_ease_value_parse_cubic_bezier_arg (GtkCssParser *parser,
guint arg,
gpointer data)
{
double *values = data;
if (!gtk_css_parser_consume_number (parser, &values[arg]))
return 0;
if (arg % 2 == 0)
{
if (values[arg] < 0 || values[arg] > 1.0)
{
gtk_css_parser_error_value (parser, "value %g out of range. Must be from 0.0 to 1.0", values[arg]);
return 0;
}
}
return 1;
}
static GtkCssValue *
gtk_css_ease_value_parse_cubic_bezier (GtkCssParser *parser)
{
double values[4];
if (!gtk_css_parser_consume_function (parser, 4, 4, gtk_css_ease_value_parse_cubic_bezier_arg, values))
return NULL;
return _gtk_css_ease_value_new_cubic_bezier (values[0], values[1], values[2], values[3]);
}
typedef struct
{
int n_steps;
gboolean start;
} ParseStepsData;
static guint
gtk_css_ease_value_parse_steps_arg (GtkCssParser *parser,
guint arg,
gpointer data_)
{
ParseStepsData *data = data_;
switch (arg)
{
case 0:
if (!gtk_css_parser_consume_integer (parser, &data->n_steps))
{
return 0;
}
else if (data->n_steps < 1)
{
gtk_css_parser_error_value (parser, "Number of steps must be > 0");
return 0;
}
return 1;
case 1:
if (gtk_css_parser_try_ident (parser, "start"))
data->start = TRUE;
else if (gtk_css_parser_try_ident (parser, "end"))
data->start = FALSE;
else
{
gtk_css_parser_error_syntax (parser, "Only allowed values are 'start' and 'end'");
return 0;
}
return 1;
default:
g_return_val_if_reached (0);
}
}
static GtkCssValue *
gtk_css_ease_value_parse_steps (GtkCssParser *parser)
{
ParseStepsData data = { 0, FALSE };
if (!gtk_css_parser_consume_function (parser, 1, 2, gtk_css_ease_value_parse_steps_arg, &data))
return NULL;
return _gtk_css_ease_value_new_steps (data.n_steps, data.start);
}
GtkCssValue *
_gtk_css_ease_value_parse (GtkCssParser *parser)
{
guint i;
GtkCssValue *value;
GtkTimingFunction *tm;
g_return_val_if_fail (parser != NULL, NULL);
if (!gtk_timing_function_parser_parse (parser, &tm))
return NULL;
for (i = 0; i < G_N_ELEMENTS (parser_values); i++)
{
if (parser_values[i].is_function)
{
if (gtk_css_parser_has_function (parser, parser_values[i].name))
{
if (parser_values[i].is_bezier)
return gtk_css_ease_value_parse_cubic_bezier (parser);
else
return gtk_css_ease_value_parse_steps (parser);
}
}
else
{
if (gtk_css_parser_try_ident (parser, parser_values[i].name))
{
if (parser_values[i].is_bezier)
return _gtk_css_ease_value_new_cubic_bezier (parser_values[i].values[0],
parser_values[i].values[1],
parser_values[i].values[2],
parser_values[i].values[3]);
else
return _gtk_css_ease_value_new_steps (parser_values[i].values[0],
parser_values[i].values[1] != 0.0);
}
}
}
value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_EASE);
value->tm = tm;
gtk_css_parser_error_syntax (parser, "Expected a valid ease value");
return NULL;
return value;
}
double
@@ -362,45 +153,5 @@ _gtk_css_ease_value_transform (const GtkCssValue *ease,
if (progress >= 1)
return 1;
switch (ease->type)
{
case GTK_CSS_EASE_CUBIC_BEZIER:
{
static const double epsilon = 0.00001;
double tmin, t, tmax;
tmin = 0.0;
tmax = 1.0;
t = progress;
while (tmin < tmax)
{
double sample;
sample = (((1.0 + 3 * ease->u.cubic.x1 - 3 * ease->u.cubic.x2) * t
+ -6 * ease->u.cubic.x1 + 3 * ease->u.cubic.x2) * t
+ 3 * ease->u.cubic.x1 ) * t;
if (fabs(sample - progress) < epsilon)
break;
if (progress > sample)
tmin = t;
else
tmax = t;
t = (tmax + tmin) * .5;
}
return (((1.0 + 3 * ease->u.cubic.y1 - 3 * ease->u.cubic.y2) * t
+ -6 * ease->u.cubic.y1 + 3 * ease->u.cubic.y2) * t
+ 3 * ease->u.cubic.y1 ) * t;
}
case GTK_CSS_EASE_STEPS:
progress *= ease->u.steps.steps;
progress = floor (progress) + (ease->u.steps.start ? 0 : 1);
return progress / ease->u.steps.steps;
default:
g_assert_not_reached ();
return 1.0;
}
return gtk_timing_function_transform_time (ease->tm, progress, 1.0);
}

View File

@@ -25,10 +25,7 @@
G_BEGIN_DECLS
GtkCssValue * _gtk_css_ease_value_new_cubic_bezier (double x1,
double y1,
double x2,
double y2);
GtkCssValue * _gtk_css_ease_value_new_ease (void);
gboolean _gtk_css_ease_value_can_parse (GtkCssParser *parser);
GtkCssValue * _gtk_css_ease_value_parse (GtkCssParser *parser);

View File

@@ -1613,8 +1613,7 @@ _gtk_css_style_property_init_properties (void)
0,
transition_timing_function_parse,
NULL,
_gtk_css_array_value_new (
_gtk_css_ease_value_new_cubic_bezier (0.25, 0.1, 0.25, 1.0)));
_gtk_css_array_value_new (_gtk_css_ease_value_new_ease ()));
gtk_css_style_property_register ("transition-delay",
GTK_CSS_PROPERTY_TRANSITION_DELAY,
G_TYPE_NONE,
@@ -1647,8 +1646,7 @@ _gtk_css_style_property_init_properties (void)
0,
transition_timing_function_parse,
NULL,
_gtk_css_array_value_new (
_gtk_css_ease_value_new_cubic_bezier (0.25, 0.1, 0.25, 1.0)));
_gtk_css_array_value_new (_gtk_css_ease_value_new_ease ()));
gtk_css_style_property_register ("animation-iteration-count",
GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT,
G_TYPE_NONE,

View File

@@ -1147,4 +1147,26 @@ typedef enum {
GTK_CONSTRAINT_VFL_PARSER_ERROR_INVALID_RELATION
} GtkConstraintVflParserError;
/**
* GtkAnimationDirection:
* @GTK_ANIMATION_DIRECTION_FORWARD:
* @GTK_ANIMATION_DIRECTION_BACKWARD:
*
* The direction of the animation.
*/
typedef enum {
GTK_ANIMATION_DIRECTION_FORWARD,
GTK_ANIMATION_DIRECTION_BACKWARD
} GtkAnimationDirection;
typedef enum {
GTK_STEP_POSITION_JUMP_START,
GTK_STEP_POSITION_JUMP_END,
GTK_STEP_POSITION_JUMP_NONE,
GTK_STEP_POSITION_JUMP_BOTH,
GTK_STEP_POSITION_START = GTK_STEP_POSITION_JUMP_START,
GTK_STEP_POSITION_END = GTK_STEP_POSITION_JUMP_END
} GtkStepPosition;
#endif /* __GTK_ENUMS_H__ */

View File

@@ -0,0 +1,49 @@
/* gtkpropertyanimation.c: An animation controlling a single property
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "gtkpropertyanimation.h"
#include "gtktransitionprivate.h"
enum
{
INITIAL,
FINAL,
N_STATES
};
struct _GtkPropertyAnimation
{
GtkTransition parent_instance;
GValue interval[N_STATES];
};
G_DEFINE_TYPE (GtkPropertyAnimation, gtk_property_animation, GTK_TYPE_ANIMATION)
static void
gtk_property_animation_class_init (GtkPropertyAnimationClass *klass)
{
}
static void
gtk_property_animation_init (GtkPropertyAnimation *self)
{
}

View File

@@ -0,0 +1,52 @@
/* gtkpropertyanimation.h: An animation controlling a single object property
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gtk/gtkanimation.h>
G_BEGIN_DECLS
/**
* GtkPropertyAnimation:
*
* A animation that operates on a single property of a #GObject.
*/
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkPropertyAnimation, gtk_property_animation, GTK, PROPERTY_ANIMATION, GtkAnimation)
GDK_AVAILABLE_IN_ALL
GtkAnimation * gtk_property_animation_new (const char *property_name);
/* Interval */
GDK_AVAILABLE_IN_ALL
void gtk_property_animation_set_from (GtkPropertyAnimation *animation,
...);
GDK_AVAILABLE_IN_ALL
void gtk_property_animation_set_from_value (GtkPropertyAnimation *animation,
const GValue *value);
GDK_AVAILABLE_IN_ALL
void gtk_property_animation_set_to (GtkPropertyAnimation *animation,
...);
GDK_AVAILABLE_IN_ALL
void gtk_property_animation_set_to_value (GtkPropertyAnimation *animation,
const GValue *value);
G_END_DECLS

View File

@@ -50,18 +50,24 @@ gtk_root_default_get_display (GtkRoot *self)
return gdk_display_get_default ();
}
static GtkConstraintSolver *
gtk_root_default_get_constraint_solver (GtkRoot *self)
{
return NULL;
}
static GtkAnimationManager *
gtk_root_default_get_animation_manager (GtkRoot *self)
{
return NULL;
}
static void
gtk_root_default_init (GtkRootInterface *iface)
{
iface->get_display = gtk_root_default_get_display;
iface->get_constraint_solver = gtk_root_default_get_constraint_solver;
iface->get_animation_manager = gtk_root_default_get_animation_manager;
g_object_interface_install_property (iface,
g_param_spec_object ("focus-widget",
@@ -101,6 +107,17 @@ gtk_root_get_constraint_solver (GtkRoot *self)
return iface->get_constraint_solver (self);
}
GtkAnimationManager *
gtk_root_get_animation_manager (GtkRoot *self)
{
GtkRootInterface *iface;
g_return_val_if_fail (GTK_IS_ROOT (self), NULL);
iface = GTK_ROOT_GET_IFACE (self);
return iface->get_animation_manager (self);
}
/**
* gtk_root_set_focus:
* @self: a #GtkRoot

View File

@@ -3,11 +3,12 @@
#include "gtkroot.h"
#include "gtkanimationmanagerprivate.h"
#include "gtkconstraintsolverprivate.h"
G_BEGIN_DECLS
/**
/*< private >
* GtkRootIface:
*
* The list of functions that must be implemented for the #GtkRoot interface.
@@ -21,9 +22,11 @@ struct _GtkRootInterface
GdkDisplay * (* get_display) (GtkRoot *self);
GtkConstraintSolver * (* get_constraint_solver) (GtkRoot *self);
GtkAnimationManager * (* get_animation_manager) (GtkRoot *self);
};
GtkConstraintSolver * gtk_root_get_constraint_solver (GtkRoot *self);
GtkAnimationManager * gtk_root_get_animation_manager (GtkRoot *self);
enum {
GTK_ROOT_PROP_FOCUS_WIDGET,

1167
gtk/gtktimingfunction.c Normal file

File diff suppressed because it is too large Load Diff

94
gtk/gtktimingfunction.h Normal file
View File

@@ -0,0 +1,94 @@
/* gtktimingfunction.h: Timing functions for animations
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gtk/gtktypes.h>
#include <gtk/gtkenums.h>
G_BEGIN_DECLS
#define GTK_TYPE_TIMING_FUNCTION (gtk_timing_function_get_type())
/**
* GtkTimingFunction:
*
* An opaque type representing a timing, or "easing" function.
*/
typedef struct _GtkTimingFunction GtkTimingFunction;
GDK_AVAILABLE_IN_ALL
GType gtk_timing_function_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
gboolean gtk_timing_function_equal (GtkTimingFunction *a,
GtkTimingFunction *b);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_timing_function_ref (GtkTimingFunction *self);
GDK_AVAILABLE_IN_ALL
void gtk_timing_function_unref (GtkTimingFunction *self);
GDK_AVAILABLE_IN_ALL
char * gtk_timing_function_to_string (GtkTimingFunction *self);
GDK_AVAILABLE_IN_ALL
void gtk_timing_function_print (GtkTimingFunction *self,
GString *buf);
GDK_AVAILABLE_IN_ALL
gboolean gtk_timing_function_parse (const char *string,
GtkTimingFunction **out_func);
GDK_AVAILABLE_IN_ALL
double gtk_timing_function_transform_time (GtkTimingFunction *self,
double elapsed,
double duration);
GDK_AVAILABLE_IN_ALL
gboolean gtk_timing_function_get_control_points (GtkTimingFunction *self,
double *x_1,
double *y_1,
double *x_2,
double *y_2);
GDK_AVAILABLE_IN_ALL
gboolean gtk_timing_function_get_steps (GtkTimingFunction *self,
int *n_steps,
GtkStepPosition *position);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_linear (void);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_cubic_bezier (double x_1,
double y_1,
double x_2,
double y_2);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_ease (void);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_ease_in (void);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_ease_out (void);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_ease_in_out (void);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_steps (int n_steps,
GtkStepPosition position);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_step_start (void);
GDK_AVAILABLE_IN_ALL
GtkTimingFunction * gtk_step_end (void);
G_END_DECLS

View File

@@ -0,0 +1,29 @@
/* gtktimingfunctionprivate.h: Private declarations for GtkTimingFunction
*
* Copyright 2019 GNOME Foundation
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "gtktimingfunction.h"
#include "gtkcssparserprivate.h"
G_BEGIN_DECLS
gboolean gtk_timing_function_parser_parse (GtkCssParser *parser,
GtkTimingFunction **out_function);
G_END_DECLS

View File

@@ -283,6 +283,7 @@ typedef struct
GList *foci;
GtkConstraintSolver *constraint_solver;
GtkAnimationManager *animation_manager;
} GtkWindowPrivate;
#ifdef GDK_WINDOWING_X11
@@ -2367,6 +2368,23 @@ gtk_window_root_get_constraint_solver (GtkRoot *root)
return priv->constraint_solver;
}
static GtkAnimationManager *
gtk_window_root_get_animation_manager (GtkRoot *root)
{
GtkWindow *self = GTK_WINDOW (root);
GtkWindowPrivate *priv = gtk_window_get_instance_private (self);
GdkFrameClock *frame_clock;
if (priv->animation_manager == NULL)
priv->animation_manager = gtk_animation_manager_new ();
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
if (frame_clock != NULL)
gtk_animation_manager_set_frame_clock (priv->animation_manager, frame_clock);
return priv->animation_manager;
}
static void
gtk_window_native_get_surface_transform (GtkNative *native,
int *x,
@@ -2396,6 +2414,7 @@ gtk_window_root_interface_init (GtkRootInterface *iface)
{
iface->get_display = gtk_window_root_get_display;
iface->get_constraint_solver = gtk_window_root_get_constraint_solver;
iface->get_animation_manager = gtk_window_root_get_animation_manager;
}
static void
@@ -4738,6 +4757,7 @@ gtk_window_finalize (GObject *object)
priv->mnemonics_display_timeout_id = 0;
}
g_clear_object (&priv->animation_manager);
g_clear_object (&priv->constraint_solver);
g_clear_object (&priv->renderer);

View File

@@ -23,6 +23,7 @@ gtk_private_sources = files([
'gtkactionobservable.c',
'gtkactionobserver.c',
'gtkallocatedbitmask.c',
'gtkanimationmanager.c',
'gtkapplicationaccels.c',
'gtkapplicationimpl.c',
'gtkbookmarksmanager.c',
@@ -315,7 +316,6 @@ gtk_public_sources = files([
'gtkradiomenuitem.c',
'gtkradiotoolbutton.c',
'gtkrange.c',
'gtktreerbtree.c',
'gtkrecentmanager.c',
'gtkrender.c',
'gtkrenderbackground.c',
@@ -377,6 +377,7 @@ gtk_public_sources = files([
'gtktexttypes.c',
'gtktextutil.c',
'gtktextview.c',
'gtktimingfunction.c',
'gtktogglebutton.c',
'gtktoggletoolbutton.c',
'gtktoolbar.c',
@@ -391,6 +392,7 @@ gtk_public_sources = files([
'gtktreemodel.c',
'gtktreemodelfilter.c',
'gtktreemodelsort.c',
'gtktreerbtree.c',
'gtktreeselection.c',
'gtktreesortable.c',
'gtktreestore.c',
@@ -618,6 +620,7 @@ gtk_public_headers = files([
'gtktexttag.h',
'gtktexttagtable.h',
'gtktextview.h',
'gtktimingfunction.h',
'gtktogglebutton.h',
'gtktoggletoolbutton.h',
'gtktoolbar.h',

View File

@@ -61,6 +61,7 @@ tests = [
['textbuffer'],
['textiter'],
['theme-validate'],
['timing-function'],
['treelistmodel'],
['treemodel', ['treemodel.c', 'liststore.c', 'treestore.c', 'filtermodel.c',
'modelrefcount.c', 'sortmodel.c', 'gtktreemodelrefcount.c']],

View File

@@ -0,0 +1,52 @@
#include <locale.h>
#include "gtk/gtk.h"
static void
timing_function_linear (void)
{
GtkTimingFunction *tm = gtk_linear ();
g_assert_cmpfloat_with_epsilon (gtk_timing_function_transform_time (tm, 0.0, 1.0), 0.0, 0.0001);
g_assert_cmpfloat_with_epsilon (gtk_timing_function_transform_time (tm, 0.1, 1.0), 0.1, 0.0001);
g_assert_cmpfloat_with_epsilon (gtk_timing_function_transform_time (tm, 0.5, 1.0), 0.5, 0.0001);
g_assert_cmpfloat_with_epsilon (gtk_timing_function_transform_time (tm, 0.9, 1.0), 0.9, 0.0001);
g_assert_cmpfloat_with_epsilon (gtk_timing_function_transform_time (tm, 1.0, 1.0), 1.0, 0.0001);
gtk_timing_function_unref (tm);
}
static void
timing_function_parse (void)
{
struct {
const char *str;
GtkTimingFunction *tm;
} defs[] = {
{ "linear", gtk_linear () },
{ "cubic-bezier(0, 0, 1, 1)", gtk_cubic_bezier (0, 0, 1, 1) },
};
for (int i = 0; i < G_N_ELEMENTS (defs); i++)
{
GtkTimingFunction *tm;
g_assert_true (gtk_timing_function_parse (defs[i].str, &tm));
g_assert_true (gtk_timing_function_equal (defs[i].tm, tm));
gtk_timing_function_unref (tm);
}
}
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
setlocale (LC_ALL, "C");
g_test_add_func ("/timing-function/linear", timing_function_linear);
g_test_add_func ("/timing-function/parse", timing_function_parse);
return g_test_run ();
}