diff options
author | Benjamin Otte <otte@redhat.com> | 2022-06-29 00:33:14 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2022-06-29 23:53:18 +0200 |
commit | 143fd737a07a2c446571c0795cc396bfa53a56a7 (patch) | |
tree | cd06b791b831be914907074bdb6f35ab1486de49 | |
parent | 8366ba8c231ac97d9e97f27eb3986583a6e4a500 (diff) | |
download | gtk+-143fd737a07a2c446571c0795cc396bfa53a56a7.tar.gz |
demos: Add a puzzle demo
-rw-r--r-- | demos/gtk-demo/canvas_puzzle.c | 125 | ||||
-rw-r--r-- | demos/gtk-demo/demo.gresource.xml | 1 | ||||
-rw-r--r-- | demos/gtk-demo/meson.build | 1 |
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', |