[gtk/layout-manager-transform-demo] layoutmanager demo: Add keynav



commit e5be887bb353ac7232d2d1e4490d35d583740c10
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Aug 29 01:08:05 2020 -0400

    layoutmanager demo: Add keynav

 demos/gtk-demo/demo2layout.c    |  43 ++++++++++++++--
 demos/gtk-demo/demo2layout.h    |   4 ++
 demos/gtk-demo/demo2widget.c    | 108 ++++++++++++++++++++++++++++++++--------
 demos/gtk-demo/layoutmanager2.c |   2 +-
 4 files changed, 129 insertions(+), 28 deletions(-)
---
diff --git a/demos/gtk-demo/demo2layout.c b/demos/gtk-demo/demo2layout.c
index f0dedf5e68..1ecaf55361 100644
--- a/demos/gtk-demo/demo2layout.c
+++ b/demos/gtk-demo/demo2layout.c
@@ -6,6 +6,7 @@ struct _Demo2Layout
   GtkLayoutManager parent_instance;
 
   float position;
+  float offset;
 };
 
 struct _Demo2LayoutClass
@@ -57,6 +58,15 @@ demo2_layout_measure (GtkLayoutManager *layout_manager,
 #define SZ(r,t,p) ((r) * sin (t) * sin (p))
 #define SY(r,t,p) ((r) * cos (t))
 
+static double
+map_offset (double x)
+{
+  if (x == 180)
+    return x;
+
+  return fmod (x, 180.0);
+}
+
 static void
 demo2_layout_allocate (GtkLayoutManager *layout_manager,
                        GtkWidget        *widget,
@@ -75,7 +85,8 @@ demo2_layout_allocate (GtkLayoutManager *layout_manager,
   double r;
   graphene_matrix_t m;
   GskTransform *transform;
-  double offset = DEMO2_LAYOUT (layout_manager)->position;
+  double position = DEMO2_LAYOUT (layout_manager)->position;
+  double offset = DEMO2_LAYOUT (layout_manager)->offset;
 
   gtk_widget_get_preferred_size (gtk_widget_get_first_child (widget), &child_req, NULL);
   w = child_req.width;
@@ -96,10 +107,13 @@ demo2_layout_allocate (GtkLayoutManager *layout_manager,
       graphene_point3d_init (&p3, 0., h, 1);
       graphene_point3d_init (&p4, w, h, 1);
 
-      t_1 = RADIANS (10 * j);
-      t_2 = RADIANS (10 * (j + 1));
-      p_1 = RADIANS (offset + 10 * k);
-      p_2 = RADIANS (offset + 10 * (k + 1));
+      t_1 = RADIANS (map_offset (offset + 10 * j));
+      t_2 = RADIANS (map_offset (offset + 10 * (j + 1)));
+      p_1 = RADIANS (position + 10 * k);
+      p_2 = RADIANS (position + 10 * (k + 1));
+
+      if (t_2 < t_1)
+        continue;
 
       if (SZ (r, t_1, p_1) > 0)
         continue;
@@ -159,3 +173,22 @@ demo2_layout_set_position (Demo2Layout *layout,
 {
   layout->position = position;
 }
+
+float
+demo2_layout_get_position (Demo2Layout *layout)
+{
+  return layout->position;
+}
+
+void
+demo2_layout_set_offset (Demo2Layout *layout,
+                         float        offset)
+{
+  layout->offset = offset;
+}
+
+float
+demo2_layout_get_offset (Demo2Layout *layout)
+{
+  return layout->offset;
+}
diff --git a/demos/gtk-demo/demo2layout.h b/demos/gtk-demo/demo2layout.h
index 832f2b65dd..4bb84ab241 100644
--- a/demos/gtk-demo/demo2layout.h
+++ b/demos/gtk-demo/demo2layout.h
@@ -10,3 +10,7 @@ GtkLayoutManager * demo2_layout_new          (void);
 
 void               demo2_layout_set_position (Demo2Layout *layout,
                                               float        position);
+float              demo2_layout_get_position (Demo2Layout *layout);
+void               demo2_layout_set_offset   (Demo2Layout *layout,
+                                              float        offset);
+float              demo2_layout_get_offset   (Demo2Layout *layout);
diff --git a/demos/gtk-demo/demo2widget.c b/demos/gtk-demo/demo2widget.c
index 661b701a66..40714be77d 100644
--- a/demos/gtk-demo/demo2widget.c
+++ b/demos/gtk-demo/demo2widget.c
@@ -8,7 +8,12 @@ struct _Demo2Widget
   GtkWidget parent_instance;
 
   gint64 start_time; /* time the transition started */
-  guint tick_id;     /* our tick cb */
+  gint64 end_time;
+  float start_position;
+  float end_position;
+  float start_offset;
+  float end_offset;
+  gboolean animating;
 };
 
 struct _Demo2WidgetClass
@@ -18,30 +23,10 @@ struct _Demo2WidgetClass
 
 G_DEFINE_TYPE (Demo2Widget, demo2_widget, GTK_TYPE_WIDGET)
 
-/* The widget is controlling the transition by calling
- * demo_layout_set_position() in a tick callback.
- */
-
-static gboolean
-transition (GtkWidget     *widget,
-            GdkFrameClock *frame_clock,
-            gpointer       data)
-{
-  Demo2Widget *self = DEMO2_WIDGET (widget);
-  Demo2Layout *demo2_layout = DEMO2_LAYOUT (gtk_widget_get_layout_manager (widget));
-  gint64 now = g_get_monotonic_time ();
-
-  gtk_widget_queue_allocate (widget);
-  demo2_layout_set_position (demo2_layout, (now - self->start_time) * 30.0 / ((double)G_TIME_SPAN_SECOND));
-
-  return G_SOURCE_CONTINUE;
-}
-
 static void
 demo2_widget_init (Demo2Widget *self)
 {
-  self->start_time = g_get_monotonic_time ();
-  self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self), transition, NULL, NULL);
+  gtk_widget_set_focusable (GTK_WIDGET (self), TRUE);
 }
 
 static void
@@ -55,6 +40,78 @@ demo2_widget_dispose (GObject *object)
   G_OBJECT_CLASS (demo2_widget_parent_class)->dispose (object);
 }
 
+/* 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 gboolean
+update_position (GtkWidget     *widget,
+                 GdkFrameClock *clock,
+                 gpointer       data)
+{
+  Demo2Widget *self = DEMO2_WIDGET (widget);
+  Demo2Layout *layout = DEMO2_LAYOUT (gtk_widget_get_layout_manager (widget));
+  gint64 now;
+
+  now = gdk_frame_clock_get_frame_time (clock);
+
+  if (now < self->end_time)
+    {
+      double t;
+
+      t = (now - self->start_time) / (double) (self->end_time - self->start_time);
+
+      t = ease_out_cubic (t);
+
+      demo2_layout_set_position (layout, self->start_position + t * (self->end_position - 
self->start_position));
+      demo2_layout_set_offset (layout, self->start_offset + t * (self->end_offset - self->start_offset));
+      gtk_widget_queue_allocate (widget);
+
+      return G_SOURCE_CONTINUE;
+    }
+  else
+    {
+      self->animating = FALSE;
+
+      return G_SOURCE_REMOVE;
+    }
+}
+
+static void
+rotate_sphere (GtkWidget  *widget,
+               const char *action,
+               GVariant   *parameters)
+{
+  Demo2Widget *self = DEMO2_WIDGET (widget);
+  Demo2Layout *layout = DEMO2_LAYOUT (gtk_widget_get_layout_manager (widget));
+  GtkOrientation orientation;
+  int direction;
+
+  g_variant_get (parameters, "(ii)", &orientation, &direction);
+
+  self->end_position = self->start_position = demo2_layout_get_position (layout);
+  self->end_offset = self->start_offset = demo2_layout_get_offset (layout);
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    self->end_position += 10 * direction;
+  else
+    self->end_offset += 10 * direction;
+  self->start_time = g_get_monotonic_time ();
+  self->end_time = self->start_time + 0.5 * G_TIME_SPAN_SECOND;
+
+  if (!self->animating)
+    {
+      gtk_widget_add_tick_callback (widget, update_position, NULL, NULL);
+      self->animating = TRUE;
+    }
+}
+
 static void
 demo2_widget_class_init (Demo2WidgetClass *class)
 {
@@ -63,6 +120,13 @@ demo2_widget_class_init (Demo2WidgetClass *class)
 
   object_class->dispose = demo2_widget_dispose;
 
+  gtk_widget_class_install_action (widget_class, "rotate", "(ii)", rotate_sphere);
+
+  gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Left, 0, "rotate", "(ii)", 
GTK_ORIENTATION_HORIZONTAL, -1);
+  gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Right, 0, "rotate", "(ii)", 
GTK_ORIENTATION_HORIZONTAL, 1);
+  gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Up, 0, "rotate", "(ii)", 
GTK_ORIENTATION_VERTICAL, -1);
+  gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Down, 0, "rotate", "(ii)", 
GTK_ORIENTATION_VERTICAL, 1);
+
   /* here is where we use our custom layout manager */
   gtk_widget_class_set_layout_manager_type (widget_class, DEMO2_TYPE_LAYOUT);
 }
diff --git a/demos/gtk-demo/layoutmanager2.c b/demos/gtk-demo/layoutmanager2.c
index ba48a4f1fd..24dfb24014 100644
--- a/demos/gtk-demo/layoutmanager2.c
+++ b/demos/gtk-demo/layoutmanager2.c
@@ -179,7 +179,7 @@ do_layoutmanager2 (GtkWidget *parent)
 
       window = gtk_window_new ();
       gtk_window_set_title (GTK_WINDOW (window), "Transformation");
-      gtk_window_set_default_size (GTK_WINDOW (window), 200, 100);
+      gtk_window_set_default_size (GTK_WINDOW (window), 600, 660);
       g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
 
       widget = demo2_widget_new ();


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