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

topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b169619 was 24be331e, checked in by Jiri Svoboda <jiri@…>, 23 months ago

Make select dialog a little wider

To fit device names. What we really need is a narrower font.
Plus the ability to resize these dialogs.

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