Mercurial > molko
comparison libmlk-ui/mlk/ui/notify.c @ 433:862b15c3a3ae
ui: cleanup hierarchy
author | David Demelier <markand@malikania.fr> |
---|---|
date | Sat, 15 Oct 2022 21:19:25 +0200 |
parents | src/libmlk-ui/ui/notify.c@8f59201dc76b |
children | 773a082f0b91 |
comparison
equal
deleted
inserted
replaced
432:38cf60f5a1c4 | 433:862b15c3a3ae |
---|---|
1 /* | |
2 * notify.c -- in game notifications | |
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 <assert.h> | |
20 #include <stddef.h> | |
21 #include <string.h> | |
22 | |
23 #include <mlk/core/font.h> | |
24 #include <mlk/core/texture.h> | |
25 #include <mlk/core/trace.h> | |
26 #include <mlk/core/window.h> | |
27 | |
28 #include "align.h" | |
29 #include "frame.h" | |
30 #include "label.h" | |
31 #include "notify.h" | |
32 #include "theme.h" | |
33 | |
34 #define WIDTH (window.w / 3) | |
35 #define HEIGHT (window.h / 10) | |
36 | |
37 struct geo { | |
38 const struct theme *theme; | |
39 int frame_x; | |
40 int frame_y; | |
41 unsigned int frame_w; | |
42 unsigned int frame_h; | |
43 int icon_x; | |
44 int icon_y; | |
45 int title_x; | |
46 int title_y; | |
47 int body_x; | |
48 int body_y; | |
49 }; | |
50 | |
51 static void draw(const struct notify *, size_t); | |
52 | |
53 static const struct notify_system default_system = { | |
54 .draw = draw | |
55 }; | |
56 static const struct notify_system *system = &default_system; | |
57 static struct notify stack[NOTIFY_MAX]; | |
58 static size_t stacksz; | |
59 | |
60 static void | |
61 geometry(struct geo *geo, const struct notify *n, size_t index) | |
62 { | |
63 int x, y; | |
64 | |
65 /* Determine theme. */ | |
66 geo->theme = system->theme ? system->theme : theme_default(); | |
67 | |
68 /* Determine notification position. */ | |
69 x = window.w - geo->theme->padding; | |
70 x -= WIDTH; | |
71 | |
72 y = geo->theme->padding * (index + 1);; | |
73 y += HEIGHT * index; | |
74 | |
75 /* Content frame. */ | |
76 geo->frame_x = x; | |
77 geo->frame_y = y; | |
78 geo->frame_w = WIDTH; | |
79 geo->frame_h = HEIGHT; | |
80 | |
81 /* Align icon at the left center. */ | |
82 if (n->icon->h >= HEIGHT) { | |
83 tracef("notification icon is too large: %u > %u", n->icon->h, HEIGHT); | |
84 geo->icon_x = x + geo->theme->padding; | |
85 geo->icon_y = y + geo->theme->padding; | |
86 } else { | |
87 align(ALIGN_LEFT, &geo->icon_x, &geo->icon_y, n->icon->w, n->icon->h, x, y, WIDTH, HEIGHT); | |
88 geo->icon_x += geo->icon_y - y; | |
89 } | |
90 | |
91 /* Align title to the right of the icon at the same y coordinate. */ | |
92 geo->title_x = geo->icon_x + n->icon->w + geo->theme->padding; | |
93 geo->title_y = geo->icon_y; | |
94 geo->title_y -= font_height(geo->theme->fonts[THEME_FONT_IMPORTANT]) / 2; | |
95 | |
96 /* Align body so it ends at the end of the icon. */ | |
97 geo->body_x = geo->title_x; | |
98 geo->body_y = geo->icon_y + n->icon->h; | |
99 geo->body_y -= font_height(geo->theme->fonts[THEME_FONT_INTERFACE]) / 2; | |
100 } | |
101 | |
102 static void | |
103 draw_frame(const struct geo *geo) | |
104 { | |
105 const struct frame f = { | |
106 .x = geo->frame_x, | |
107 .y = geo->frame_y, | |
108 .w = geo->frame_w, | |
109 .h = geo->frame_h | |
110 }; | |
111 | |
112 frame_draw(&f); | |
113 } | |
114 | |
115 static void | |
116 draw_icon(const struct geo *geo, const struct notify *n) | |
117 { | |
118 texture_draw(n->icon, geo->icon_x, geo->icon_y); | |
119 } | |
120 | |
121 #include <stdio.h> | |
122 | |
123 static void | |
124 draw_title(const struct geo *geo, const struct notify *n) | |
125 { | |
126 const struct label l = { | |
127 .x = geo->title_x, | |
128 .y = geo->title_y, | |
129 .text = n->title, | |
130 .flags = LABEL_FLAGS_SHADOW | LABEL_FLAGS_IMPORTANT | |
131 }; | |
132 | |
133 label_draw(&l); | |
134 } | |
135 | |
136 static void | |
137 draw_body(const struct geo *geo, const struct notify *n) | |
138 { | |
139 const struct label l = { | |
140 .x = geo->body_x, | |
141 .y = geo->body_y, | |
142 .text = n->body, | |
143 .flags = LABEL_FLAGS_SHADOW | |
144 }; | |
145 | |
146 label_draw(&l); | |
147 } | |
148 | |
149 static void | |
150 draw(const struct notify *n, size_t index) | |
151 { | |
152 struct geo geo; | |
153 | |
154 /* Compute notification size and widgets. */ | |
155 geometry(&geo, n, index); | |
156 | |
157 draw_frame(&geo); | |
158 draw_icon(&geo, n); | |
159 draw_title(&geo, n); | |
160 draw_body(&geo, n); | |
161 } | |
162 | |
163 void | |
164 notify(const struct texture *icon, const char *title, const char *body) | |
165 { | |
166 assert(icon); | |
167 assert(title); | |
168 assert(body); | |
169 | |
170 struct notify *n; | |
171 | |
172 if (stacksz >= NOTIFY_MAX) { | |
173 memmove(&stack[0], &stack[1], sizeof (stack[0]) - NOTIFY_MAX - 1); | |
174 n = &stack[NOTIFY_MAX - 1]; | |
175 } else | |
176 n = &stack[stacksz++]; | |
177 | |
178 memset(n, 0, sizeof (*n)); | |
179 n->icon = icon; | |
180 n->title = title; | |
181 n->body = body; | |
182 } | |
183 | |
184 void | |
185 notify_update(unsigned int ticks) | |
186 { | |
187 struct notify *n; | |
188 | |
189 for (size_t i = 0; i < stacksz; ++i) { | |
190 n = &stack[i]; | |
191 n->elapsed += ticks; | |
192 | |
193 if (n->elapsed >= NOTIFY_TIMEOUT_DEFAULT) | |
194 memmove(n, n + 1, sizeof (*n) * (--stacksz - i)); | |
195 } | |
196 } | |
197 | |
198 void | |
199 notify_draw(void) | |
200 { | |
201 for (size_t i = 0; i < stacksz; ++i) | |
202 system->draw(&stack[i], i); | |
203 } | |
204 | |
205 void | |
206 notify_set_system(const struct notify_system *sys) | |
207 { | |
208 system = sys ? sys : &default_system; | |
209 } |