comparison examples/example-ui/example-ui.c @ 415:a5b98db4fd87

misc: fix .hgignore too greedy
author David Demelier <markand@malikania.fr>
date Sun, 09 Oct 2022 13:53:33 +0200
parents
children 8f59201dc76b
comparison
equal deleted inserted replaced
414:6947c1fefe5c 415:a5b98db4fd87
1 /*
2 * example-action.c -- example on how to use automatic actions
3 *
4 * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <core/core.h>
20 #include <core/event.h>
21 #include <core/game.h>
22 #include <core/maths.h>
23 #include <core/panic.h>
24 #include <core/painter.h>
25 #include <core/state.h>
26 #include <core/sys.h>
27 #include <core/util.h>
28 #include <core/window.h>
29
30 #include <ui/align.h>
31 #include <ui/button.h>
32 #include <ui/checkbox.h>
33 #include <ui/frame.h>
34 #include <ui/label.h>
35 #include <ui/theme.h>
36 #include <ui/ui.h>
37
38 #define W (1280)
39 #define H (720)
40
41 #define FRAME_ORIGIN_X (10)
42 #define FRAME_ORIGIN_Y (10)
43 #define FRAME_WIDTH (400)
44 #define FRAME_HEIGHT (200)
45
46 #define HEADER_HEIGHT (32)
47
48 #define ELEMENT_HEIGHT (20)
49
50 /*
51 * We design a basic UI like this.
52 *
53 * FRAME_WIDTH
54 * +---------------------------------------------+--
55 * | Title | | HEADER_HEIGHT
56 * +---------------------------------------------+--
57 * | [x] Auto save |
58 * | |
59 * | |
60 * | [ Quit ] |
61 * +---------------------------------------------+
62 */
63 static struct {
64 struct {
65 int active;
66 int x;
67 int y;
68 } motion;
69
70 struct {
71 struct frame frame;
72 } panel;
73
74 struct {
75 struct label label;
76 } header;
77
78 struct {
79 struct checkbox cb;
80 struct label label;
81 } autosave;
82
83 struct {
84 struct button button;
85 } quit;
86 } ui = {
87 .panel = {
88 .frame = {
89 .x = FRAME_ORIGIN_X,
90 .y = FRAME_ORIGIN_Y,
91 .w = FRAME_WIDTH,
92 .h = FRAME_HEIGHT
93 }
94 },
95 .header = {
96 .label = {
97 .text = "Preferences",
98 .x = FRAME_ORIGIN_X,
99 .y = FRAME_ORIGIN_Y,
100 .flags = LABEL_FLAGS_SHADOW,
101 }
102 },
103 .autosave = {
104 .cb = {
105 .w = ELEMENT_HEIGHT,
106 .h = ELEMENT_HEIGHT
107 },
108 .label = {
109 .text = "Auto save game",
110 .flags = LABEL_FLAGS_SHADOW,
111 }
112 },
113 .quit = {
114 .button = {
115 .text = "Quit",
116 .h = ELEMENT_HEIGHT
117 }
118 }
119 };
120
121 static struct state *states[1];
122
123 static void
124 init(void)
125 {
126 if (core_init("fr.malikania", "example-ui") < 0 || ui_init() < 0)
127 panic();
128 if (window_open("Example - UI", W, H) < 0)
129 panic();
130 }
131
132 static void
133 resize_header(void)
134 {
135 struct frame *f = &ui.panel.frame;
136 struct label *l = &ui.header.label;
137 unsigned int w, h;
138
139 /* Header. */
140 label_query(l, &w, &h);
141 align(ALIGN_LEFT, &l->x, &l->y, w, h, f->x, f->y, f->w, HEADER_HEIGHT);
142
143 l->x += theme_default()->padding;
144 }
145
146 static void
147 resize_autosave(void)
148 {
149 unsigned int padding = theme_default()->padding;
150 struct frame *f = &ui.panel.frame;
151 struct checkbox *c = &ui.autosave.cb;
152 struct label *l = &ui.autosave.label;
153
154 c->x = f->x + padding;
155 c->y = f->y + HEADER_HEIGHT + padding;
156
157 l->x = c->x + c->w + padding;
158 l->y = c->y;
159 }
160
161 static void
162 resize_button(void)
163 {
164 unsigned int padding = theme_default()->padding;
165 struct frame *f = &ui.panel.frame;
166 struct button *b = &ui.quit.button;
167
168 /* Button. */
169 b->w = f->w / 4;
170
171 align(ALIGN_BOTTOM_RIGHT, &b->x, &b->y, b->w, b->h,
172 f->x, f->y, f->w, f->h);
173
174 b->x -= padding;
175 b->y -= padding;
176 }
177
178 static void
179 resize(void)
180 {
181 resize_header();
182 resize_autosave();
183 resize_button();
184 }
185
186 static int
187 headerclick(int x, int y)
188 {
189 return maths_is_boxed(
190 ui.panel.frame.x,
191 ui.panel.frame.y,
192 ui.panel.frame.w,
193 HEADER_HEIGHT,
194 x,
195 y
196 );
197 }
198
199 static void
200 handle(struct state *st, const union event *ev)
201 {
202 (void)st;
203
204 switch (ev->type) {
205 case EVENT_QUIT:
206 game_quit();
207 break;
208 case EVENT_MOUSE:
209 if (ui.motion.active) {
210 ui.panel.frame.x += ev->mouse.x - ui.motion.x;
211 ui.panel.frame.y += ev->mouse.y - ui.motion.y;
212 ui.motion.x = ev->mouse.x;
213 ui.motion.y = ev->mouse.y;
214 resize();
215 }
216 break;
217 case EVENT_CLICKDOWN:
218 if (headerclick(ev->click.x, ev->click.y)) {
219 ui.motion.active = 1;
220 ui.motion.x = ev->click.x;
221 ui.motion.y = ev->click.y;
222 window_set_cursor(WINDOW_CURSOR_SIZE);
223 }
224 break;
225 case EVENT_CLICKUP:
226 ui.motion.active = 0;
227 window_set_cursor(WINDOW_CURSOR_ARROW);
228 break;
229 default:
230 break;
231 }
232
233 checkbox_handle(&ui.autosave.cb, ev);
234
235 if (button_handle(&ui.quit.button, ev))
236 game_quit();
237 }
238
239 static void
240 draw(struct state *st)
241 {
242 (void)st;
243
244 painter_set_color(0xffffffff);
245 painter_clear();
246 frame_draw(&ui.panel.frame);
247 label_draw(&ui.header.label);
248 checkbox_draw(&ui.autosave.cb);
249 label_draw(&ui.autosave.label);
250 button_draw(&ui.quit.button);
251 painter_present();
252 }
253
254 static void
255 run(void)
256 {
257 struct state state = {
258 .handle = handle,
259 .draw = draw
260 };
261
262 resize();
263
264 game_init(states, UTIL_SIZE(states));
265 game_push(&state);
266 game_loop();
267 }
268
269 static void
270 quit(void)
271 {
272 window_finish();
273 ui_finish();
274 core_finish();
275 }
276
277 int
278 main(int argc, char **argv)
279 {
280 (void)argc;
281 (void)argv;
282
283 init();
284 run();
285 quit();
286
287 return 0;
288 }