1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4struct TileData {
5 image: image,
6 image-visible: bool,
7 solved: bool,
8}
9
10component MemoryTile inherits Rectangle {
11 in property <bool> open-curtain;
12 in property <bool> solved;
13 in property <image> icon;
14
15 callback clicked;
16
17 border-radius: 8px;
18 background: root.solved ? #70ff00 : #858585;
19
20 animate background { duration: 800ms; }
21
22 Image {
23 source: root.icon;
24 width: parent.width - 16px;
25 height: parent.height - 16px;
26 x: 8px;
27 y: 8px;
28 }
29
30 // Left curtain
31 Rectangle {
32 x: 0;
33 background: #0025ff;
34 border-radius: 4px;
35 width: root.open-curtain ? 0px : parent.width / 2 + 4px;
36 height: parent.height;
37 clip: true;
38
39 animate width { duration: 250ms; easing: ease-in; }
40
41 Image {
42 width: root.width - 32px;
43 height: root.height - 32px;
44 x: 16px;
45 y: 16px;
46 source: @image-url("icons/tile_logo.png");
47 }
48 }
49
50 // Right curtain
51 right-curtain := Rectangle {
52 background: #0025ff;
53 border-radius: 4px;
54 x: root.open-curtain ? parent.width : parent.width / 2 - 4px;
55 width: root.open-curtain ? 0px : parent.width / 2 + 4px;
56 height: parent.height;
57 clip: true;
58
59 animate width { duration: 250ms; easing: ease-in; }
60 animate x { duration: 250ms; easing: ease-in; }
61
62 Image {
63 width: root.width - 32px;
64 height: root.height - 32px;
65 x: right-curtain.width - self.width - 16px;
66 y: 16px;
67 source: @image-url("icons/tile_logo.png");
68 }
69 }
70
71 TouchArea {
72 clicked => {
73 root.clicked();
74 }
75
76 width: 100%;
77 height: 100%;
78 }
79}
80
81export component MainWindow inherits Window {
82 in property <bool> disable-tiles;
83 in property <[TileData]> memory-tiles : [
84 { image: @image-url("icons/at.png") },
85 { image: @image-url("icons/balance-scale.png") },
86 { image: @image-url("icons/bicycle.png") },
87 { image: @image-url("icons/bus.png") },
88 { image: @image-url("icons/cloud.png") },
89 { image: @image-url("icons/cogs.png") },
90 { image: @image-url("icons/motorcycle.png") },
91 { image: @image-url("icons/video.png") },
92 ];
93
94 callback check-if-pair-solved();
95
96 private property <length> tile-size: 80px;
97 private property <length> tile-spacing: 10px;
98 private property <int> row-count: 4;
99 private property <int> column-count: 4;
100
101 // "column_count + 1" and "row_count + 1" are the number of gaps between the tiles.
102 width: (root.column-count * root.tile-size) + ((root.column-count + 1) * root.tile-spacing);
103 height: (root.row-count * root.tile-size) + ((root.row-count + 1) * root.tile-spacing);
104 title: "Memory Game - Slint Demo";
105
106 for tile[i] in root.memory-tiles: MemoryTile {
107 clicked => {
108 if (!root.disable-tiles) {
109 tile.image-visible = !tile.image-visible;
110 root.check-if-pair-solved();
111 }
112 }
113
114 x: root.tile-spacing + mod(i, root.column-count) * (root.tile-size + root.tile-spacing);
115 y: root.tile-spacing + floor(i / root.row-count) * (root.tile-size + root.tile-spacing);
116 width: root.tile-size;
117 height: root.tile-size;
118
119 icon: tile.image;
120
121 open-curtain: tile.image-visible || tile.solved;
122 solved: tile.solved;
123 }
124}
125