summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2022-06-29 00:33:14 +0200
committerBenjamin Otte <otte@redhat.com>2022-06-29 23:53:18 +0200
commit143fd737a07a2c446571c0795cc396bfa53a56a7 (patch)
treecd06b791b831be914907074bdb6f35ab1486de49
parent8366ba8c231ac97d9e97f27eb3986583a6e4a500 (diff)
downloadgtk+-143fd737a07a2c446571c0795cc396bfa53a56a7.tar.gz
demos: Add a puzzle demo
-rw-r--r--demos/gtk-demo/canvas_puzzle.c125
-rw-r--r--demos/gtk-demo/demo.gresource.xml1
-rw-r--r--demos/gtk-demo/meson.build1
3 files changed, 94 insertions, 33 deletions
diff --git a/demos/gtk-demo/canvas_puzzle.c b/demos/gtk-demo/canvas_puzzle.c
index 8fae9fa177..07b0d5f66d 100644
--- a/demos/gtk-demo/canvas_puzzle.c
+++ b/demos/gtk-demo/canvas_puzzle.c
@@ -7,66 +7,125 @@
#include <gtk/gtk.h>
-#define WIDTH 400
-#define HEIGHT 300
+#include "puzzlepiece.h"
static void
-bind_item (GtkListItemFactory *factory,
- GtkCanvasItem *ci)
+set_item_position (GtkCanvasItem *ci,
+ float x,
+ float y)
{
GtkCanvasPoint *point;
GtkCanvasSize *size;
- GtkCanvasBox *box;
+ GtkCanvasBox *box, *viewport;
- widget = gtk_picture_new_for_paintable (gtk_canvas_item_get_item (ci));
- gtk_canvas_item_set_widget (ci, widget);
+ x = CLAMP (x, 0, 1);
+ y = CLAMP (y, 0, 1);
+
+ point = gtk_canvas_point_new (0, 0);
+ viewport = gtk_canvas_box_new (point,
+ gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
+ 0.0, 0.0);
+ gtk_canvas_point_free (point);
+
+ point = gtk_canvas_point_new_from_box (viewport, x, y, 0, 0);
+ gtk_canvas_box_free (viewport);
+ size = gtk_canvas_size_new (0, 0);
+ box = gtk_canvas_box_new (point, size, x, y);
+ gtk_canvas_point_free (point);
+ gtk_canvas_size_free (size);
- /* Also cener the item, so we do something interesting */
- point = gtk_canvas_point_new (WIDTH / 2.0, HEIGHT / 2.0);
- size = gtk_canvas_size_new_measure_item (ci, GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN);
- box = gtk_canvas_box_new (point, size, 0.5, 0.5);
gtk_canvas_item_set_bounds (ci, box);
gtk_canvas_box_free (box);
- gtk_canvas_size_free (size);
- gtk_canvas_point_free (point);
+}
+
+static void
+move_item (GtkGestureDrag *gesture,
+ double x,
+ double y,
+ GtkCanvasItem *ci)
+{
+ GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
+ graphene_rect_t bounds;
+
+ if (!gtk_canvas_box_eval (gtk_canvas_item_get_bounds (ci), &bounds))
+ return;
+
+ set_item_position (ci,
+ (bounds.origin.x + x) / (gtk_widget_get_width (GTK_WIDGET (canvas)) - bounds.size.width),
+ (bounds.origin.y + y) / (gtk_widget_get_height (GTK_WIDGET (canvas)) - bounds.size.height));
+}
+
+static void
+bind_item (GtkListItemFactory *factory,
+ GtkCanvasItem *ci)
+{
+ GtkWidget *widget;
+ GtkGesture *gesture;
+
+ widget = gtk_picture_new_for_paintable (gtk_canvas_item_get_item (ci));
+ gtk_picture_set_can_shrink (GTK_PICTURE (widget), FALSE);
+ gesture = gtk_gesture_drag_new ();
+ g_signal_connect (gesture, "drag-update", G_CALLBACK (move_item), ci);
+ g_signal_connect (gesture, "drag-end", G_CALLBACK (move_item), ci);
+ gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
+ gtk_canvas_item_set_widget (ci, widget);
+
+ /* Also center the item, so we do something interesting */
+ set_item_position (ci, g_random_double (), g_random_double ());
+}
+
+static GListModel *
+create_puzzle (GdkPaintable *puzzle)
+{
+ GListStore *store = g_list_store_new (GDK_TYPE_PAINTABLE);
+ int width = 5;
+ int height = 5;
+ int x, y;
+
+ /* add a picture for every cell */
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ GdkPaintable *piece;
+
+ piece = gtk_puzzle_piece_new (puzzle,
+ x, y,
+ width, height);
+ g_list_store_append (store, piece);
+ g_object_unref (piece);
+ }
+ }
+
+ return G_LIST_MODEL (store);
}
GtkWidget *
-do_canvas_intro (GtkWidget *do_widget)
+do_canvas_puzzle (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
- GtkWidget *canvas, *widget;
- GListStore *store;
+ GtkWidget *canvas;
+ GListModel *model;
GtkListItemFactory *factory;
+ GdkPaintable *puzzle;
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
- gtk_window_set_default_size (GTK_WINDOW (window), WIDTH, HEIGHT);
+ gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
- /* GtkCanvas manages its items using an external list.
- * We do a very simple thing and put the widgets in the list
- * that the canvas should display.
- */
- store = g_list_store_new (GTK_TYPE_WIDGET);
- widget = gtk_label_new ("Hello World");
- g_list_store_append (store, widget);
-
- /* GtkCanvas maps the items from the list to the canvas using factories.
- * Set up a simple factory here that just maps the widget directly
- * onto the canvas.
- */
+ puzzle = GDK_PAINTABLE (gdk_texture_new_from_resource ("/sliding_puzzle/portland-rose.jpg"));
+ model = create_puzzle (puzzle);
+ g_object_unref (puzzle);
+
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
- /* Create the canvas.
- * We hand it the factory and the model, and then everything happens by itself.
- */
- canvas = gtk_canvas_new (G_LIST_MODEL (store), factory);
+ canvas = gtk_canvas_new (model, factory);
gtk_window_set_child (GTK_WINDOW (window), canvas);
}
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index ef3cb889b6..e1edcf303b 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -255,6 +255,7 @@
<file>assistant.c</file>
<file>builder.c</file>
<file>canvas_intro.c</file>
+ <file>canvas_puzzle.c</file>
<file>clipboard.c</file>
<file>combobox.c</file>
<file>constraints.c</file>
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 20c1b9e25f..293c488827 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -5,6 +5,7 @@ demos = files([
'assistant.c',
'builder.c',
'canvas_intro.c',
+ 'canvas_puzzle.c',
'clipboard.c',
'combobox.c',
'constraints.c',