[gnome-boxes/wip/exalm/swipe: 1/2] welcome-tutorial: Make it swipeable



commit a94ccbfbc8a98c8eb2c67ddf7a9c98b1bdd760a2
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Wed Feb 19 19:08:57 2020 +0500

    welcome-tutorial: Make it swipeable
    
    Use Hdy.Paginator instead of Gtk.Stack and interpolate color smoothly
    between the pages. Animate back/forward button opacity based on position
    as well.

 data/gtk-style.css             |  4 ++-
 data/ui/welcome-tutorial.ui    | 12 ++++---
 src/welcome-tutorial-page.vala |  7 ++--
 src/welcome-tutorial.vala      | 73 +++++++++++++++++++++++++++++-------------
 4 files changed, 66 insertions(+), 30 deletions(-)
---
diff --git a/data/gtk-style.css b/data/gtk-style.css
index ae24b066..e3d0cc85 100644
--- a/data/gtk-style.css
+++ b/data/gtk-style.css
@@ -134,6 +134,8 @@ separator {
     background-position: center 15%;
 }
 
-.welcome-tutorial-title-label, .welcome-tutorial-description-label {
+.welcome-tutorial,
+.welcome-tutorial-title-label,
+.welcome-tutorial-description-label {
     color: white;
 }
diff --git a/data/ui/welcome-tutorial.ui b/data/ui/welcome-tutorial.ui
index 63157cb6..94798ac0 100644
--- a/data/ui/welcome-tutorial.ui
+++ b/data/ui/welcome-tutorial.ui
@@ -8,6 +8,9 @@
     <property name="height-request">600</property>
     <property name="width-request">710</property>
     <signal name="delete-event" handler="gtk_widget_hide_on_delete"/>
+    <style>
+      <class name="welcome-tutorial"/>
+    </style>
 
     <child internal-child="vbox">
       <object class="GtkBox">
@@ -20,11 +23,10 @@
             <property name="expand">True</property>
 
             <child>
-              <object class="GtkStack" id="stack">
+              <object class="HdyPaginator" id="paginator">
                 <property name="visible">True</property>
-                <property name="transition-duration">400</property>
-                <property name="transition-type">slide-left-right</property>
-                <signal name="notify::visible-child" handler="on_stack_page_changed"/>
+                <property name="animation-duration">400</property>
+                <signal name="notify::position" handler="on_position_changed"/>
 
                 <child>
                   <object class="BoxesWelcomeTutorialPage">
@@ -72,7 +74,7 @@
 
                 <child>
                   <object class="GtkButton" id="go_back_button">
-                    <property name="visible">False</property>
+                    <property name="visible">True</property>
                     <property name="can-focus">True</property>
                     <property name="valign">center</property>
                     <signal name="clicked" handler="on_back_button_clicked"/>
diff --git a/src/welcome-tutorial-page.vala b/src/welcome-tutorial-page.vala
index cbce473e..05e17b22 100644
--- a/src/welcome-tutorial-page.vala
+++ b/src/welcome-tutorial-page.vala
@@ -28,15 +28,18 @@
     public Gdk.RGBA color { set; get; }
     public string image { set; get; }
 
+    construct {
+        expand = true;
+    }
+
     [GtkCallback]
     private void load_css () {
         var provider = new CssProvider ();
         var css = """
           .tutorial-page {
-            background-color: %s;
             background-image: url("resource://%s");
           }
-        """.printf (color.to_string (), image);
+        """.printf (image);
 
         provider.load_from_data (css);
         get_style_context ().add_provider (provider, STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/src/welcome-tutorial.vala b/src/welcome-tutorial.vala
index be753f31..8bec1e81 100644
--- a/src/welcome-tutorial.vala
+++ b/src/welcome-tutorial.vala
@@ -1,62 +1,91 @@
 // This file is part of GNOME Boxes. License: LGPLv2+
 using Gtk;
+using Hdy;
 
 [GtkTemplate (ui = "/org/gnome/Boxes/ui/welcome-tutorial.ui")]
 private class Boxes.WelcomeTutorial : Gtk.Dialog {
     [GtkChild]
-    private Stack stack;
+    private Paginator paginator;
     [GtkChild]
     private Button go_back_button;
     [GtkChild]
     private Button go_next_button;
 
-    private GLib.List<unowned Widget> pages;
-
-    private uint _visible_page_idx = 0;
-    private uint visible_page_idx {
-        set {
-            _visible_page_idx = value;
-
-            stack.set_visible_child (pages.nth_data (visible_page_idx));
-        }
-        get {
-            return _visible_page_idx;
-        }
-    }
+    private GLib.List<unowned WelcomeTutorialPage> pages;
+    private CssProvider provider;
 
     construct {
         use_header_bar = 1;
 
-        pages = stack.get_children ();
+        pages = new GLib.List<unowned WelcomeTutorialPage> ();
+        foreach (var page in paginator.get_children ()) {
+            assert (page is WelcomeTutorialPage);
+            pages.append (page as WelcomeTutorialPage);
+        }
+
+        provider = new CssProvider ();
+        get_style_context ().add_provider (provider,
+                                           STYLE_PROVIDER_PRIORITY_APPLICATION);
 
-        on_stack_page_changed ();
+        on_position_changed ();
     }
 
     public WelcomeTutorial (AppWindow app_window) {
         set_transient_for (app_window);
     }
 
+    private void set_background_color (Gdk.RGBA color) {
+        var css = """
+          .welcome-tutorial {
+            background-color: %s;
+          }
+        """.printf (color.to_string ());
+
+        provider.load_from_data (css);
+    }
+
     [GtkCallback]
-    private void on_stack_page_changed () {
+    private void on_position_changed () {
         var n_pages = pages.length ();
+        var position = paginator.position;
+        var index = (uint) Math.round (position);
 
         var topbar = get_header_bar () as Gtk.HeaderBar;
-        topbar.subtitle = _("%u/%u").printf (visible_page_idx + 1, n_pages);
+        topbar.subtitle = _("%u/%u").printf (index + 1, n_pages);
 
         // Toggle button's visibility
-        go_back_button.visible = (visible_page_idx > 0);
-        go_next_button.visible = (visible_page_idx < pages.length () - 1);
+        go_back_button.opacity = double.min (position, 1);
+        go_next_button.opacity = double.max (0, n_pages - 1 - position);
 
+        var color1 = pages.nth_data ((uint) Math.floor (position)).color;
+        var color2 = pages.nth_data ((uint) Math.ceil (position)).color;
+        var progress = position % 1;
+
+        Gdk.RGBA rgba = {
+            red:   color1.red   * (1 - progress) + color2.red   * progress,
+            green: color1.green * (1 - progress) + color2.green * progress,
+            blue:  color1.blue  * (1 - progress) + color2.blue  * progress,
+            alpha: 1
+        };
+        set_background_color (rgba);
     }
 
     [GtkCallback]
     private void on_next_button_clicked () {
-        visible_page_idx += 1;
+        var index = (int) Math.round (paginator.position) + 1;
+        if (index >= pages.length ())
+            return;
+
+        paginator.scroll_to (pages.nth_data (index));
 
     }
 
     [GtkCallback]
     private void on_back_button_clicked () {
-        visible_page_idx -= 1;
+        var index = (int) Math.round (paginator.position) - 1;
+        if (index < 0)
+            return;
+
+        paginator.scroll_to (pages.nth_data (index));
     }
 }


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