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

Last change on this file was 0ae9e18, checked in by Jiri Svoboda <jiri@…>, 4 months ago

Select shutdown action (power off / restart) in shutdown dialog.

  • Property mode set to 100644
File size: 10.5 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 Select 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/list.h>
42#include <ui/selectdialog.h>
43#include <ui/pbutton.h>
44#include <ui/resource.h>
45#include <ui/ui.h>
46#include <ui/window.h>
47#include "../private/selectdialog.h"
48
49static void ui_select_dialog_wnd_close(ui_window_t *, void *);
50static void ui_select_dialog_wnd_kbd(ui_window_t *, void *, kbd_event_t *);
51
52ui_window_cb_t ui_select_dialog_wnd_cb = {
53 .close = ui_select_dialog_wnd_close,
54 .kbd = ui_select_dialog_wnd_kbd
55};
56
57static void ui_select_dialog_bok_clicked(ui_pbutton_t *, void *);
58static void ui_select_dialog_bcancel_clicked(ui_pbutton_t *, void *);
59
60ui_pbutton_cb_t ui_select_dialog_bok_cb = {
61 .clicked = ui_select_dialog_bok_clicked
62};
63
64ui_pbutton_cb_t ui_select_dialog_bcancel_cb = {
65 .clicked = ui_select_dialog_bcancel_clicked
66};
67
68static void ui_select_dialog_list_selected(ui_list_entry_t *, void *);
69
70ui_list_cb_t ui_select_dialog_list_cb = {
71 .selected = ui_select_dialog_list_selected
72};
73
74/** Initialize select dialog parameters structure.
75 *
76 * Select dialog parameters structure must always be initialized using
77 * this function first.
78 *
79 * @param params Select dialog parameters structure
80 */
81void ui_select_dialog_params_init(ui_select_dialog_params_t *params)
82{
83 memset(params, 0, sizeof(ui_select_dialog_params_t));
84}
85
86/** Create new select dialog.
87 *
88 * @param ui User interface
89 * @param params Select dialog parameters
90 * @param rdialog Place to store pointer to new dialog
91 * @return EOK on success or an error code
92 */
93errno_t ui_select_dialog_create(ui_t *ui, ui_select_dialog_params_t *params,
94 ui_select_dialog_t **rdialog)
95{
96 errno_t rc;
97 ui_select_dialog_t *dialog;
98 ui_window_t *window = NULL;
99 ui_wnd_params_t wparams;
100 ui_fixed_t *fixed = NULL;
101 ui_label_t *label = NULL;
102 ui_list_t *list = NULL;
103 ui_pbutton_t *bok = NULL;
104 ui_pbutton_t *bcancel = NULL;
105 gfx_rect_t rect;
106 ui_resource_t *ui_res;
107
108 dialog = calloc(1, sizeof(ui_select_dialog_t));
109 if (dialog == NULL) {
110 rc = ENOMEM;
111 goto error;
112 }
113
114 ui_wnd_params_init(&wparams);
115 wparams.caption = params->caption;
116
117 if ((params->flags & usdf_topmost) != 0)
118 wparams.flags |= wndf_topmost;
119 if ((params->flags & usdf_center) != 0)
120 wparams.placement = ui_wnd_place_center;
121
122 /* FIXME: Auto layout */
123 if (ui_is_textmode(ui)) {
124 wparams.rect.p0.x = 0;
125 wparams.rect.p0.y = 0;
126 wparams.rect.p1.x = 55;
127 wparams.rect.p1.y = 19;
128 } else {
129 wparams.rect.p0.x = 0;
130 wparams.rect.p0.y = 0;
131 wparams.rect.p1.x = 450;
132 wparams.rect.p1.y = 235;
133 }
134
135 rc = ui_window_create(ui, &wparams, &window);
136 if (rc != EOK)
137 goto error;
138
139 ui_window_set_cb(window, &ui_select_dialog_wnd_cb, dialog);
140
141 ui_res = ui_window_get_res(window);
142
143 rc = ui_fixed_create(&fixed);
144 if (rc != EOK)
145 goto error;
146
147 rc = ui_label_create(ui_res, params->prompt, &label);
148 if (rc != EOK)
149 goto error;
150
151 /* FIXME: Auto layout */
152 if (ui_is_textmode(ui)) {
153 rect.p0.x = 3;
154 rect.p0.y = 2;
155 rect.p1.x = 17;
156 rect.p1.y = 3;
157 } else {
158 rect.p0.x = 10;
159 rect.p0.y = 35;
160 rect.p1.x = 190;
161 rect.p1.y = 50;
162 }
163
164 ui_label_set_rect(label, &rect);
165
166 rc = ui_fixed_add(fixed, ui_label_ctl(label));
167 if (rc != EOK)
168 goto error;
169
170 label = NULL;
171
172 rc = ui_list_create(window, true, &list);
173 if (rc != EOK)
174 goto error;
175
176 ui_list_set_cb(list, &ui_select_dialog_list_cb, dialog);
177
178 /* FIXME: Auto layout */
179 if (ui_is_textmode(ui)) {
180 rect.p0.x = 3;
181 rect.p0.y = 4;
182 rect.p1.x = 52;
183 rect.p1.y = 15;
184 } else {
185 rect.p0.x = 10;
186 rect.p0.y = 55;
187 rect.p1.x = 440;
188 rect.p1.y = 180;
189 }
190
191 ui_list_set_rect(list, &rect);
192
193 rc = ui_fixed_add(fixed, ui_list_ctl(list));
194 if (rc != EOK)
195 goto error;
196
197 dialog->list = list;
198 list = NULL;
199
200 rc = ui_pbutton_create(ui_res, "OK", &bok);
201 if (rc != EOK)
202 goto error;
203
204 ui_pbutton_set_cb(bok, &ui_select_dialog_bok_cb, dialog);
205
206 /* FIXME: Auto layout */
207 if (ui_is_textmode(ui)) {
208 rect.p0.x = 16;
209 rect.p0.y = 16;
210 rect.p1.x = 26;
211 rect.p1.y = 17;
212 } else {
213 rect.p0.x = 130;
214 rect.p0.y = 190;
215 rect.p1.x = 220;
216 rect.p1.y = 218;
217 }
218
219 ui_pbutton_set_rect(bok, &rect);
220
221 ui_pbutton_set_default(bok, true);
222
223 rc = ui_fixed_add(fixed, ui_pbutton_ctl(bok));
224 if (rc != EOK)
225 goto error;
226
227 dialog->bok = bok;
228 bok = NULL;
229
230 rc = ui_pbutton_create(ui_res, "Cancel", &bcancel);
231 if (rc != EOK)
232 goto error;
233
234 ui_pbutton_set_cb(bcancel, &ui_select_dialog_bcancel_cb, dialog);
235
236 /* FIXME: Auto layout */
237 if (ui_is_textmode(ui)) {
238 rect.p0.x = 28;
239 rect.p0.y = 16;
240 rect.p1.x = 38;
241 rect.p1.y = 17;
242 } else {
243 rect.p0.x = 230;
244 rect.p0.y = 190;
245 rect.p1.x = 320;
246 rect.p1.y = 218;
247 }
248
249 ui_pbutton_set_rect(bcancel, &rect);
250
251 rc = ui_fixed_add(fixed, ui_pbutton_ctl(bcancel));
252 if (rc != EOK)
253 goto error;
254
255 dialog->bcancel = bcancel;
256 bcancel = NULL;
257
258 ui_window_add(window, ui_fixed_ctl(fixed));
259 fixed = NULL;
260
261 rc = ui_window_paint(window);
262 if (rc != EOK)
263 goto error;
264
265 dialog->window = window;
266 *rdialog = dialog;
267 return EOK;
268error:
269 if (list != NULL)
270 ui_list_destroy(list);
271 if (bok != NULL)
272 ui_pbutton_destroy(bok);
273 if (bcancel != NULL)
274 ui_pbutton_destroy(bcancel);
275 if (label != NULL)
276 ui_label_destroy(label);
277 if (fixed != NULL)
278 ui_fixed_destroy(fixed);
279 if (window != NULL)
280 ui_window_destroy(window);
281 if (dialog != NULL)
282 free(dialog);
283 return rc;
284}
285
286/** Destroy select dialog.
287 *
288 * @param dialog Select dialog or @c NULL
289 */
290void ui_select_dialog_destroy(ui_select_dialog_t *dialog)
291{
292 if (dialog == NULL)
293 return;
294
295 ui_window_destroy(dialog->window);
296 free(dialog);
297}
298
299/** Set mesage dialog callback.
300 *
301 * @param dialog Select dialog
302 * @param cb Select dialog callbacks
303 * @param arg Callback argument
304 */
305void ui_select_dialog_set_cb(ui_select_dialog_t *dialog, ui_select_dialog_cb_t *cb,
306 void *arg)
307{
308 dialog->cb = cb;
309 dialog->arg = arg;
310}
311
312/** Append new entry to select dialog.
313 *
314 * @param dialog Select dialog
315 * @param attr List entry attributes
316 * @return EOK on success or an error code
317 */
318errno_t ui_select_dialog_append(ui_select_dialog_t *dialog,
319 ui_list_entry_attr_t *attr)
320{
321 return ui_list_entry_append(dialog->list, attr, NULL);
322}
323
324/** Paint select dialog.
325 *
326 * This needs to be called after appending entries.
327 *
328 * @param dialog Select dialog
329 * @return EOK on success or an error code
330 */
331errno_t ui_select_dialog_paint(ui_select_dialog_t *dialog)
332{
333 return ui_window_paint(dialog->window);
334}
335
336/** Get the entry list from select dialog.
337 *
338 * @param dialog Select dialog
339 * @return UI list
340 */
341ui_list_t *ui_select_dialog_list(ui_select_dialog_t *dialog)
342{
343 return dialog->list;
344}
345
346/** Select dialog window close handler.
347 *
348 * @param window Window
349 * @param arg Argument (ui_select_dialog_t *)
350 */
351static void ui_select_dialog_wnd_close(ui_window_t *window, void *arg)
352{
353 ui_select_dialog_t *dialog = (ui_select_dialog_t *) arg;
354
355 if (dialog->cb != NULL && dialog->cb->close != NULL)
356 dialog->cb->close(dialog, dialog->arg);
357}
358
359/** Select dialog window keyboard event handler.
360 *
361 * @param window Window
362 * @param arg Argument (ui_select_dialog_t *)
363 * @param event Keyboard event
364 */
365static void ui_select_dialog_wnd_kbd(ui_window_t *window, void *arg,
366 kbd_event_t *event)
367{
368 ui_select_dialog_t *dialog = (ui_select_dialog_t *) arg;
369 ui_list_entry_t *entry;
370 void *earg;
371
372 if (event->type == KEY_PRESS &&
373 (event->mods & (KM_CTRL | KM_SHIFT | KM_ALT)) == 0) {
374 if (event->key == KC_ENTER) {
375 /* Confirm */
376 if (dialog->cb != NULL && dialog->cb->bok != NULL) {
377 entry = ui_list_get_cursor(dialog->list);
378 earg = ui_list_entry_get_arg(entry);
379 dialog->cb->bok(dialog, dialog->arg, earg);
380 return;
381 }
382 } else if (event->key == KC_ESCAPE) {
383 /* Cancel */
384 if (dialog->cb != NULL && dialog->cb->bcancel != NULL) {
385 dialog->cb->bcancel(dialog, dialog->arg);
386 return;
387 }
388 }
389 }
390
391 ui_window_def_kbd(window, event);
392}
393
394/** Select dialog OK button click handler.
395 *
396 * @param pbutton Push button
397 * @param arg Argument (ui_select_dialog_t *)
398 */
399static void ui_select_dialog_bok_clicked(ui_pbutton_t *pbutton, void *arg)
400{
401 ui_select_dialog_t *dialog = (ui_select_dialog_t *) arg;
402 ui_list_entry_t *entry;
403 void *earg;
404
405 if (dialog->cb != NULL && dialog->cb->bok != NULL) {
406 entry = ui_list_get_cursor(dialog->list);
407 if (entry != NULL)
408 earg = ui_list_entry_get_arg(entry);
409 else
410 earg = NULL;
411
412 dialog->cb->bok(dialog, dialog->arg, earg);
413 }
414}
415
416/** Select dialog cancel button click handler.
417 *
418 * @param pbutton Push button
419 * @param arg Argument (ui_select_dialog_t *)
420 */
421static void ui_select_dialog_bcancel_clicked(ui_pbutton_t *pbutton, void *arg)
422{
423 ui_select_dialog_t *dialog = (ui_select_dialog_t *) arg;
424
425 if (dialog->cb != NULL && dialog->cb->bcancel != NULL)
426 dialog->cb->bcancel(dialog, dialog->arg);
427}
428
429/** Select dialog list entry selection handler.
430 *
431 * @param entry UI list entry
432 * @param arg Entry argument
433 */
434static void ui_select_dialog_list_selected(ui_list_entry_t *entry, void *arg)
435{
436 ui_list_t *list;
437 ui_select_dialog_t *dialog;
438
439 list = ui_list_entry_get_list(entry);
440 dialog = (ui_select_dialog_t *)ui_list_get_cb_arg(list);
441
442 if (dialog->cb != NULL && dialog->cb->bok != NULL)
443 dialog->cb->bok(dialog, dialog->arg, arg);
444}
445
446/** @}
447 */
Note: See TracBrowser for help on using the repository browser.