[gtk/layout-manager-transform-demo: 1/2] wip: Add another layout manager demo
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/layout-manager-transform-demo: 1/2] wip: Add another layout manager demo
- Date: Sat, 29 Aug 2020 02:59:20 +0000 (UTC)
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]