[gtk/layout-manager-transform-demo] layoutmanager demo: Add keynav
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/layout-manager-transform-demo] layoutmanager demo: Add keynav
- Date: Sat, 29 Aug 2020 16:13:17 +0000 (UTC)
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]