[gtk/layout-manager-transform-demo: 1/2] wip: Add another layout manager demo




commit 71f2bb12b90abc67a16f69ec0a2d3bd5652226ef
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Aug 27 07:16:38 2020 -0400

    wip: Add another layout manager demo

 demos/gtk-demo/demo2layout.c    | 138 ++++++++++++++++++++++++++++++++++++++++
 demos/gtk-demo/demo2layout.h    |  12 ++++
 demos/gtk-demo/demo2widget.c    |  81 +++++++++++++++++++++++
 demos/gtk-demo/demo2widget.h    |  11 ++++
 demos/gtk-demo/layoutmanager.c  |   2 +-
 demos/gtk-demo/layoutmanager2.c |  46 ++++++++++++++
 demos/gtk-demo/meson.build      |   5 +-
 7 files changed, 293 insertions(+), 2 deletions(-)
---
diff --git a/demos/gtk-demo/demo2layout.c b/demos/gtk-demo/demo2layout.c
new file mode 100644
index 0000000000..9eaae52a60
--- /dev/null
+++ b/demos/gtk-demo/demo2layout.c
@@ -0,0 +1,138 @@
+#include "demo2layout.h"
+
+
+struct _Demo2Layout
+{
+  GtkLayoutManager parent_instance;
+
+  float position;
+};
+
+struct _Demo2LayoutClass
+{
+  GtkLayoutManagerClass parent_class;
+};
+
+G_DEFINE_TYPE (Demo2Layout, demo2_layout, GTK_TYPE_LAYOUT_MANAGER)
+
+static void
+demo2_layout_measure (GtkLayoutManager *layout_manager,
+                      GtkWidget        *widget,
+                      GtkOrientation    orientation,
+                      int               for_size,
+                      int              *minimum,
+                      int              *natural,
+                      int              *minimum_baseline,
+                      int              *natural_baseline)
+{
+  GtkWidget *child;
+  int minimum_size = 0;
+  int natural_size = 0;
+
+  for (child = gtk_widget_get_first_child (widget);
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child))
+    {
+      int child_min = 0, child_nat = 0;
+
+      if (!gtk_widget_should_layout (child))
+        continue;
+
+      gtk_widget_measure (child, orientation, -1,
+                          &child_min, &child_nat,
+                          NULL, NULL);
+      minimum_size = MAX (minimum_size, child_min);
+      natural_size = MAX (natural_size, child_nat);
+    }
+
+  *minimum = minimum_size;
+  *natural = 3 * natural_size;
+}
+
+static void
+demo2_layout_allocate (GtkLayoutManager *layout_manager,
+                       GtkWidget        *widget,
+                       int               width,
+                       int               height,
+                       int               baseline)
+{
+  Demo2Layout *self = DEMO2_LAYOUT (layout_manager);
+  GtkWidget *child;
+  float t = fmodf (self->position, 4.0);
+  int x, y;
+
+  for (child = gtk_widget_get_first_child (widget);
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child))
+    {
+      GtkRequisition child_req;
+
+      if (!gtk_widget_should_layout (child))
+        continue;
+
+      gtk_widget_get_preferred_size (child, &child_req, NULL);
+
+      if (t < 1.0)
+        {
+          x = t * (width - child_req.width);
+          y = 0;
+        }
+      else if (t < 2.0)
+        {
+          t -= 1.0;
+          x = (1.0 - t) * (width - child_req.width);
+          y = t * (height - child_req.height);
+        }
+      else if (t < 3.0)
+        {
+          t -= 2.0;
+          x = t * (width - child_req.width);
+          y = height - child_req.height;
+        }
+      else
+        {
+          t -= 3.0;
+          x = (1.0 - t) * (width - child_req.width);
+          y = (1.0 - t) * (height - child_req.height);
+        }
+
+      gtk_widget_size_allocate (child,
+                                &(const GtkAllocation){ x, y, child_req.width, child_req.height},
+                                -1);
+    }
+}
+
+static GtkSizeRequestMode
+demo2_layout_get_request_mode (GtkLayoutManager *layout_manager,
+                               GtkWidget        *widget)
+{
+  return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+static void
+demo2_layout_class_init (Demo2LayoutClass *klass)
+{
+  GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (klass);
+
+  layout_class->get_request_mode = demo2_layout_get_request_mode;
+  layout_class->measure = demo2_layout_measure;
+  layout_class->allocate = demo2_layout_allocate;
+}
+
+static void
+demo2_layout_init (Demo2Layout *self)
+{
+}
+
+GtkLayoutManager *
+demo2_layout_new (void)
+{
+  return g_object_new (DEMO2_TYPE_LAYOUT, NULL);
+}
+
+void
+demo2_layout_set_position (Demo2Layout *layout,
+                           float        position)
+{
+  layout->position = position;
+}
diff --git a/demos/gtk-demo/demo2layout.h b/demos/gtk-demo/demo2layout.h
new file mode 100644
index 0000000000..832f2b65dd
--- /dev/null
+++ b/demos/gtk-demo/demo2layout.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <gtk/gtk.h>
+
+#define DEMO2_TYPE_LAYOUT (demo2_layout_get_type ())
+
+G_DECLARE_FINAL_TYPE (Demo2Layout, demo2_layout, DEMO2, LAYOUT, GtkLayoutManager)
+
+GtkLayoutManager * demo2_layout_new          (void);
+
+void               demo2_layout_set_position (Demo2Layout *layout,
+                                              float        position);
diff --git a/demos/gtk-demo/demo2widget.c b/demos/gtk-demo/demo2widget.c
new file mode 100644
index 0000000000..e8e200dd1c
--- /dev/null
+++ b/demos/gtk-demo/demo2widget.c
@@ -0,0 +1,81 @@
+#include "demo2widget.h"
+#include "demo2layout.h"
+
+/* parent widget */
+
+struct _Demo2Widget
+{
+  GtkWidget parent_instance;
+
+  gint64 start_time; /* time the transition started */
+  guint tick_id;     /* our tick cb */
+};
+
+struct _Demo2WidgetClass
+{
+  GtkWidgetClass parent_class;
+};
+
+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) / (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);
+}
+
+static void
+demo2_widget_dispose (GObject *object)
+{
+  GtkWidget *child;
+
+  while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
+    gtk_widget_unparent (child);
+
+  G_OBJECT_CLASS (demo2_widget_parent_class)->dispose (object);
+}
+
+static void
+demo2_widget_class_init (Demo2WidgetClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+  object_class->dispose = demo2_widget_dispose;
+
+  /* here is where we use our custom layout manager */
+  gtk_widget_class_set_layout_manager_type (widget_class, DEMO2_TYPE_LAYOUT);
+}
+
+GtkWidget *
+demo2_widget_new (void)
+{
+  return g_object_new (DEMO2_TYPE_WIDGET, NULL);
+}
+
+void
+demo2_widget_add_child (Demo2Widget *self,
+                        GtkWidget  *child)
+{
+  gtk_widget_set_parent (child, GTK_WIDGET (self));
+}
diff --git a/demos/gtk-demo/demo2widget.h b/demos/gtk-demo/demo2widget.h
new file mode 100644
index 0000000000..54529f95c1
--- /dev/null
+++ b/demos/gtk-demo/demo2widget.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <gtk/gtk.h>
+
+#define DEMO2_TYPE_WIDGET (demo2_widget_get_type ())
+G_DECLARE_FINAL_TYPE (Demo2Widget, demo2_widget, DEMO2, WIDGET, GtkWidget)
+
+GtkWidget * demo2_widget_new       (void);
+
+void        demo2_widget_add_child (Demo2Widget *self,
+                                    GtkWidget  *child);
diff --git a/demos/gtk-demo/layoutmanager.c b/demos/gtk-demo/layoutmanager.c
index 3a715d0fc8..e7a065c574 100644
--- a/demos/gtk-demo/layoutmanager.c
+++ b/demos/gtk-demo/layoutmanager.c
@@ -1,4 +1,4 @@
-/* Layout Manager
+/* Layout Manager/Transition
  *
  * This examples shows a simple example of a custom layout manager
  * and a widget using it. The layout manager places the children
diff --git a/demos/gtk-demo/layoutmanager2.c b/demos/gtk-demo/layoutmanager2.c
new file mode 100644
index 0000000000..97ed89fcee
--- /dev/null
+++ b/demos/gtk-demo/layoutmanager2.c
@@ -0,0 +1,46 @@
+/* Layout Manager/Transformation
+ *
+ * This examples shows a simple example of a custom layout manager
+ * and a widget using it. The layout manager places the children
+ * of the widget in a grid or a circle, or something in between.
+ *
+ * The widget is animating the transition between the two layouts.
+ * Click to start the transition.
+ */
+
+#include <gtk/gtk.h>
+
+#include "demo2widget.h"
+
+GtkWidget *
+do_layoutmanager2 (GtkWidget *parent)
+{
+  static GtkWidget *window = NULL;
+
+  if (!window)
+    {
+      GtkWidget *widget;
+      GtkWidget *child;
+
+      window = gtk_window_new ();
+      gtk_window_set_title (GTK_WINDOW (window), "Transformation");
+      gtk_window_set_default_size (GTK_WINDOW (window), 200, 100);
+      g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
+
+      widget = demo2_widget_new ();
+
+      child =  gtk_button_new_with_label ("Hello");
+      gtk_widget_set_cursor_from_name (child, "crosshair");
+      demo2_widget_add_child (DEMO2_WIDGET (widget), child);
+
+      gtk_window_set_child (GTK_WINDOW (window), widget);
+    }
+
+  if (!gtk_widget_get_visible (window))
+    gtk_widget_show (window);
+  else
+    gtk_window_destroy (GTK_WINDOW (window));
+
+  return window;
+
+}
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 2ef7a443aa..358868d54e 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -39,6 +39,7 @@ demos = files([
   'images.c',
   'infobar.c',
   'layoutmanager.c',
+  'layoutmanager2.c',
   'links.c',
   'listbox.c',
   'listbox2.c',
@@ -103,7 +104,9 @@ extra_demo_sources = files(['main.c',
                             'demotaggedentry.c',
                             'demochild.c',
                             'demolayout.c',
-                            'demowidget.c'])
+                            'demowidget.c',
+                            'demo2layout.c',
+                            'demo2widget.c'])
 
 if harfbuzz_dep.found() and pangoft_dep.found()
   demos += files('font_features.c')


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