[gjs: 1/2] doc: add simple Gtk.TickCallback example




commit 1d22175581d0c87ee45f3301951056ad4895f085
Author: Andy Holmes <andrew g r holmes gmail com>
Date:   Wed Aug 3 17:55:17 2022 -0700

    doc: add simple Gtk.TickCallback example
    
    Add a simple example of using `Gtk.Widget.add_tick_callback()` to
    demonstrate how it can be used to implement simple tweening.

 examples/gtk4-frame-clock.js | 93 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)
---
diff --git a/examples/gtk4-frame-clock.js b/examples/gtk4-frame-clock.js
new file mode 100644
index 000000000..5b1a2a9a5
--- /dev/null
+++ b/examples/gtk4-frame-clock.js
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2022 Andy Holmes <andyholmes gnome org>
+
+
+import Gtk from 'gi://Gtk?version=4.0';
+import GLib from 'gi://GLib';
+
+
+function easeInOutQuad(p) {
+    if ((p *= 2.0) < 1.0)
+        return 0.5 * p * p;
+
+    return -0.5 * (--p * (p - 2) - 1);
+}
+
+// When the button is clicked, we'll add a tick callback to run the animation
+function _onButtonClicked(widget) {
+    // Prevent concurrent animations from being triggered
+    if (widget._animationId)
+        return;
+
+    const duration = 1000; // one second in milliseconds
+    let start = Date.now();
+    let fadeIn = false;
+
+    // Tick callbacks are just like GSource callbacks. You will get a ID that
+    // can be passed to Gtk.Widget.remove_tick_callback(), or you can return
+    // GLib.SOURCE_CONTINUE and GLib.SOURCE_REMOVE as appropriate.
+    widget._animationId = widget.add_tick_callback(() => {
+        let now = Date.now();
+
+        // We've now passed the time duration
+        if (now >= start + duration) {
+            // If we just finished fading in, we're all done
+            if (fadeIn) {
+                widget._animationId = null;
+                return GLib.SOURCE_REMOVE;
+            }
+
+            // If we just finished fading out, we'll start fading in
+            fadeIn = true;
+            start = now;
+        }
+
+        // Apply the easing function to the current progress
+        let progress = (now - start) / duration;
+        progress = easeInOutQuad(progress);
+
+        // We are using the progress as the opacity value of the button
+        widget.opacity = fadeIn ? progress : 1.0 - progress;
+
+        return GLib.SOURCE_CONTINUE;
+    });
+}
+
+
+// Initialize GTK
+Gtk.init();
+const loop = GLib.MainLoop.new(null, false);
+
+// Create a button to start the animation
+const button = new Gtk.Button({
+    label: 'Fade out, fade in',
+    valign: Gtk.Align.CENTER,
+    halign: Gtk.Align.CENTER,
+});
+button.connect('clicked', _onButtonClicked);
+
+// Create a top-level window
+const win = new Gtk.Window({
+    title: 'GTK4 Frame Clock',
+    default_width: 300,
+    default_height: 250,
+    child: button,
+});
+
+// When a widget is destroyed any tick callbacks will be removed automatically,
+// so in practice our callback would be cleaned up when the window closes.
+win.connect('close-request', () => {
+    // Note that removing a tick callback by ID will interrupt its progress, so
+    // we are resetting the button opacity manually after it's removed.
+    if (button._animationId) {
+        button.remove_tick_callback(button._animationId);
+        button.opacity = 1.0;
+    }
+
+    loop.quit();
+});
+
+// Show the window
+win.present();
+loop.run();
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]