forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
547d63d56a
commit
a849ffbd79
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user