Mercurial > molko
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 } |