source: mainline/uspace/lib/ui/src/msgdialog.c

Last change on this file was a188131, checked in by Jiri Svoboda <jiri@…>, 3 months ago

Add UI to system installer

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libui
30 * @{
31 */
32/**
33 * @file Message dialog
34 */
35
36#include <errno.h>
37#include <mem.h>
38#include <stdlib.h>
39#include <ui/fixed.h>
40#include <ui/label.h>
41#include <ui/msgdialog.h>
42#include <ui/pbutton.h>
43#include <ui/resource.h>
44#include <ui/ui.h>
45#include <ui/window.h>
46#include "../private/msgdialog.h"
47
48static void ui_msg_dialog_wnd_close(ui_window_t *, void *);
49static void ui_msg_dialog_wnd_kbd(ui_window_t *, void *, kbd_event_t *);
50
51ui_window_cb_t ui_msg_dialog_wnd_cb = {
52 .close = ui_msg_dialog_wnd_close,
53 .kbd = ui_msg_dialog_wnd_kbd
54};
55
56static void ui_msg_dialog_btn_clicked(ui_pbutton_t *, void *);
57
58ui_pbutton_cb_t ui_msg_dialog_btn_cb = {
59 .clicked = ui_msg_dialog_btn_clicked
60};
61
62static const char *ui_msg_dialog_captions[][ui_msg_dialog_maxbtn + 1] = {
63 [umdc_ok] = { "OK", NULL },
64 [umdc_ok_cancel] = { "OK", "Cancel", NULL }
65};
66
67/** Initialize message dialog parameters structure.
68 *
69 * Message dialog parameters structure must always be initialized using
70 * this function first.
71 *
72 * @param params Message dialog parameters structure
73 */
74void ui_msg_dialog_params_init(ui_msg_dialog_params_t *params)
75{
76 memset(params, 0, sizeof(ui_msg_dialog_params_t));
77}
78
79/** Create new message dialog.
80 *
81 * @param ui User interface
82 * @param params Message dialog parameters
83 * @param rdialog Place to store pointer to new dialog
84 * @return EOK on success or an error code
85 */
86errno_t ui_msg_dialog_create(ui_t *ui, ui_msg_dialog_params_t *params,
87 ui_msg_dialog_t **rdialog)
88{
89 errno_t rc;
90 ui_msg_dialog_t *dialog;
91 ui_window_t *window = NULL;
92 ui_wnd_params_t wparams;
93 ui_fixed_t *fixed = NULL;
94 ui_label_t *label = NULL;
95 ui_pbutton_t *btn[ui_msg_dialog_maxbtn];
96 const char **cp;
97 unsigned i, nb;
98 gfx_rect_t rect;
99 gfx_coord_t bw, bpad, btnsw, bp0x;
100 ui_resource_t *ui_res;
101
102 for (i = 0; i < ui_msg_dialog_maxbtn; i++)
103 btn[i] = NULL;
104
105 dialog = calloc(1, sizeof(ui_msg_dialog_t));
106 if (dialog == NULL) {
107 rc = ENOMEM;
108 goto error;
109 }
110
111 ui_wnd_params_init(&wparams);
112 wparams.caption = params->caption;
113 if ((params->flags & umdf_topmost) != 0)
114 wparams.flags |= wndf_topmost;
115 if ((params->flags & umdf_center) != 0)
116 wparams.placement = ui_wnd_place_center;
117
118 /* FIXME: Auto layout */
119 if (ui_is_textmode(ui)) {
120 wparams.rect.p0.x = 0;
121 wparams.rect.p0.y = 0;
122 wparams.rect.p1.x = 60;
123 wparams.rect.p1.y = 7;
124 } else {
125 wparams.rect.p0.x = 0;
126 wparams.rect.p0.y = 0;
127 wparams.rect.p1.x = 440;
128 wparams.rect.p1.y = 110;
129 }
130
131 rc = ui_window_create(ui, &wparams, &window);
132 if (rc != EOK)
133 goto error;
134
135 ui_window_set_cb(window, &ui_msg_dialog_wnd_cb, dialog);
136
137 ui_res = ui_window_get_res(window);
138
139 rc = ui_fixed_create(&fixed);
140 if (rc != EOK)
141 goto error;
142
143 rc = ui_label_create(ui_res, params->text, &label);
144 if (rc != EOK)
145 goto error;
146
147 /* FIXME: Auto layout */
148 if (ui_is_textmode(ui)) {
149 rect.p0.x = 3;
150 rect.p0.y = 2;
151 rect.p1.x = 57;
152 rect.p1.y = 3;
153 } else {
154 rect.p0.x = 10;
155 rect.p0.y = 35;
156 rect.p1.x = 430;
157 rect.p1.y = 50;
158 }
159
160 ui_label_set_rect(label, &rect);
161 ui_label_set_halign(label, gfx_halign_center);
162
163 rc = ui_fixed_add(fixed, ui_label_ctl(label));
164 if (rc != EOK)
165 goto error;
166
167 label = NULL;
168
169 i = 0;
170 assert(params->choice == umdc_ok || params->choice == umdc_ok_cancel);
171 cp = ui_msg_dialog_captions[params->choice];
172
173 while (*cp != NULL) {
174 rc = ui_pbutton_create(ui_res, *cp, &btn[i]);
175 if (rc != EOK)
176 goto error;
177
178 ui_pbutton_set_cb(btn[i], &ui_msg_dialog_btn_cb, dialog);
179 ++cp;
180 ++i;
181 }
182
183 nb = i;
184
185 if (ui_is_textmode(ui)) {
186 bw = 12;
187 bpad = 2;
188 } else {
189 bw = 90;
190 bpad = 10;
191 }
192
193 btnsw = (nb - 1) * (bw + bpad) + bw;
194 bp0x = (wparams.rect.p0.x + wparams.rect.p1.x - btnsw) / 2;
195
196 for (i = 0; i < nb; i++) {
197 /* FIXME: Auto layout */
198 if (ui_is_textmode(ui)) {
199 rect.p0.x = bp0x + i * (bw + bpad);
200 rect.p0.y = 4;
201 rect.p1.x = bp0x + bw + i * (bw + bpad);
202 rect.p1.y = 5;
203 } else {
204 rect.p0.x = bp0x + i * (bw + bpad);
205 rect.p0.y = 60;
206 rect.p1.x = bp0x + bw + i * (bw + bpad);
207 rect.p1.y = 88;
208 }
209
210 ui_pbutton_set_rect(btn[i], &rect);
211
212 rc = ui_fixed_add(fixed, ui_pbutton_ctl(btn[i]));
213 if (rc != EOK)
214 goto error;
215 }
216
217 ui_pbutton_set_default(btn[0], true);
218
219 for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
220 dialog->btn[i] = btn[i];
221 btn[i] = NULL;
222 }
223
224 ui_window_add(window, ui_fixed_ctl(fixed));
225 fixed = NULL;
226
227 rc = ui_window_paint(window);
228 if (rc != EOK)
229 goto error;
230
231 dialog->window = window;
232 *rdialog = dialog;
233 return EOK;
234error:
235 for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
236 if (btn[i] != NULL)
237 ui_pbutton_destroy(btn[i]);
238 }
239 if (label != NULL)
240 ui_label_destroy(label);
241 if (fixed != NULL)
242 ui_fixed_destroy(fixed);
243 if (window != NULL)
244 ui_window_destroy(window);
245 if (dialog != NULL)
246 free(dialog);
247 return rc;
248}
249
250/** Destroy message dialog.
251 *
252 * @param dialog Message dialog or @c NULL
253 */
254void ui_msg_dialog_destroy(ui_msg_dialog_t *dialog)
255{
256 if (dialog == NULL)
257 return;
258
259 ui_window_destroy(dialog->window);
260 free(dialog);
261}
262
263/** Set mesage dialog callback.
264 *
265 * @param dialog Message dialog
266 * @param cb Message dialog callbacks
267 * @param arg Callback argument
268 */
269void ui_msg_dialog_set_cb(ui_msg_dialog_t *dialog, ui_msg_dialog_cb_t *cb,
270 void *arg)
271{
272 dialog->cb = cb;
273 dialog->arg = arg;
274}
275
276/** Message dialog window close handler.
277 *
278 * @param window Window
279 * @param arg Argument (ui_msg_dialog_t *)
280 */
281static void ui_msg_dialog_wnd_close(ui_window_t *window, void *arg)
282{
283 ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
284
285 if (dialog->cb != NULL && dialog->cb->close != NULL)
286 dialog->cb->close(dialog, dialog->arg);
287}
288
289/** Message dialog window keyboard event handler.
290 *
291 * @param window Window
292 * @param arg Argument (ui_msg_dialog_t *)
293 * @param event Keyboard event
294 */
295static void ui_msg_dialog_wnd_kbd(ui_window_t *window, void *arg,
296 kbd_event_t *event)
297{
298 ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
299 ui_evclaim_t claim;
300
301 claim = ui_window_def_kbd(window, event);
302 if (claim == ui_claimed)
303 return;
304
305 if (event->type == KEY_PRESS &&
306 (event->mods & (KM_CTRL | KM_SHIFT | KM_ALT)) == 0) {
307 if (event->key == KC_ENTER) {
308 /* OK / default button */
309 if (dialog->cb != NULL && dialog->cb->button != NULL) {
310 dialog->cb->button(dialog, dialog->arg, 0);
311 return;
312 }
313 } else if (event->key == KC_ESCAPE) {
314 /* Cancel */
315 if (dialog->cb != NULL && dialog->cb->close != NULL) {
316 dialog->cb->close(dialog, dialog->arg);
317 return;
318 }
319 }
320 }
321
322}
323
324/** Message dialog button click handler.
325 *
326 * @param pbutton Push button
327 * @param arg Argument (ui_msg_dialog_t *)
328 */
329static void ui_msg_dialog_btn_clicked(ui_pbutton_t *pbutton, void *arg)
330{
331 ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
332 unsigned i;
333
334 if (dialog->cb != NULL && dialog->cb->button != NULL) {
335 for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
336 if (dialog->btn[i] == pbutton)
337 dialog->cb->button(dialog, dialog->arg, i);
338 }
339 }
340}
341
342/** @}
343 */
Note: See TracBrowser for help on using the repository browser.