[libadwaita] demo: add demo for AdwTimedAnimation
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libadwaita] demo: add demo for AdwTimedAnimation
- Date: Mon, 22 Nov 2021 13:33:37 +0000 (UTC)
commit 278d46554408cdb1a01d4c88f318c779e9698c80
Author: Manuel Genovés <manuel genoves gmail com>
Date: Fri Aug 6 02:41:26 2021 +0200
demo: add demo for AdwTimedAnimation
demo/adw-demo-window.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++
demo/adw-demo-window.ui | 225 +++++++++++++++++++++++++++++++++++++++++++++
demo/style.css | 30 +++++-
3 files changed, 491 insertions(+), 4 deletions(-)
---
diff --git a/demo/adw-demo-window.c b/demo/adw-demo-window.c
index 44205045..2812ee7a 100644
--- a/demo/adw-demo-window.c
+++ b/demo/adw-demo-window.c
@@ -29,10 +29,24 @@ struct _AdwDemoWindow
GtkListBox *avatar_contacts;
int toast_undo_items;
AdwToast *undo_toast;
+ AdwAnimation *timed_animation;
+ GtkWidget *timed_animation_sample;
+ GtkWidget *timed_animation_button_box;
+ GtkSpinButton *timed_animation_repeat_count;
+ GtkSwitch *timed_animation_reverse;
+ GtkSwitch *timed_animation_alternate;
+ GtkSpinButton *timed_animation_duration;
+ AdwComboRow *timed_animation_easing;
};
G_DEFINE_TYPE (AdwDemoWindow, adw_demo_window, ADW_TYPE_APPLICATION_WINDOW)
+enum {
+ PROP_0,
+ PROP_TIMED_ANIMATION,
+ LAST_PROP,
+};
+
static char *
get_color_scheme_icon_name (gpointer user_data,
gboolean dark)
@@ -40,6 +54,44 @@ get_color_scheme_icon_name (gpointer user_data,
return g_strdup (dark ? "light-mode-symbolic" : "dark-mode-symbolic");
}
+static GParamSpec *props[LAST_PROP];
+
+static void
+adw_demo_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AdwDemoWindow *self = ADW_DEMO_WINDOW (object);
+
+ switch (prop_id) {
+ case PROP_TIMED_ANIMATION:
+ g_value_set_object (value, self->timed_animation);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+adw_demo_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AdwDemoWindow *self = ADW_DEMO_WINDOW (object);
+
+ switch (prop_id) {
+ case PROP_TIMED_ANIMATION:
+ g_set_object (&self->timed_animation, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
static void
color_scheme_button_clicked_cb (AdwDemoWindow *self)
{
@@ -391,6 +443,119 @@ tab_view_demo_clicked_cb (GtkButton *btn,
gtk_window_present (GTK_WINDOW (window));
}
+static char *
+animations_easing_name (AdwEnumListItem *value,
+ gpointer user_data)
+{
+ g_return_val_if_fail (ADW_IS_ENUM_LIST_ITEM (value), NULL);
+
+ switch (adw_enum_list_item_get_value (value)) {
+ case ADW_EASING_EASE_IN_CUBIC:
+ return g_strdup (_("Ease-in (Cubic)"));
+ case ADW_EASING_EASE_OUT_CUBIC:
+ return g_strdup (_("Ease-out (Cubic)"));
+ case ADW_EASING_EASE_IN_OUT_CUBIC:
+ return g_strdup (_("Ease-in-out (Cubic)"));
+ default:
+ return NULL;
+ }
+}
+
+static void
+timed_animation_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkWidget *child = gtk_widget_get_first_child (widget);
+
+ if (!child)
+ return;
+
+ gtk_widget_measure (child, orientation, for_size, minimum, natural,
+ minimum_baseline, natural_baseline);
+}
+
+static void
+timed_animation_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ AdwDemoWindow *self = ADW_DEMO_WINDOW (gtk_widget_get_root (widget));
+ GtkWidget *child = gtk_widget_get_first_child (widget);
+ double progress;
+ int child_width, offset;
+
+ if (!child)
+ return;
+
+ progress = adw_animation_get_value (self->timed_animation);
+
+ gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1,
+ &child_width, NULL, NULL, NULL);
+
+ offset = (int) ((width - child_width) * (progress - 0.5));
+
+ gtk_widget_allocate (child, width, height, baseline,
+ gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (offset, 0)));
+}
+
+static void
+timed_animation_reset (AdwDemoWindow *self)
+{
+ adw_animation_reset (self->timed_animation);
+}
+
+static void
+timed_animation_play_pause (AdwDemoWindow *self)
+{
+ switch (adw_animation_get_state (self->timed_animation)) {
+ case ADW_ANIMATION_IDLE:
+ case ADW_ANIMATION_FINISHED:
+ adw_animation_play (self->timed_animation);
+ break;
+ case ADW_ANIMATION_PAUSED:
+ adw_animation_resume (self->timed_animation);
+ break;
+ case ADW_ANIMATION_PLAYING:
+ adw_animation_pause (self->timed_animation);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+timed_animation_skip (AdwDemoWindow *self)
+{
+ adw_animation_skip (self->timed_animation);
+}
+
+static char *
+get_play_pause_icon_name (gpointer user_data,
+ AdwAnimationState state)
+{
+ return g_strdup (state == ADW_ANIMATION_PLAYING ? "media-playback-pause-symbolic" :
"media-playback-start-symbolic");
+}
+
+static gboolean
+timed_animation_can_reset (gpointer user_data,
+ AdwAnimationState state)
+{
+ return state != ADW_ANIMATION_IDLE;
+}
+
+static gboolean
+timed_animation_can_skip (gpointer user_data,
+ AdwAnimationState state)
+{
+ return state != ADW_ANIMATION_FINISHED;
+}
+
static void
style_classes_demo_clicked_cb (GtkButton *btn,
AdwDemoWindow *self)
@@ -485,8 +650,12 @@ toast_dismiss_cb (AdwDemoWindow *self)
static void
adw_demo_window_class_init (AdwDemoWindowClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ object_class->set_property = adw_demo_window_set_property;
+ object_class->get_property = adw_demo_window_get_property;
+
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_q, GDK_CONTROL_MASK, "window.close", NULL);
gtk_widget_class_install_action (widget_class, "toast.undo", NULL, (GtkWidgetActionActivateFunc)
toast_undo_cb);
@@ -509,6 +678,13 @@ adw_demo_window_class_init (AdwDemoWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, avatar_remove_button);
gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, avatar_contacts);
gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, toast_overlay);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_sample);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_button_box);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_repeat_count);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_reverse);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_alternate);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_duration);
+ gtk_widget_class_bind_template_child (widget_class, AdwDemoWindow, timed_animation_easing);
gtk_widget_class_bind_template_callback (widget_class, notify_visible_child_cb);
gtk_widget_class_bind_template_callback (widget_class, back_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, leaflet_back_clicked_cb);
@@ -532,6 +708,22 @@ adw_demo_window_class_init (AdwDemoWindowClass *klass)
gtk_widget_class_bind_template_callback (widget_class, add_toast_cb);
gtk_widget_class_bind_template_callback (widget_class, add_toast_with_button_cb);
gtk_widget_class_bind_template_callback (widget_class, add_toast_with_long_title_cb);
+ gtk_widget_class_bind_template_callback (widget_class, animations_easing_name);
+ gtk_widget_class_bind_template_callback (widget_class, timed_animation_reset);
+ gtk_widget_class_bind_template_callback (widget_class, timed_animation_play_pause);
+ gtk_widget_class_bind_template_callback (widget_class, timed_animation_skip);
+ gtk_widget_class_bind_template_callback (widget_class, get_play_pause_icon_name);
+ gtk_widget_class_bind_template_callback (widget_class, timed_animation_can_reset);
+ gtk_widget_class_bind_template_callback (widget_class, timed_animation_can_skip);
+
+ props[PROP_TIMED_ANIMATION] =
+ g_param_spec_object ("timed_animation",
+ "Timed animation",
+ "Timed animation",
+ ADW_TYPE_ANIMATION,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
}
static void
@@ -558,6 +750,52 @@ avatar_page_init (AdwDemoWindow *self)
avatar_file_remove_cb (self);
}
+static void
+animation_page_init (AdwDemoWindow *self)
+{
+ GtkLayoutManager *manager;
+ AdwAnimationTarget *target =
+ adw_callback_animation_target_new ((AdwAnimationTargetFunc)
+ gtk_widget_queue_allocate,
+ self->timed_animation_sample, NULL);
+
+ self->timed_animation =
+ adw_timed_animation_new (GTK_WIDGET (self->timed_animation_sample),
+ 0, 1, 100, target);
+
+ g_object_bind_property (self->timed_animation_repeat_count, "value",
+ self->timed_animation, "repeat-count",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+ g_object_bind_property (self->timed_animation_reverse, "state",
+ self->timed_animation, "reverse",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+ g_object_bind_property (self->timed_animation_alternate, "state",
+ self->timed_animation, "alternate",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+ g_object_bind_property (self->timed_animation_duration, "value",
+ self->timed_animation, "duration",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+ g_object_bind_property (self->timed_animation_easing, "selected",
+ self->timed_animation, "easing",
+ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+
+ adw_timed_animation_set_easing (ADW_TIMED_ANIMATION (self->timed_animation),
+ ADW_EASING_EASE_IN_OUT_CUBIC);
+
+ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TIMED_ANIMATION]);
+
+ manager = gtk_custom_layout_new (NULL, timed_animation_measure,
+ timed_animation_allocate);
+
+ gtk_widget_set_layout_manager (self->timed_animation_sample, manager);
+
+ gtk_widget_set_direction (self->timed_animation_button_box, GTK_TEXT_DIR_LTR);
+}
+
static void
adw_demo_window_init (AdwDemoWindow *self)
{
@@ -578,4 +816,6 @@ adw_demo_window_init (AdwDemoWindow *self)
adw_leaflet_set_visible_child (self->content_box, GTK_WIDGET (self->right_box));
gtk_widget_action_set_enabled (GTK_WIDGET (self), "toast.dismiss", FALSE);
+
+ animation_page_init (self);
}
diff --git a/demo/adw-demo-window.ui b/demo/adw-demo-window.ui
index 90768e02..33851e48 100644
--- a/demo/adw-demo-window.ui
+++ b/demo/adw-demo-window.ui
@@ -992,6 +992,231 @@
</property>
</object>
</child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">animations</property>
+ <property name="title" translatable="yes">Animations</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+ <property name="child">
+ <object class="GtkViewport">
+ <property name="scroll-to-focus">True</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="timed-animation-page"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="AdwClamp">
+ <property name="maximum-size">400</property>
+ <property name="tightening-threshold">300</property>
+ <property name="child">
+ <object class="AdwBin" id="timed_animation_sample">
+ <property name="child">
+ <object class="AdwBin" id="timed_animation_widget">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="htranslate"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label"
translatable="yes">Animations</property>
+ <property name="halign">center</property>
+ <property name="xalign">0</property>
+ <property name="wrap">True</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="justify">center</property>
+ <style>
+ <class name="title"/>
+ <class name="large-title"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Simpe timed
transitions.</property>
+ <property name="justify">center</property>
+ <property name="use_markup">true</property>
+ <property name="wrap">True</property>
+ <style>
+ <class name="body"/>
+ <class name="description"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="timed_animation_button_box">
+ <property name="valign">center</property>
+ <property name="halign">center</property>
+ <property name="margin-top">30</property>
+ <property name="margin-bottom">30</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkButton">
+ <property
name="icon-name">media-skip-backward-symbolic</property>
+ <property name="valign">center</property>
+ <binding name="sensitive">
+ <closure type="gboolean"
function="timed_animation_can_reset">
+ <lookup name="state" type="AdwAnimation">
+ <lookup name="timed-animation">AdwDemoWindow</lookup>
+ </lookup>
+ </closure>
+ </binding>
+ <signal name="clicked" handler="timed_animation_reset"
swapped="true"/>
+ <style>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <binding name="icon-name">
+ <closure type="gchararray"
function="get_play_pause_icon_name">
+ <lookup name="state" type="AdwAnimation">
+ <lookup name="timed-animation">AdwDemoWindow</lookup>
+ </lookup>
+ </closure>
+ </binding>
+ <property name="width-request">48</property>
+ <property name="height-request">48</property>
+ <signal name="clicked" handler="timed_animation_play_pause"
swapped="true"/>
+ <style>
+ <class name="circular"/>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property
name="icon-name">media-skip-forward-symbolic</property>
+ <property name="valign">center</property>
+ <binding name="sensitive">
+ <closure type="gboolean"
function="timed_animation_can_skip">
+ <lookup name="state" type="AdwAnimation">
+ <lookup name="timed-animation">AdwDemoWindow</lookup>
+ </lookup>
+ </closure>
+ </binding>
+ <signal name="clicked" handler="timed_animation_skip"
swapped="true"/>
+ <style>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwClamp">
+ <property name="maximum-size">400</property>
+ <property name="tightening-threshold">300</property>
+ <property name="child">
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwComboRow" id="timed_animation_easing">
+ <property name="title"
translatable="yes">Easing</property>
+ <property name="model">
+ <object class="AdwEnumListModel">
+ <property name="enum-type">AdwEasing</property>
+ </object>
+ </property>
+ <property name="expression">
+ <closure type="gchararray"
function="animations_easing_name"/>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title"
translatable="yes">Duration</property>
+ <child>
+ <object class="GtkSpinButton"
id="timed_animation_duration">
+ <property name="valign">center</property>
+ <property name="numeric">True</property>
+ <property name="adjustment">
+ <object class="GtkAdjustment">
+ <property name="lower">100</property>
+ <property name="upper">4000</property>
+ <property name="value">500</property>
+ <property name="page-increment">100</property>
+ <property name="step-increment">50</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title" translatable="yes">Repeat
count</property>
+ <child>
+ <object class="GtkSpinButton"
id="timed_animation_repeat_count">
+ <property name="valign">center</property>
+ <property name="numeric">True</property>
+ <property name="adjustment">
+ <object class="GtkAdjustment">
+ <property name="lower">0</property>
+ <property name="upper">10</property>
+ <property name="value">1</property>
+ <property name="page-increment">1</property>
+ <property name="step-increment">1</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title"
translatable="yes">Reverse</property>
+ <property
name="activatable_widget">timed_animation_reverse</property>
+ <child>
+ <object class="GtkSwitch" id="timed_animation_reverse">
+ <property name="valign">center</property>
+ <property name="state">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow">
+ <property name="title"
translatable="yes">Alternate</property>
+ <property
name="activatable_widget">timed_animation_alternate</property>
+ <child>
+ <object class="GtkSwitch"
id="timed_animation_alternate">
+ <property name="valign">center</property>
+ <property name="state">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
</object>
</child>
</object>
diff --git a/demo/style.css b/demo/style.css
index ce2676cd..b20e8815 100644
--- a/demo/style.css
+++ b/demo/style.css
@@ -12,10 +12,23 @@ carousel.vertical .carousel-icon {
}
/* Mimic the status page. */
-box.avatar-page { margin: 36px 12px; }
-box.avatar-page > box > avatar { margin-bottom: 36px; }
-box.avatar-page > box > label.title { margin-bottom: 12px; }
-box.avatar-page > box > label.description { margin-bottom: 36px; }
+.avatar-page,
+.timed-animation-page {
+ margin: 36px 12px;
+}
+
+.avatar-page > box > label.title,
+.timed-animation-page > box > label.title {
+ margin-bottom: 12px;
+}
+
+.avatar-page > box > label.description {
+ margin-bottom: 36px;
+}
+
+.avatar-page > box > avatar {
+ margin-bottom: 36px;
+}
flowbox.inline flowboxchild {
padding: 0;
@@ -40,3 +53,12 @@ flowbox.inline flowboxchild {
color: white;
background-color: @orange_4;
}
+
+.htranslate {
+ min-width: 30px;
+ min-height: 30px;
+ border-radius: 24px;
+ background: #33d17a;
+ background: linear-gradient(to bottom, @green_2, @green_5);
+ margin-bottom: 36px;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]