summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-06-05 21:02:57 -0400
committerMatthias Clasen <mclasen@redhat.com>2018-06-07 07:59:58 -0400
commitec07349da6862f0125a8f0d06c65b19e23c7f5b7 (patch)
tree7b081ac60645bfbc46d47c4e1888385040526714
parentfae6a32629f36f702f9b4fb4803fb01e76504510 (diff)
downloadgtk+-ec07349da6862f0125a8f0d06c65b19e23c7f5b7.tar.gz
Add tweaks
Allow setting the puzzle size, and allow chosing between the rose and the radioactive animation. Change the default size to 3. 6 is just too hard.
-rw-r--r--demos/gtk-demo/sliding_puzzle.c257
1 files changed, 246 insertions, 11 deletions
diff --git a/demos/gtk-demo/sliding_puzzle.c b/demos/gtk-demo/sliding_puzzle.c
index f7615fc15e..09671024dc 100644
--- a/demos/gtk-demo/sliding_puzzle.c
+++ b/demos/gtk-demo/sliding_puzzle.c
@@ -9,13 +9,179 @@
/* Include the header for the puzzle piece */
#include "puzzlepiece.h"
+#include "paintable.h"
+
+#define ICON_TYPE_PAINTABLE (icon_paintable_get_type ())
+
+G_DECLARE_FINAL_TYPE (IconPaintable, icon_paintable, ICON, PAINTABLE, GObject)
+
+GdkPaintable * icon_paintable_new (GdkPaintable *paintable,
+ double height);
+
+struct _IconPaintable
+{
+ GObject parent_instance;
+
+ GdkPaintable *paintable;
+ double height;
+ double scale_factor;
+};
+
+struct _IconPaintableClass
+{
+ GObjectClass parent_class;
+};
+
+
+static void
+icon_paintable_paintable_snapshot (GdkPaintable *paintable,
+ GdkSnapshot *snapshot,
+ double width,
+ double height)
+{
+ IconPaintable *self = ICON_PAINTABLE (paintable);
+
+ if (self->scale_factor == 1.0)
+ {
+ gdk_paintable_snapshot (self->paintable, snapshot, width, height);
+ }
+ else
+ {
+ graphene_matrix_t scale_matrix;
+
+ graphene_matrix_init_scale (&scale_matrix, 1.0 / self->scale_factor, 1.0 / self->scale_factor, 1.0);
+ gtk_snapshot_push_transform (snapshot, &scale_matrix);
+ gdk_paintable_snapshot (self->paintable,
+ snapshot,
+ width * self->scale_factor,
+ height * self->scale_factor);
+ gtk_snapshot_pop (snapshot);
+ }
+}
+
+static GdkPaintable *
+icon_paintable_paintable_get_current_image (GdkPaintable *paintable)
+{
+ IconPaintable *self = ICON_PAINTABLE (paintable);
+ GdkPaintable *current_paintable, *current_self;
+
+ current_paintable = gdk_paintable_get_current_image (self->paintable);
+ current_self = icon_paintable_new (current_paintable, self->height);
+ g_object_unref (current_paintable);
+
+ return current_self;
+}
+
+static GdkPaintableFlags
+icon_paintable_paintable_get_flags (GdkPaintable *paintable)
+{
+ IconPaintable *self = ICON_PAINTABLE (paintable);
+
+ return gdk_paintable_get_flags (self->paintable);
+}
+
+static int
+icon_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
+{
+ IconPaintable *self = ICON_PAINTABLE (paintable);
+
+ return gdk_paintable_get_intrinsic_width (self->paintable) / self->scale_factor;
+}
+
+static int
+icon_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
+{
+ IconPaintable *self = ICON_PAINTABLE (paintable);
+
+ return gdk_paintable_get_intrinsic_height (self->paintable) / self->scale_factor;
+}
+
+static double icon_paintable_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
+{
+ IconPaintable *self = ICON_PAINTABLE (paintable);
+
+ return gdk_paintable_get_intrinsic_aspect_ratio (self->paintable);
+};
+
+static void
+icon_paintable_paintable_init (GdkPaintableInterface *iface)
+{
+ iface->snapshot = icon_paintable_paintable_snapshot;
+ iface->get_current_image = icon_paintable_paintable_get_current_image;
+ iface->get_flags = icon_paintable_paintable_get_flags;
+ iface->get_intrinsic_width = icon_paintable_paintable_get_intrinsic_width;
+ iface->get_intrinsic_height = icon_paintable_paintable_get_intrinsic_height;
+ iface->get_intrinsic_aspect_ratio = icon_paintable_paintable_get_intrinsic_aspect_ratio;
+}
+
+G_DEFINE_TYPE_EXTENDED (IconPaintable, icon_paintable, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+ icon_paintable_paintable_init))
+
+static void
+icon_paintable_dispose (GObject *object)
+{
+ IconPaintable *self = ICON_PAINTABLE (object);
+
+ if (self->paintable)
+ {
+ g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_contents, self);
+ g_signal_handlers_disconnect_by_func (self->paintable, gdk_paintable_invalidate_size, self);
+ g_clear_object (&self->paintable);
+ }
+
+ G_OBJECT_CLASS (icon_paintable_parent_class)->dispose (object);
+}
+
+static void
+icon_paintable_class_init (IconPaintableClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = icon_paintable_dispose;
+}
+
+static void
+icon_paintable_init (IconPaintable *self)
+{
+ self->scale_factor = 1.0;
+}
+
+GdkPaintable *
+icon_paintable_new (GdkPaintable *paintable,
+ double height)
+{
+ IconPaintable *self;
+
+ g_return_val_if_fail (GDK_IS_PAINTABLE (paintable), NULL);
+ g_return_val_if_fail (height > 0.0, NULL);
+
+ self = g_object_new (ICON_TYPE_PAINTABLE, NULL);
+
+ self->paintable = g_object_ref (paintable);
+ g_signal_connect_swapped (paintable, "invalidate-contents", G_CALLBACK (gdk_paintable_invalidate_contents), self);
+ g_signal_connect_swapped (paintable, "invalidate-size", G_CALLBACK (gdk_paintable_invalidate_size), self);
+ self->height = height;
+ if (gdk_paintable_get_intrinsic_height (paintable) == 0)
+ self->scale_factor = 1.0;
+ else
+ self->scale_factor = gdk_paintable_get_intrinsic_height (paintable) / height;
+
+ return GDK_PAINTABLE (self);
+}
+
static GtkWidget *window = NULL;
static GtkWidget *frame = NULL;
+static GtkWidget *size_spin = NULL;
+static GtkWidget *rose_button = NULL;
+static GdkPaintable *puzzle = NULL;
+static GdkPaintable *rose = NULL;
+static GdkPaintable *atom = NULL;
static gboolean solved = TRUE;
-static guint width = 6;
-static guint height = 6;
+static guint width = 3;
+static guint height = 3;
static guint pos_x;
static guint pos_y;
@@ -280,24 +446,98 @@ reshuffle (void)
GtkWidget *grid;
grid = gtk_bin_get_child (GTK_BIN (frame));
- shuffle_puzzle (grid);
+ if (solved)
+ start_puzzle (puzzle);
+ else
+ shuffle_puzzle (grid);
+ gtk_widget_grab_focus (grid);
+}
+
+static void
+reconfigure (void)
+{
+ GtkWidget *popover;
+ GtkWidget *grid;
+
+ width = height = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (size_spin));
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (rose_button)))
+ puzzle = rose;
+ else
+ puzzle= atom;
+
+ start_puzzle (puzzle);
+ popover = gtk_widget_get_ancestor (size_spin, GTK_TYPE_POPOVER);
+ gtk_popover_popdown (GTK_POPOVER (popover));
+ grid = gtk_bin_get_child (GTK_BIN (frame));
+ gtk_widget_grab_focus (grid);
}
GtkWidget *
do_sliding_puzzle (GtkWidget *do_widget)
{
- GdkPaintable *puzzle;
-
if (!window)
{
GtkWidget *header;
GtkWidget *restart;
-
+ GtkWidget *tweak;
+ GtkWidget *popover;
+ GtkWidget *tweaks;
+ GtkWidget *apply;
+ GtkWidget *image;
+ GtkWidget *button;
+ GtkWidget *label;
+
+ rose = GDK_PAINTABLE (gdk_texture_new_from_resource ("/sliding_puzzle/portland-rose.jpg"));
+ atom = gtk_nuclear_animation_new ();
+
+ puzzle = rose;
+
+ tweaks = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (tweaks), 10);
+ gtk_grid_set_column_spacing (GTK_GRID (tweaks), 10);
+ g_object_set (tweaks, "margin", 10, NULL);
+
+ rose_button = button = gtk_radio_button_new (NULL);
+ image = gtk_image_new_from_paintable (icon_paintable_new (rose, 40));
+ gtk_image_set_can_shrink (GTK_IMAGE (image), TRUE);
+ gtk_widget_set_size_request (image, 40, 40);
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+ gtk_grid_attach (GTK_GRID (tweaks), button, 0, 0, 1, 1);
+
+ button = gtk_radio_button_new_from_widget (button);
+ image = gtk_image_new_from_paintable (icon_paintable_new (atom, 40));
+ gtk_image_set_can_shrink (GTK_IMAGE (image), TRUE);
+ gtk_widget_set_size_request (image, 40, 40);
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
+ gtk_grid_attach (GTK_GRID (tweaks), button, 1, 0, 1, 1);
+
+ label = gtk_label_new ("Size");
+ gtk_label_set_xalign (label, 0.0);
+ gtk_grid_attach (GTK_GRID (tweaks), label, 0, 1, 1, 1);
+ size_spin = gtk_spin_button_new_with_range (2, 10, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (size_spin), width);
+ gtk_grid_attach (GTK_GRID (tweaks), size_spin, 1, 1, 1, 1);
+
+ apply = gtk_button_new_with_label ("Apply");
+ gtk_widget_set_halign (apply, GTK_ALIGN_END);
+ gtk_grid_attach (GTK_GRID (tweaks), apply, 1, 2, 1, 1);
+ g_signal_connect (apply, "clicked", G_CALLBACK (reconfigure), NULL);
+ popover = gtk_popover_new (NULL);
+ gtk_popover_set_modal (GTK_POPOVER (popover), TRUE);
+ gtk_container_add (GTK_CONTAINER (popover), tweaks);
restart = gtk_button_new_from_icon_name ("view-refresh-symbolic");
g_signal_connect (restart, "clicked", G_CALLBACK (reshuffle), NULL);
+ tweak = gtk_menu_button_new ();
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (tweak), popover);
+ gtk_button_set_icon_name (tweak, "emblem-system-symbolic");
+
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
+ gtk_header_bar_pack_end (GTK_HEADER_BAR (header), tweak);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -307,15 +547,10 @@ do_sliding_puzzle (GtkWidget *do_widget)
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
- puzzle = GDK_PAINTABLE (gdk_texture_new_from_resource ("/sliding_puzzle/portland-rose.jpg"));
-
frame = gtk_aspect_frame_new (NULL, 0.5, 0.5, (float) gdk_paintable_get_intrinsic_aspect_ratio (puzzle), FALSE);
gtk_container_add (GTK_CONTAINER (window), frame);
- /* Start a puzzle with a default image */
-
start_puzzle (puzzle);
- g_object_unref (puzzle);
}
if (!gtk_widget_get_visible (window))