gtk-demo: Finish peg solitaire demo

The restart button was simply not implemented.
While we are at it, make the pegs a bit bigger,
so clicking them is easier.
This commit is contained in:
Matthias Clasen 2020-08-09 18:27:18 -04:00
parent da0955feeb
commit e5247b7cbb

View File

@ -6,8 +6,6 @@
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
/* Create an object for the pegs that get moved around in the game.
*
* We implement the GdkPaintable interface for them, so we can use GtkPicture
@ -56,11 +54,25 @@ solitaire_peg_get_flags (GdkPaintable *paintable)
return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
}
static int
solitaire_peg_get_intrinsic_width (GdkPaintable *paintable)
{
return 32;
}
static int
solitaire_peg_get_intrinsic_height (GdkPaintable *paintable)
{
return 32;
}
static void
solitaire_peg_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = solitaire_peg_snapshot;
iface->get_flags = solitaire_peg_get_flags;
iface->get_intrinsic_width = solitaire_peg_get_intrinsic_width;
iface->get_intrinsic_height = solitaire_peg_get_intrinsic_height;
}
/* When defining the GType, we need to implement the GdkPaintable interface */
@ -259,25 +271,99 @@ drop_drop (GtkDropTarget *target,
return TRUE;
}
static void
create_board (GtkWidget *window)
{
GtkWidget *grid;
GtkWidget *image;
int x, y;
GtkDragSource *source;
GtkDropTarget *target;
grid = gtk_grid_new ();
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
gtk_window_set_child (GTK_WINDOW (window), grid);
for (x = 0; x < 7; x++)
{
for (y = 0; y < 7; y++)
{
if ((x < 2 || x >= 5) && (y < 2 || y >= 5))
continue;
image = gtk_image_new ();
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
if (x != 3 || y != 3)
{
SolitairePeg *peg = solitaire_peg_new ();
solitaire_peg_set_position (peg, x, y);
gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (peg));
}
gtk_grid_attach (GTK_GRID (grid), image, x, y, 1, 1);
/* Set up the drag source.
* This is rather straightforward: Set the supported actions
* (in our case, pegs can only be moved) and connect all the
* relevant signals.
* And because all drag'n'drop handling is done via event controllers,
* we need to add the controller to the widget.
*/
source = gtk_drag_source_new ();
gtk_drag_source_set_actions (source, GDK_ACTION_MOVE);
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), image);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
/* Set up the drop target.
* This is more involved, because the game logic goes here.
*/
/* First we specify the data we accept: pegs.
* And we only want moves.
*/
target = gtk_drop_target_new (SOLITAIRE_TYPE_PEG, GDK_ACTION_MOVE);
/* Then we connect our signals.
*/
g_signal_connect (target, "accept", G_CALLBACK (drop_accept), image);
g_signal_connect (target, "drop", G_CALLBACK (drop_drop), image);
/* Finally, like above, we add it to the widget.
*/
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (target));
}
}
}
static void
restart_game (GtkButton *button,
GtkWidget *window)
{
create_board (window);
}
GtkWidget *
do_peg_solitaire (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *header;
GtkWidget *restart;
GtkWidget *grid;
GtkWidget *image;
int x, y;
GtkDragSource *source;
GtkDropTarget *target;
window = gtk_window_new ();
restart = gtk_button_new_from_icon_name ("view-refresh-symbolic");
g_signal_connect (restart, "clicked", G_CALLBACK (restart), NULL);
g_signal_connect (restart, "clicked", G_CALLBACK (restart_game), window);
header = gtk_header_bar_new ();
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Peg Solitaire");
@ -285,63 +371,7 @@ do_peg_solitaire (GtkWidget *do_widget)
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
grid = gtk_grid_new ();
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
gtk_window_set_child (GTK_WINDOW (window), grid);
for (x = 0; x < 7; x++)
{
for (y = 0; y < 7; y++)
{
if ((x < 2 || x >= 5) && (y < 2 || y >= 5))
continue;
image = gtk_image_new ();
if (x != 3 || y != 3)
{
SolitairePeg *peg = solitaire_peg_new ();
solitaire_peg_set_position (peg, x, y);
gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (peg));
}
gtk_grid_attach (GTK_GRID (grid), image, x, y, 1, 1);
/* Set up the drag source.
* This is rather straightforward: Set the supported actions
* (in our case, pegs can only be moved) and connect all the
* relevant signals.
* And because all drag'n'drop handling is done via event controllers,
* we need to add the controller to the widget.
*/
source = gtk_drag_source_new ();
gtk_drag_source_set_actions (source, GDK_ACTION_MOVE);
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), image);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
/* Set up the drop target.
* This is more involved, because the game logic goes here.
*/
/* First we specify the data we accept: pegs.
* And we only want moves.
*/
target = gtk_drop_target_new (SOLITAIRE_TYPE_PEG, GDK_ACTION_MOVE);
/* Then we connect our signals.
*/
g_signal_connect (target, "accept", G_CALLBACK (drop_accept), image);
g_signal_connect (target, "drop", G_CALLBACK (drop_drop), image);
/* Finally, like above, we add it to the widget.
*/
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (target));
}
}
create_board (window);
}
if (!gtk_widget_get_visible (window))