Mercurial > molko
comparison examples/example-ui/main.c @ 209:23a844fdc911
examples: move all into subdirectories, closes #2513
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 11 Nov 2020 17:10:40 +0100 |
parents | examples/example-ui.c@133926e08d6e |
children | 76afe639fd72 |
comparison
equal
deleted
inserted
replaced
208:c0e0d4accae8 | 209:23a844fdc911 |
---|---|
1 /* | |
2 * example-action.c -- example on how to use automatic actions | |
3 * | |
4 * Copyright (c) 2020 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/action.h> | |
20 #include <core/core.h> | |
21 #include <core/event.h> | |
22 #include <core/game.h> | |
23 #include <core/maths.h> | |
24 #include <core/panic.h> | |
25 #include <core/painter.h> | |
26 #include <core/state.h> | |
27 #include <core/sys.h> | |
28 #include <core/util.h> | |
29 #include <core/window.h> | |
30 | |
31 #include <ui/align.h> | |
32 #include <ui/button.h> | |
33 #include <ui/checkbox.h> | |
34 #include <ui/frame.h> | |
35 #include <ui/label.h> | |
36 #include <ui/theme.h> | |
37 #include <ui/ui.h> | |
38 | |
39 #define W (1280) | |
40 #define H (720) | |
41 | |
42 #define FRAME_ORIGIN_X (10) | |
43 #define FRAME_ORIGIN_Y (10) | |
44 #define FRAME_WIDTH (400) | |
45 #define FRAME_HEIGHT (200) | |
46 | |
47 #define HEADER_HEIGHT (32) | |
48 | |
49 #define ELEMENT_HEIGHT (20) | |
50 | |
51 /* | |
52 * We design a basic UI like this. | |
53 * | |
54 * FRAME_WIDTH | |
55 * +---------------------------------------------+-- | |
56 * | Title | | HEADER_HEIGHT | |
57 * +---------------------------------------------+-- | |
58 * | [x] Auto save | | |
59 * | | | |
60 * | | | |
61 * | [ Quit ] | | |
62 * +---------------------------------------------+ | |
63 */ | |
64 static struct { | |
65 struct action_stack st; | |
66 | |
67 struct { | |
68 bool active; | |
69 int x; | |
70 int y; | |
71 } motion; | |
72 | |
73 struct { | |
74 struct frame frame; | |
75 struct action act; | |
76 } panel; | |
77 | |
78 struct { | |
79 struct label label; | |
80 struct action act; | |
81 } header; | |
82 | |
83 struct { | |
84 struct checkbox cb; | |
85 struct action cb_act; | |
86 struct label label; | |
87 struct action label_act; | |
88 } autosave; | |
89 | |
90 struct { | |
91 struct button button; | |
92 struct action act; | |
93 } quit; | |
94 } ui = { | |
95 .panel = { | |
96 .frame = { | |
97 .x = FRAME_ORIGIN_X, | |
98 .y = FRAME_ORIGIN_Y, | |
99 .w = FRAME_WIDTH, | |
100 .h = FRAME_HEIGHT | |
101 } | |
102 }, | |
103 .header = { | |
104 .label = { | |
105 .text = "Preferences", | |
106 .x = FRAME_ORIGIN_X, | |
107 .y = FRAME_ORIGIN_Y, | |
108 .flags = LABEL_FLAGS_SHADOW, | |
109 } | |
110 }, | |
111 .autosave = { | |
112 .cb = { | |
113 .w = ELEMENT_HEIGHT, | |
114 .h = ELEMENT_HEIGHT | |
115 }, | |
116 .label = { | |
117 .text = "Auto save game", | |
118 .flags = LABEL_FLAGS_SHADOW, | |
119 } | |
120 }, | |
121 .quit = { | |
122 .button = { | |
123 .text = "Quit", | |
124 .h = ELEMENT_HEIGHT | |
125 } | |
126 } | |
127 }; | |
128 | |
129 static void | |
130 init(void) | |
131 { | |
132 if (!core_init() || !ui_init()) | |
133 panic(); | |
134 if (!window_open("Example - UI", W, H)) | |
135 panic(); | |
136 } | |
137 | |
138 static void | |
139 resize_header(void) | |
140 { | |
141 struct frame *f = &ui.panel.frame; | |
142 struct label *l = &ui.header.label; | |
143 unsigned int w, h; | |
144 | |
145 /* Header. */ | |
146 label_query(l, &w, &h); | |
147 align(ALIGN_LEFT, &l->x, &l->y, w, h, f->x, f->y, f->w, HEADER_HEIGHT); | |
148 | |
149 l->x += theme_default()->padding; | |
150 } | |
151 | |
152 static void | |
153 resize_autosave(void) | |
154 { | |
155 unsigned int padding = theme_default()->padding; | |
156 struct frame *f = &ui.panel.frame; | |
157 struct checkbox *c = &ui.autosave.cb; | |
158 struct label *l = &ui.autosave.label; | |
159 | |
160 c->x = f->x + padding; | |
161 c->y = f->y + HEADER_HEIGHT + padding; | |
162 | |
163 l->x = c->x + c->w + padding; | |
164 l->y = c->y; | |
165 } | |
166 | |
167 static void | |
168 resize_button(void) | |
169 { | |
170 unsigned int padding = theme_default()->padding; | |
171 struct frame *f = &ui.panel.frame; | |
172 struct button *b = &ui.quit.button; | |
173 | |
174 /* Button. */ | |
175 b->w = f->w / 4; | |
176 | |
177 align(ALIGN_BOTTOM_RIGHT, &b->x, &b->y, b->w, b->h, | |
178 f->x, f->y, f->w, f->h); | |
179 | |
180 b->x -= padding; | |
181 b->y -= padding; | |
182 } | |
183 | |
184 static void | |
185 resize(void) | |
186 { | |
187 resize_header(); | |
188 resize_autosave(); | |
189 resize_button(); | |
190 } | |
191 | |
192 static void | |
193 prepare(void) | |
194 { | |
195 /* Frame. */ | |
196 frame_action(&ui.panel.frame, &ui.panel.act); | |
197 | |
198 /* Header title. */ | |
199 label_action(&ui.header.label, &ui.header.act); | |
200 | |
201 /* Button quit. */ | |
202 button_action(&ui.quit.button, &ui.quit.act); | |
203 | |
204 /* Autosave. */ | |
205 checkbox_action(&ui.autosave.cb, &ui.autosave.cb_act); | |
206 label_action(&ui.autosave.label, &ui.autosave.label_act); | |
207 | |
208 /* Add all UI elements. */ | |
209 action_stack_add(&ui.st, &ui.panel.act); | |
210 action_stack_add(&ui.st, &ui.header.act); | |
211 action_stack_add(&ui.st, &ui.autosave.cb_act); | |
212 action_stack_add(&ui.st, &ui.autosave.label_act); | |
213 action_stack_add(&ui.st, &ui.quit.act); | |
214 } | |
215 | |
216 static bool | |
217 headerclick(int x, int y) | |
218 { | |
219 return maths_is_boxed( | |
220 ui.panel.frame.x, | |
221 ui.panel.frame.y, | |
222 ui.panel.frame.w, | |
223 HEADER_HEIGHT, | |
224 x, | |
225 y | |
226 ); | |
227 } | |
228 | |
229 static void | |
230 handle(struct state *st, const union event *ev) | |
231 { | |
232 (void)st; | |
233 | |
234 switch (ev->type) { | |
235 case EVENT_QUIT: | |
236 game_quit(); | |
237 break; | |
238 case EVENT_MOUSE: | |
239 if (ui.motion.active) { | |
240 ui.panel.frame.x += ev->mouse.x - ui.motion.x; | |
241 ui.panel.frame.y += ev->mouse.y - ui.motion.y; | |
242 ui.motion.x = ev->mouse.x; | |
243 ui.motion.y = ev->mouse.y; | |
244 resize(); | |
245 } | |
246 break; | |
247 case EVENT_CLICKDOWN: | |
248 if (headerclick(ev->click.x, ev->click.y)) { | |
249 ui.motion.active = true; | |
250 ui.motion.x = ev->click.x; | |
251 ui.motion.y = ev->click.y; | |
252 window_set_cursor(WINDOW_CURSOR_SIZE); | |
253 } | |
254 else | |
255 action_stack_handle(&ui.st, ev); | |
256 break; | |
257 case EVENT_CLICKUP: | |
258 ui.motion.active = false; | |
259 window_set_cursor(WINDOW_CURSOR_ARROW); | |
260 /* Fallthrough. */ | |
261 default: | |
262 action_stack_handle(&ui.st, ev); | |
263 break; | |
264 } | |
265 } | |
266 | |
267 static void | |
268 update(struct state *st, unsigned int ticks) | |
269 { | |
270 (void)st; | |
271 | |
272 if (ui.quit.button.state == BUTTON_STATE_ACTIVATED) | |
273 game_quit(); | |
274 else | |
275 action_stack_update(&ui.st, ticks); | |
276 } | |
277 | |
278 static void | |
279 draw(struct state *st) | |
280 { | |
281 (void)st; | |
282 | |
283 painter_set_color(0xffffffff); | |
284 painter_clear(); | |
285 action_stack_draw(&ui.st); | |
286 painter_present(); | |
287 } | |
288 | |
289 static void | |
290 run(void) | |
291 { | |
292 struct state state = { | |
293 .handle = handle, | |
294 .update = update, | |
295 .draw = draw | |
296 }; | |
297 | |
298 prepare(); | |
299 resize(); | |
300 | |
301 game_switch(&state, true); | |
302 game_loop(); | |
303 } | |
304 | |
305 static void | |
306 quit(void) | |
307 { | |
308 window_finish(); | |
309 ui_finish(); | |
310 core_finish(); | |
311 } | |
312 | |
313 int | |
314 main(int argc, char **argv) | |
315 { | |
316 (void)argc; | |
317 (void)argv; | |
318 | |
319 init(); | |
320 run(); | |
321 quit(); | |
322 | |
323 return 0; | |
324 } |