source: mainline/uspace/lib/ui/src/promptdialog.c@ 6c0766b

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6c0766b was 6c0766b, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Confirm / cancel file and prompt dialogs using Enter / Escape

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2021 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 Prompt dialog
34 */
35
36#include <errno.h>
37#include <mem.h>
38#include <stdlib.h>
39#include <ui/entry.h>
40#include <ui/fixed.h>
41#include <ui/label.h>
42#include <ui/promptdialog.h>
43#include <ui/pbutton.h>
44#include <ui/resource.h>
45#include <ui/ui.h>
46#include <ui/window.h>
47#include "../private/promptdialog.h"
48
49static void ui_prompt_dialog_wnd_close(ui_window_t *, void *);
50static void ui_prompt_dialog_wnd_kbd(ui_window_t *, void *, kbd_event_t *);
51
52ui_window_cb_t ui_prompt_dialog_wnd_cb = {
53 .close = ui_prompt_dialog_wnd_close,
54 .kbd = ui_prompt_dialog_wnd_kbd
55};
56
57static void ui_prompt_dialog_bok_clicked(ui_pbutton_t *, void *);
58static void ui_prompt_dialog_bcancel_clicked(ui_pbutton_t *, void *);
59
60ui_pbutton_cb_t ui_prompt_dialog_bok_cb = {
61 .clicked = ui_prompt_dialog_bok_clicked
62};
63
64ui_pbutton_cb_t ui_prompt_dialog_bcancel_cb = {
65 .clicked = ui_prompt_dialog_bcancel_clicked
66};
67
68/** Initialize prompt dialog parameters structure.
69 *
70 * Prompt dialog parameters structure must always be initialized using
71 * this function first.
72 *
73 * @param params Prompt dialog parameters structure
74 */
75void ui_prompt_dialog_params_init(ui_prompt_dialog_params_t *params)
76{
77 memset(params, 0, sizeof(ui_prompt_dialog_params_t));
78}
79
80/** Create new prompt dialog.
81 *
82 * @param ui User interface
83 * @param params Prompt dialog parameters
84 * @param rdialog Place to store pointer to new dialog
85 * @return EOK on success or an error code
86 */
87errno_t ui_prompt_dialog_create(ui_t *ui, ui_prompt_dialog_params_t *params,
88 ui_prompt_dialog_t **rdialog)
89{
90 errno_t rc;
91 ui_prompt_dialog_t *dialog;
92 ui_window_t *window = NULL;
93 ui_wnd_params_t wparams;
94 ui_fixed_t *fixed = NULL;
95 ui_label_t *label = NULL;
96 ui_entry_t *entry = NULL;
97 ui_pbutton_t *bok = NULL;
98 ui_pbutton_t *bcancel = NULL;
99 gfx_rect_t rect;
100 ui_resource_t *ui_res;
101
102 dialog = calloc(1, sizeof(ui_prompt_dialog_t));
103 if (dialog == NULL) {
104 rc = ENOMEM;
105 goto error;
106 }
107
108 ui_wnd_params_init(&wparams);
109 wparams.caption = params->caption;
110
111 /* FIXME: Auto layout */
112 if (ui_is_textmode(ui)) {
113 wparams.rect.p0.x = 0;
114 wparams.rect.p0.y = 0;
115 wparams.rect.p1.x = 40;
116 wparams.rect.p1.y = 9;
117 } else {
118 wparams.rect.p0.x = 0;
119 wparams.rect.p0.y = 0;
120 wparams.rect.p1.x = 300;
121 wparams.rect.p1.y = 135;
122 }
123
124 rc = ui_window_create(ui, &wparams, &window);
125 if (rc != EOK)
126 goto error;
127
128 ui_window_set_cb(window, &ui_prompt_dialog_wnd_cb, dialog);
129
130 ui_res = ui_window_get_res(window);
131
132 rc = ui_fixed_create(&fixed);
133 if (rc != EOK)
134 goto error;
135
136 rc = ui_label_create(ui_res, params->prompt, &label);
137 if (rc != EOK)
138 goto error;
139
140 /* FIXME: Auto layout */
141 if (ui_is_textmode(ui)) {
142 rect.p0.x = 3;
143 rect.p0.y = 2;
144 rect.p1.x = 17;
145 rect.p1.y = 3;
146 } else {
147 rect.p0.x = 10;
148 rect.p0.y = 35;
149 rect.p1.x = 190;
150 rect.p1.y = 50;
151 }
152
153 ui_label_set_rect(label, &rect);
154
155 rc = ui_fixed_add(fixed, ui_label_ctl(label));
156 if (rc != EOK)
157 goto error;
158
159 label = NULL;
160
161 rc = ui_entry_create(window, "", &entry);
162 if (rc != EOK)
163 goto error;
164
165 /* FIXME: Auto layout */
166 if (ui_is_textmode(ui)) {
167 rect.p0.x = 3;
168 rect.p0.y = 4;
169 rect.p1.x = 37;
170 rect.p1.y = 5;
171 } else {
172 rect.p0.x = 10;
173 rect.p0.y = 55;
174 rect.p1.x = 290;
175 rect.p1.y = 80;
176 }
177
178 ui_entry_set_rect(entry, &rect);
179
180 rc = ui_fixed_add(fixed, ui_entry_ctl(entry));
181 if (rc != EOK)
182 goto error;
183
184 ui_entry_activate(entry);
185
186 dialog->ename = entry;
187 entry = NULL;
188
189 rc = ui_pbutton_create(ui_res, "OK", &bok);
190 if (rc != EOK)
191 goto error;
192
193 ui_pbutton_set_cb(bok, &ui_prompt_dialog_bok_cb, dialog);
194
195 /* FIXME: Auto layout */
196 if (ui_is_textmode(ui)) {
197 rect.p0.x = 10;
198 rect.p0.y = 6;
199 rect.p1.x = 20;
200 rect.p1.y = 7;
201 } else {
202 rect.p0.x = 55;
203 rect.p0.y = 90;
204 rect.p1.x = 145;
205 rect.p1.y = 118;
206 }
207
208 ui_pbutton_set_rect(bok, &rect);
209
210 ui_pbutton_set_default(bok, true);
211
212 rc = ui_fixed_add(fixed, ui_pbutton_ctl(bok));
213 if (rc != EOK)
214 goto error;
215
216 dialog->bok = bok;
217 bok = NULL;
218
219 rc = ui_pbutton_create(ui_res, "Cancel", &bcancel);
220 if (rc != EOK)
221 goto error;
222
223 ui_pbutton_set_cb(bcancel, &ui_prompt_dialog_bcancel_cb, dialog);
224
225 /* FIXME: Auto layout */
226 if (ui_is_textmode(ui)) {
227 rect.p0.x = 22;
228 rect.p0.y = 6;
229 rect.p1.x = 32;
230 rect.p1.y = 7;
231 } else {
232 rect.p0.x = 155;
233 rect.p0.y = 90;
234 rect.p1.x = 245;
235 rect.p1.y = 118;
236 }
237
238 ui_pbutton_set_rect(bcancel, &rect);
239
240 rc = ui_fixed_add(fixed, ui_pbutton_ctl(bcancel));
241 if (rc != EOK)
242 goto error;
243
244 dialog->bcancel = bcancel;
245 bcancel = NULL;
246
247 ui_window_add(window, ui_fixed_ctl(fixed));
248 fixed = NULL;
249
250 rc = ui_window_paint(window);
251 if (rc != EOK)
252 goto error;
253
254 dialog->window = window;
255 *rdialog = dialog;
256 return EOK;
257error:
258 if (entry != NULL)
259 ui_entry_destroy(entry);
260 if (bok != NULL)
261 ui_pbutton_destroy(bok);
262 if (bcancel != NULL)
263 ui_pbutton_destroy(bcancel);
264 if (label != NULL)
265 ui_label_destroy(label);
266 if (fixed != NULL)
267 ui_fixed_destroy(fixed);
268 if (window != NULL)
269 ui_window_destroy(window);
270 if (dialog != NULL)
271 free(dialog);
272 return rc;
273}
274
275/** Destroy prompt dialog.
276 *
277 * @param dialog Prompt dialog or @c NULL
278 */
279void ui_prompt_dialog_destroy(ui_prompt_dialog_t *dialog)
280{
281 if (dialog == NULL)
282 return;
283
284 ui_window_destroy(dialog->window);
285 free(dialog);
286}
287
288/** Set mesage dialog callback.
289 *
290 * @param dialog Prompt dialog
291 * @param cb Prompt dialog callbacks
292 * @param arg Callback argument
293 */
294void ui_prompt_dialog_set_cb(ui_prompt_dialog_t *dialog, ui_prompt_dialog_cb_t *cb,
295 void *arg)
296{
297 dialog->cb = cb;
298 dialog->arg = arg;
299}
300
301/** Prompt dialog window close handler.
302 *
303 * @param window Window
304 * @param arg Argument (ui_prompt_dialog_t *)
305 */
306static void ui_prompt_dialog_wnd_close(ui_window_t *window, void *arg)
307{
308 ui_prompt_dialog_t *dialog = (ui_prompt_dialog_t *) arg;
309
310 if (dialog->cb != NULL && dialog->cb->close != NULL)
311 dialog->cb->close(dialog, dialog->arg);
312}
313
314/** Prompt dialog window keyboard event handler.
315 *
316 * @param window Window
317 * @param arg Argument (ui_prompt_dialog_t *)
318 * @param event Keyboard event
319 */
320static void ui_prompt_dialog_wnd_kbd(ui_window_t *window, void *arg,
321 kbd_event_t *event)
322{
323 ui_prompt_dialog_t *dialog = (ui_prompt_dialog_t *) arg;
324 const char *fname;
325
326 if (event->type == KEY_PRESS &&
327 (event->mods & (KM_CTRL | KM_SHIFT | KM_ALT)) == 0) {
328 if (event->key == KC_ENTER) {
329 /* Confirm */
330 if (dialog->cb != NULL && dialog->cb->bok != NULL) {
331 fname = ui_entry_get_text(dialog->ename);
332 dialog->cb->bok(dialog, dialog->arg, fname);
333 return;
334 }
335 } else if (event->key == KC_ESCAPE) {
336 /* Cancel */
337 if (dialog->cb != NULL && dialog->cb->bcancel != NULL) {
338 dialog->cb->bcancel(dialog, dialog->arg);
339 return;
340 }
341 }
342 }
343
344 ui_window_def_kbd(window, event);
345}
346
347/** Prompt dialog OK button click handler.
348 *
349 * @param pbutton Push button
350 * @param arg Argument (ui_prompt_dialog_t *)
351 */
352static void ui_prompt_dialog_bok_clicked(ui_pbutton_t *pbutton, void *arg)
353{
354 ui_prompt_dialog_t *dialog = (ui_prompt_dialog_t *) arg;
355 const char *fname;
356
357 if (dialog->cb != NULL && dialog->cb->bok != NULL) {
358 fname = ui_entry_get_text(dialog->ename);
359 dialog->cb->bok(dialog, dialog->arg, fname);
360 }
361}
362
363/** Prompt dialog cancel button click handler.
364 *
365 * @param pbutton Push button
366 * @param arg Argument (ui_prompt_dialog_t *)
367 */
368static void ui_prompt_dialog_bcancel_clicked(ui_pbutton_t *pbutton, void *arg)
369{
370 ui_prompt_dialog_t *dialog = (ui_prompt_dialog_t *) arg;
371
372 if (dialog->cb != NULL && dialog->cb->bcancel != NULL)
373 dialog->cb->bcancel(dialog, dialog->arg);
374}
375
376/** @}
377 */
Note: See TracBrowser for help on using the repository browser.