Skip to content

Commit 92dcc5f

Browse files
authored
Port 'Snapshot' demo to Vala (#179)
1 parent 34d9c65 commit 92dcc5f

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

src/Snapshot/main.vala

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#! /usr/bin/env -S vala workbench.vala --pkg libadwaita-1
2+
3+
private Chessboard chessboard;
4+
private Gtk.Box box;
5+
private Gtk.Label label;
6+
7+
public class Chessboard : Gtk.Widget {
8+
const int SQUARE_SIZE = 70;
9+
const int BOARD_SIZE = 8 * SQUARE_SIZE;
10+
const float PIECE_SIZE = 1.5f * SQUARE_SIZE;
11+
12+
private Gdk.RGBA black_squares_color;
13+
private Gdk.RGBA white_squares_color;
14+
private Gdk.RGBA knight_color;
15+
16+
private float x;
17+
private float y;
18+
private float initial_x;
19+
private float initial_y;
20+
private Gsk.Path knight_path;
21+
private Gsk.Stroke knight_stroke;
22+
private Graphene.Rect knight_bounds;
23+
private Gtk.GestureDrag gesture;
24+
private bool gesture_started = false;
25+
26+
public Chessboard() {
27+
// Initialize colors
28+
black_squares_color = Gdk.RGBA();
29+
black_squares_color.parse("Gray");
30+
white_squares_color = Gdk.RGBA();
31+
white_squares_color.parse("LightGray");
32+
knight_color = Gdk.RGBA();
33+
knight_color.parse("SaddleBrown");
34+
35+
// Initialize knight position and contour
36+
x = y = (float) 4 * SQUARE_SIZE - PIECE_SIZE / 2;
37+
initial_x = x;
38+
initial_y = y;
39+
// Made by SVG Repo: https://www.svgrepo.com/svg/380957/chess-piece-knight-strategy
40+
knight_path = Gsk.Path.parse(
41+
"M47.26,22.08c-.74-3.36-5.69-5.27-7.74-5.92l.34-4.5a1,1,0,0,0-1.74-.74L33.9,15.66c-6.45,2.23-11,6-13.39,11.19-2.9,6.19-2.2,12.94-1.29,17.06H13.71l-1.27,9.5H50.08l-1.27-9.5h-8c.85-4.13-3-10.63-5.59-14.53A5.93,5.93,0,0,0,39,28.1c2.85,1.17,9.48,2.29,10.77,2,1-.19,1.3-1.33,1.5-2.09,0-.12,0-.22,0-.23C52.4,25.82,49.64,23.63,47.26,22.08Zm-.2,23.83.74,5.5H14.72l.74-5.5h31.6Zm2.27-18.35a4.87,4.87,0,0,1-.19.63c-1.6,0-7.92-1.13-9.8-2.13a1,1,0,0,0-1.11.11,4.25,4.25,0,0,1-3.06,1.2A3.65,3.65,0,0,1,33,26.23a1,1,0,0,0-1.39-.16,1,1,0,0,0-.17,1.4C34,30.74,40.19,40,38.78,43.91H21.28c-.87-3.79-1.7-10.37,1-16.21,2.22-4.76,6.42-8.2,12.47-10.23a1,1,0,0,0,.43-.29l2.43-2.72-.18,2.36a1,1,0,0,0,.74,1c1.78.47,6.92,2.39,7.13,4.9a1,1,0,0,0,.46.76,15.42,15.42,0,0,1,3.25,2.54,2.06,2.06,0,0,1,.51.8A3,3,0,0,0,49.33,27.56Z"
42+
);
43+
knight_stroke = new Gsk.Stroke(2.0f);
44+
knight_path.get_stroke_bounds(knight_stroke, out knight_bounds);
45+
46+
// Add drag gesture and connect it to signals
47+
gesture = new Gtk.GestureDrag();
48+
add_controller(gesture);
49+
50+
gesture.drag_begin.connect(() => {
51+
var knight_hitbox = Graphene.Rect();
52+
knight_hitbox.init(initial_x, initial_y, PIECE_SIZE, PIECE_SIZE);
53+
var cursor_pos = Graphene.Point();
54+
cursor_pos.init((float) x, (float) y);
55+
gesture_started = knight_hitbox.contains_point(cursor_pos);
56+
});
57+
58+
gesture.drag_end.connect((offset_x, offset_y) => {
59+
if (!gesture_started)return;
60+
initial_x += (float) offset_x;
61+
initial_y += (float) offset_y;
62+
queue_draw();
63+
gesture_started = false;
64+
});
65+
gesture.drag_update.connect((offset_x, offset_y) => {
66+
if (!gesture_started)return;
67+
x = initial_x + (float) offset_x;
68+
y = initial_y + (float) offset_y;
69+
queue_draw();
70+
});
71+
}
72+
73+
public override void snapshot(Gtk.Snapshot snapshot) {
74+
// Draw chessboard by repeating a 2x2 block of squares
75+
var bounds = Graphene.Rect();
76+
bounds.init(0, 0, BOARD_SIZE, BOARD_SIZE);
77+
var child_bounds = Graphene.Rect();
78+
child_bounds.init(0, 0, 2 * SQUARE_SIZE, 2 * SQUARE_SIZE);
79+
snapshot.push_repeat(bounds, child_bounds); // start of repeated part
80+
81+
var r11 = Graphene.Rect();
82+
r11.init(0, 0, SQUARE_SIZE, SQUARE_SIZE);
83+
snapshot.append_color(white_squares_color, r11);
84+
85+
var r12 = Graphene.Rect();
86+
r12.init(0, SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE);
87+
snapshot.append_color(black_squares_color, r12);
88+
89+
var r21 = Graphene.Rect();
90+
r21.init(SQUARE_SIZE, 0, SQUARE_SIZE, SQUARE_SIZE);
91+
snapshot.append_color(black_squares_color, r21);
92+
93+
var r22 = Graphene.Rect();
94+
r22.init(SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE);
95+
snapshot.append_color(white_squares_color, r22);
96+
97+
snapshot.pop(); // end of repeated part
98+
99+
// Draw knight anchored on position (x, y)
100+
var anchor = Graphene.Point();
101+
anchor.init(x, y);
102+
float factor = (float) PIECE_SIZE / knight_bounds.get_width();
103+
var transformation = new Gsk.Transform().translate(anchor).scale(factor, factor);
104+
snapshot.transform(transformation);
105+
snapshot.append_stroke(knight_path, knight_stroke, knight_color);
106+
}
107+
108+
public override void measure(Gtk.Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline) {
109+
minimum = BOARD_SIZE;
110+
natural = BOARD_SIZE;
111+
minimum_baseline = -1;
112+
natural_baseline = -1;
113+
}
114+
}
115+
116+
117+
public void main() {
118+
box = (Gtk.Box) workbench.builder.get_object("box");
119+
label = (Gtk.Label) workbench.builder.get_object("label");
120+
chessboard = new Chessboard(){
121+
hexpand = true, vexpand = true
122+
};
123+
box.insert_child_after(chessboard, label);
124+
}

0 commit comments

Comments
 (0)