source: mainline/uspace/lib/ui/src/msgdialog.c@ 9a07ee3

Last change on this file since 9a07ee3 was 9a07ee3, checked in by Jiri Svoboda <jiri@…>, 8 months ago

Add message dialog choice selection (OK, OK/Cancel)

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Copyright (c) 2024 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 *);
49
50ui_window_cb_t ui_msg_dialog_wnd_cb = {
51 .close = ui_msg_dialog_wnd_close
52};
53
54static void ui_msg_dialog_btn_clicked(ui_pbutton_t *, void *);
55
56ui_pbutton_cb_t ui_msg_dialog_btn_cb = {
57 .clicked = ui_msg_dialog_btn_clicked
58};
59
60static const char *ui_msg_dialog_captions[][ui_msg_dialog_maxbtn + 1] = {
61 [umdc_ok] = { "OK", NULL },
62 [umdc_ok_cancel] = { "OK", "Cancel", NULL }
63};
64
65/** Initialize message dialog parameters structure.
66 *
67 * Message dialog parameters structure must always be initialized using
68 * this function first.
69 *
70 * @param params Message dialog parameters structure
71 */
72void ui_msg_dialog_params_init(ui_msg_dialog_params_t *params)
73{
74 memset(params, 0, sizeof(ui_msg_dialog_params_t));
75}
76
77/** Create new message dialog.
78 *
79 * @param ui User interface
80 * @param params Message dialog parameters
81 * @param rdialog Place to store pointer to new dialog
82 * @return EOK on success or an error code
83 */
84errno_t ui_msg_dialog_create(ui_t *ui, ui_msg_dialog_params_t *params,
85 ui_msg_dialog_t **rdialog)
86{
87 errno_t rc;
88 ui_msg_dialog_t *dialog;
89 ui_window_t *window = NULL;
90 ui_wnd_params_t wparams;
91 ui_fixed_t *fixed = NULL;
92 ui_label_t *label = NULL;
93 ui_pbutton_t *btn[ui_msg_dialog_maxbtn];
94 const char **cp;
95 unsigned i, nb;
96 gfx_rect_t rect;
97 gfx_coord_t bw, bpad, btnsw, bp0x;
98 ui_resource_t *ui_res;
99
100 for (i = 0; i < ui_msg_dialog_maxbtn; i++)
101 btn[i] = NULL;
102
103 dialog = calloc(1, sizeof(ui_msg_dialog_t));
104 if (dialog == NULL) {
105 rc = ENOMEM;
106 goto error;
107 }
108
109 ui_wnd_params_init(&wparams);
110 wparams.caption = params->caption;
111
112 /* FIXME: Auto layout */
113 if (ui_is_textmode(ui)) {
114 wparams.rect.p0.x = 0;
115 wparams.rect.p0.y = 0;
116 wparams.rect.p1.x = 60;
117 wparams.rect.p1.y = 7;
118 } else {
119 wparams.rect.p0.x = 0;
120 wparams.rect.p0.y = 0;
121 wparams.rect.p1.x = 400;
122 wparams.rect.p1.y = 110;
123 }
124
125 rc = ui_window_create(ui, &wparams, &window);
126 if (rc != EOK)
127 goto error;
128
129 ui_window_set_cb(window, &ui_msg_dialog_wnd_cb, dialog);
130
131 ui_res = ui_window_get_res(window);
132
133 rc = ui_fixed_create(&fixed);
134 if (rc != EOK)
135 goto error;
136
137 rc = ui_label_create(ui_res, params->text, &label);
138 if (rc != EOK)
139 goto error;
140
141 /* FIXME: Auto layout */
142 if (ui_is_textmode(ui)) {
143 rect.p0.x = 3;
144 rect.p0.y = 2;
145 rect.p1.x = 57;
146 rect.p1.y = 3;
147 } else {
148 rect.p0.x = 10;
149 rect.p0.y = 35;
150 rect.p1.x = 390;
151 rect.p1.y = 50;
152 }
153
154 ui_label_set_rect(label, &rect);
155 ui_label_set_halign(label, gfx_halign_center);
156
157 rc = ui_fixed_add(fixed, ui_label_ctl(label));
158 if (rc != EOK)
159 goto error;
160
161 label = NULL;
162
163 i = 0;
164 assert(params->choice == umdc_ok || params->choice == umdc_ok_cancel);
165 cp = ui_msg_dialog_captions[params->choice];
166
167 while (*cp != NULL) {
168 rc = ui_pbutton_create(ui_res, *cp, &btn[i]);
169 if (rc != EOK)
170 goto error;
171
172 ui_pbutton_set_cb(btn[i], &ui_msg_dialog_btn_cb, dialog);
173 ++cp;
174 ++i;
175 }
176
177 nb = i;
178
179 if (ui_is_textmode(ui)) {
180 bw = 12;
181 bpad = 2;
182 } else {
183 bw = 90;
184 bpad = 10;
185 }
186
187 btnsw = (nb - 1) * (bw + bpad) + bw;
188 bp0x = (wparams.rect.p0.x + wparams.rect.p1.x - btnsw) / 2;
189
190 for (i = 0; i < nb; i++) {
191 /* FIXME: Auto layout */
192 if (ui_is_textmode(ui)) {
193 rect.p0.x = bp0x + i * (bw + bpad);
194 rect.p0.y = 4;
195 rect.p1.x = bp0x + bw + i * (bw + bpad);
196 rect.p1.y = 5;
197 } else {
198 rect.p0.x = bp0x + i * (bw + bpad);
199 rect.p0.y = 60;
200 rect.p1.x = bp0x + bw + i * (bw + bpad);
201 rect.p1.y = 88;
202 }
203
204 ui_pbutton_set_rect(btn[i], &rect);
205
206 rc = ui_fixed_add(fixed, ui_pbutton_ctl(btn[i]));
207 if (rc != EOK)
208 goto error;
209 }
210
211 ui_pbutton_set_default(btn[0], true);
212
213 for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
214 dialog->btn[i] = btn[i];
215 btn[i] = NULL;
216 }
217
218 ui_window_add(window, ui_fixed_ctl(fixed));
219 fixed = NULL;
220
221 rc = ui_window_paint(window);
222 if (rc != EOK)
223 goto error;
224
225 dialog->window = window;
226 *rdialog = dialog;
227 return EOK;
228error:
229 for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
230 if (btn[i] != NULL)
231 ui_pbutton_destroy(btn[i]);
232 }
233 if (label != NULL)
234 ui_label_destroy(label);
235 if (fixed != NULL)
236 ui_fixed_destroy(fixed);
237 if (window != NULL)
238 ui_window_destroy(window);
239 if (dialog != NULL)
240 free(dialog);
241 return rc;
242}
243
244/** Destroy message dialog.
245 *
246 * @param dialog Message dialog or @c NULL
247 */
248void ui_msg_dialog_destroy(ui_msg_dialog_t *dialog)
249{
250 if (dialog == NULL)
251 return;
252
253 ui_window_destroy(dialog->window);
254 free(dialog);
255}
256
257/** Set mesage dialog callback.
258 *
259 * @param dialog Message dialog
260 * @param cb Message dialog callbacks
261 * @param arg Callback argument
262 */
263void ui_msg_dialog_set_cb(ui_msg_dialog_t *dialog, ui_msg_dialog_cb_t *cb,
264 void *arg)
265{
266 dialog->cb = cb;
267 dialog->arg = arg;
268}
269
270/** Message dialog window close handler.
271 *
272 * @param window Window
273 * @param arg Argument (ui_msg_dialog_t *)
274 */
275static void ui_msg_dialog_wnd_close(ui_window_t *window, void *arg)
276{
277 ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
278
279 if (dialog->cb != NULL && dialog->cb->close != NULL)
280 dialog->cb->close(dialog, dialog->arg);
281}
282
283/** Message dialog button click handler.
284 *
285 * @param pbutton Push button
286 * @param arg Argument (ui_msg_dialog_t *)
287 */
288static void ui_msg_dialog_btn_clicked(ui_pbutton_t *pbutton, void *arg)
289{
290 ui_msg_dialog_t *dialog = (ui_msg_dialog_t *) arg;
291 unsigned i;
292
293 if (dialog->cb != NULL && dialog->cb->button != NULL) {
294 for (i = 0; i < ui_msg_dialog_maxbtn; i++) {
295 if (dialog->btn[i] == pbutton)
296 dialog->cb->button(dialog, dialog->arg, i);
297 }
298 }
299}
300
301/** @}
302 */
Note: See TracBrowser for help on using the repository browser.