source: mainline/uspace/app/taskbar-cfg/startmenu.c

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

Simplify SIF interface, remove contacts

Remove transactions, move to a load/save model. Remove contacts
application as it was never finished and not useful at all.

  • Property mode set to 100644
File size: 16.6 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 taskbar-cfg
30 * @{
31 */
32/** @file Start menu configuration tab
33 */
34
35#include <gfx/coord.h>
36#include <loc.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <str.h>
40#include <tbarcfg/tbarcfg.h>
41#include <ui/control.h>
42#include <ui/label.h>
43#include <ui/list.h>
44#include <ui/pbutton.h>
45#include <ui/resource.h>
46#include <ui/tab.h>
47#include <ui/window.h>
48#include "smeedit.h"
49#include "startmenu.h"
50#include "taskbar-cfg.h"
51
52static void startmenu_entry_selected(ui_list_entry_t *, void *);
53static void startmenu_new_entry_clicked(ui_pbutton_t *, void *);
54static void startmenu_delete_entry_clicked(ui_pbutton_t *, void *);
55static void startmenu_edit_entry_clicked(ui_pbutton_t *, void *);
56static void startmenu_sep_entry_clicked(ui_pbutton_t *, void *);
57static void startmenu_up_entry_clicked(ui_pbutton_t *, void *);
58static void startmenu_down_entry_clicked(ui_pbutton_t *, void *);
59
60/** Entry list callbacks */
61ui_list_cb_t startmenu_entry_list_cb = {
62 .selected = startmenu_entry_selected
63};
64
65/** New entry button callbacks */
66ui_pbutton_cb_t startmenu_new_entry_button_cb = {
67 .clicked = startmenu_new_entry_clicked
68};
69
70/** Delete entry button callbacks */
71ui_pbutton_cb_t startmenu_delete_entry_button_cb = {
72 .clicked = startmenu_delete_entry_clicked
73};
74
75/** Edit entry button callbacks */
76ui_pbutton_cb_t startmenu_edit_entry_button_cb = {
77 .clicked = startmenu_edit_entry_clicked
78};
79
80/** Separator entry button callbacks */
81ui_pbutton_cb_t startmenu_sep_entry_button_cb = {
82 .clicked = startmenu_sep_entry_clicked
83};
84
85/** Move entry up button callbacks */
86ui_pbutton_cb_t startmenu_up_entry_button_cb = {
87 .clicked = startmenu_up_entry_clicked
88};
89
90/** Move entry down button callbacks */
91ui_pbutton_cb_t startmenu_down_entry_button_cb = {
92 .clicked = startmenu_down_entry_clicked
93};
94
95/** Create start menu configuration tab
96 *
97 * @param tbcfg Taskbar configuration dialog
98 * @param rsmenu Place to store pointer to new start menu configuration tab
99 * @return EOK on success or an error code
100 */
101errno_t startmenu_create(taskbar_cfg_t *tbcfg, startmenu_t **rsmenu)
102{
103 ui_resource_t *ui_res;
104 startmenu_t *smenu;
105 gfx_rect_t rect;
106 errno_t rc;
107
108 ui_res = ui_window_get_res(tbcfg->window);
109
110 smenu = calloc(1, sizeof(startmenu_t));
111 if (smenu == NULL) {
112 printf("Out of memory.\n");
113 return ENOMEM;
114 }
115
116 smenu->tbarcfg = tbcfg;
117
118 /* 'Start Menu' tab */
119
120 rc = ui_tab_create(tbcfg->tabset, "Start Menu", &smenu->tab);
121 if (rc != EOK)
122 goto error;
123
124 rc = ui_fixed_create(&smenu->fixed);
125 if (rc != EOK) {
126 printf("Error creating fixed layout.\n");
127 goto error;
128 }
129
130 /* 'Start menu entries:' label */
131
132 rc = ui_label_create(ui_res, "Start menu entries:",
133 &smenu->entries_label);
134 if (rc != EOK) {
135 printf("Error creating label.\n");
136 goto error;
137 }
138
139 if (ui_resource_is_textmode(ui_res)) {
140 rect.p0.x = 4;
141 rect.p0.y = 4;
142 rect.p1.x = 36;
143 rect.p1.y = 5;
144 } else {
145 rect.p0.x = 20;
146 rect.p0.y = 60;
147 rect.p1.x = 360;
148 rect.p1.y = 80;
149 }
150
151 ui_label_set_rect(smenu->entries_label, &rect);
152
153 rc = ui_fixed_add(smenu->fixed, ui_label_ctl(smenu->entries_label));
154 if (rc != EOK) {
155 printf("Error adding control to layout.\n");
156 goto error;
157 }
158
159 /* List of entries */
160
161 rc = ui_list_create(tbcfg->window, false, &smenu->entries_list);
162 if (rc != EOK) {
163 printf("Error creating list.\n");
164 goto error;
165 }
166
167 if (ui_resource_is_textmode(ui_res)) {
168 rect.p0.x = 4;
169 rect.p0.y = 5;
170 rect.p1.x = 56;
171 rect.p1.y = 20;
172 } else {
173 rect.p0.x = 20;
174 rect.p0.y = 80;
175 rect.p1.x = 360;
176 rect.p1.y = 330;
177 }
178
179 ui_list_set_rect(smenu->entries_list, &rect);
180
181 rc = ui_fixed_add(smenu->fixed, ui_list_ctl(smenu->entries_list));
182 if (rc != EOK) {
183 printf("Error adding control to layout.\n");
184 goto error;
185 }
186
187 ui_list_set_cb(smenu->entries_list, &startmenu_entry_list_cb,
188 (void *)smenu);
189
190 /* New entry button */
191
192 rc = ui_pbutton_create(ui_res, "New...", &smenu->new_entry);
193 if (rc != EOK) {
194 printf("Error creating button.\n");
195 goto error;
196 }
197
198 if (ui_resource_is_textmode(ui_res)) {
199 rect.p0.x = 58;
200 rect.p0.y = 5;
201 rect.p1.x = 68;
202 rect.p1.y = 6;
203 } else {
204 rect.p0.x = 370;
205 rect.p0.y = 80;
206 rect.p1.x = 450;
207 rect.p1.y = 105;
208 }
209
210 ui_pbutton_set_rect(smenu->new_entry, &rect);
211
212 rc = ui_fixed_add(smenu->fixed, ui_pbutton_ctl(smenu->new_entry));
213 if (rc != EOK) {
214 printf("Error adding control to layout.\n");
215 goto error;
216 }
217
218 ui_pbutton_set_cb(smenu->new_entry, &startmenu_new_entry_button_cb,
219 (void *)smenu);
220
221 /* Delete entry button */
222
223 rc = ui_pbutton_create(ui_res, "Delete", &smenu->delete_entry);
224 if (rc != EOK) {
225 printf("Error creating button.\n");
226 goto error;
227 }
228
229 if (ui_resource_is_textmode(ui_res)) {
230 rect.p0.x = 58;
231 rect.p0.y = 7;
232 rect.p1.x = 68;
233 rect.p1.y = 8;
234 } else {
235 rect.p0.x = 370;
236 rect.p0.y = 110;
237 rect.p1.x = 450;
238 rect.p1.y = 135;
239 }
240
241 ui_pbutton_set_rect(smenu->delete_entry, &rect);
242
243 rc = ui_fixed_add(smenu->fixed, ui_pbutton_ctl(smenu->delete_entry));
244 if (rc != EOK) {
245 printf("Error adding control to layout.\n");
246 goto error;
247 }
248
249 ui_pbutton_set_cb(smenu->delete_entry,
250 &startmenu_delete_entry_button_cb, (void *)smenu);
251
252 /* Edit entry button */
253
254 rc = ui_pbutton_create(ui_res, "Edit...", &smenu->edit_entry);
255 if (rc != EOK) {
256 printf("Error creating button.\n");
257 goto error;
258 }
259
260 if (ui_resource_is_textmode(ui_res)) {
261 rect.p0.x = 58;
262 rect.p0.y = 9;
263 rect.p1.x = 68;
264 rect.p1.y = 10;
265 } else {
266 rect.p0.x = 370;
267 rect.p0.y = 140;
268 rect.p1.x = 450;
269 rect.p1.y = 165;
270 }
271
272 ui_pbutton_set_rect(smenu->edit_entry, &rect);
273
274 rc = ui_fixed_add(smenu->fixed, ui_pbutton_ctl(smenu->edit_entry));
275 if (rc != EOK) {
276 printf("Error adding control to layout.\n");
277 goto error;
278 }
279
280 ui_pbutton_set_cb(smenu->edit_entry,
281 &startmenu_edit_entry_button_cb, (void *)smenu);
282
283 /* Separator entry button */
284
285 rc = ui_pbutton_create(ui_res, "Separator", &smenu->sep_entry);
286 if (rc != EOK) {
287 printf("Error creating button.\n");
288 goto error;
289 }
290
291 if (ui_resource_is_textmode(ui_res)) {
292 rect.p0.x = 58;
293 rect.p0.y = 11;
294 rect.p1.x = 68;
295 rect.p1.y = 12;
296 } else {
297 rect.p0.x = 370;
298 rect.p0.y = 170;
299 rect.p1.x = 450;
300 rect.p1.y = 195;
301 }
302
303 ui_pbutton_set_rect(smenu->sep_entry, &rect);
304
305 rc = ui_fixed_add(smenu->fixed, ui_pbutton_ctl(smenu->sep_entry));
306 if (rc != EOK) {
307 printf("Error adding control to layout.\n");
308 goto error;
309 }
310
311 ui_pbutton_set_cb(smenu->sep_entry,
312 &startmenu_sep_entry_button_cb, (void *)smenu);
313
314 /* Move entry up button */
315
316 rc = ui_pbutton_create(ui_res, "Up", &smenu->up_entry);
317 if (rc != EOK) {
318 printf("Error creating button.\n");
319 goto error;
320 }
321
322 if (ui_resource_is_textmode(ui_res)) {
323 rect.p0.x = 58;
324 rect.p0.y = 13;
325 rect.p1.x = 68;
326 rect.p1.y = 14;
327 } else {
328 rect.p0.x = 370;
329 rect.p0.y = 220;
330 rect.p1.x = 450;
331 rect.p1.y = 245;
332 }
333
334 ui_pbutton_set_rect(smenu->up_entry, &rect);
335
336 rc = ui_fixed_add(smenu->fixed, ui_pbutton_ctl(smenu->up_entry));
337 if (rc != EOK) {
338 printf("Error adding control to layout.\n");
339 goto error;
340 }
341
342 ui_pbutton_set_cb(smenu->up_entry,
343 &startmenu_up_entry_button_cb, (void *)smenu);
344
345 /* Move entry down button */
346
347 rc = ui_pbutton_create(ui_res, "Down", &smenu->down_entry);
348 if (rc != EOK) {
349 printf("Error creating button.\n");
350 goto error;
351 }
352
353 if (ui_resource_is_textmode(ui_res)) {
354 rect.p0.x = 58;
355 rect.p0.y = 15;
356 rect.p1.x = 68;
357 rect.p1.y = 16;
358 } else {
359 rect.p0.x = 370;
360 rect.p0.y = 250;
361 rect.p1.x = 450;
362 rect.p1.y = 275;
363 }
364
365 ui_pbutton_set_rect(smenu->down_entry, &rect);
366
367 rc = ui_fixed_add(smenu->fixed, ui_pbutton_ctl(smenu->down_entry));
368 if (rc != EOK) {
369 printf("Error adding control to layout.\n");
370 goto error;
371 }
372
373 ui_pbutton_set_cb(smenu->down_entry,
374 &startmenu_down_entry_button_cb, (void *)smenu);
375
376 ui_tab_add(smenu->tab, ui_fixed_ctl(smenu->fixed));
377
378 *rsmenu = smenu;
379 return EOK;
380error:
381 if (smenu->down_entry != NULL)
382 ui_pbutton_destroy(smenu->down_entry);
383 if (smenu->up_entry != NULL)
384 ui_pbutton_destroy(smenu->up_entry);
385 if (smenu->delete_entry != NULL)
386 ui_pbutton_destroy(smenu->delete_entry);
387 if (smenu->new_entry != NULL)
388 ui_pbutton_destroy(smenu->new_entry);
389 if (smenu->entries_label != NULL)
390 ui_label_destroy(smenu->entries_label);
391 if (smenu->entries_list != NULL)
392 ui_list_destroy(smenu->entries_list);
393 if (smenu->fixed != NULL)
394 ui_fixed_destroy(smenu->fixed);
395 free(smenu);
396 return rc;
397}
398
399/** Populate start menu tab with start menu configuration data
400 *
401 * @param smenu Start menu configuration tab
402 * @param tbarcfg Taskbar configuration
403 * @return EOK on success or an error code
404 */
405errno_t startmenu_populate(startmenu_t *smenu, tbarcfg_t *tbarcfg)
406{
407 smenu_entry_t *entry;
408 startmenu_entry_t *smentry;
409 errno_t rc;
410
411 entry = tbarcfg_smenu_first(tbarcfg);
412 while (entry != NULL) {
413 rc = startmenu_insert(smenu, entry, &smentry);
414 if (rc != EOK)
415 return rc;
416
417 entry = tbarcfg_smenu_next(entry);
418 }
419
420 return EOK;
421}
422
423/** Destroy start menu configuration tab.
424 *
425 * @param smenu Start menu configuration tab
426 */
427void startmenu_destroy(startmenu_t *smenu)
428{
429 ui_list_entry_t *lentry;
430 startmenu_entry_t *entry;
431
432 lentry = ui_list_first(smenu->entries_list);
433 while (lentry != NULL) {
434 entry = (startmenu_entry_t *)ui_list_entry_get_arg(lentry);
435 free(entry);
436 ui_list_entry_delete(lentry);
437 lentry = ui_list_first(smenu->entries_list);
438 }
439
440 /* This will automatically destroy all controls in the tab */
441 ui_tab_destroy(smenu->tab);
442 free(smenu);
443}
444
445/** Insert new entry into entries list.
446 *
447 * @param smenu Start menu configuration tab
448 * @param entry Backing entry
449 * @param rsmentry Place to store pointer to new entry or NULL
450 * @return EOK on success or an error code
451 */
452errno_t startmenu_insert(startmenu_t *smenu, smenu_entry_t *entry,
453 startmenu_entry_t **rsmentry)
454{
455 startmenu_entry_t *smentry;
456 ui_list_entry_attr_t attr;
457 bool separator;
458 errno_t rc;
459
460 smentry = calloc(1, sizeof(startmenu_entry_t));
461 if (smentry == NULL)
462 return ENOMEM;
463
464 smentry->startmenu = smenu;
465 smentry->entry = entry;
466
467 ui_list_entry_attr_init(&attr);
468 separator = smenu_entry_get_separator(entry);
469 if (separator)
470 attr.caption = "-- Separator --";
471 else
472 attr.caption = smenu_entry_get_caption(entry);
473
474 attr.arg = (void *)smentry;
475
476 rc = ui_list_entry_append(smenu->entries_list, &attr, &smentry->lentry);
477 if (rc != EOK) {
478 free(smentry);
479 return rc;
480 }
481
482 if (rsmentry != NULL)
483 *rsmentry = smentry;
484 return EOK;
485}
486
487/** Get selected start menu entry.
488 *
489 * @param smenu Start menu
490 * @return Selected entry or @c NULL if no entry is selected
491 */
492startmenu_entry_t *startmenu_get_selected(startmenu_t *smenu)
493{
494 ui_list_entry_t *entry;
495
496 entry = ui_list_get_cursor(smenu->entries_list);
497 if (entry == NULL)
498 return NULL;
499
500 return (startmenu_entry_t *)ui_list_entry_get_arg(entry);
501}
502
503/** Create new menu entry.
504 *
505 * @param smenu Start menu
506 */
507void startmenu_new_entry(startmenu_t *smenu)
508{
509 smeedit_t *smee;
510 errno_t rc;
511
512 rc = smeedit_create(smenu, NULL, &smee);
513 if (rc != EOK)
514 return;
515
516 (void)smee;
517 (void)tbarcfg_sync(smenu->tbarcfg->tbarcfg);
518 (void)tbarcfg_notify(TBARCFG_NOTIFY_DEFAULT);
519}
520
521/** Create new separator menu entry.
522 *
523 * @param smenu Start menu
524 */
525void startmenu_sep_entry(startmenu_t *smenu)
526{
527 startmenu_entry_t *smentry = NULL;
528 smenu_entry_t *entry;
529 errno_t rc;
530
531 rc = smenu_entry_sep_create(smenu->tbarcfg->tbarcfg, &entry);
532 if (rc != EOK)
533 return;
534
535 (void)startmenu_insert(smenu, entry, &smentry);
536 (void)ui_control_paint(ui_list_ctl(smenu->entries_list));
537 (void)tbarcfg_sync(smenu->tbarcfg->tbarcfg);
538 (void)tbarcfg_notify(TBARCFG_NOTIFY_DEFAULT);
539}
540
541/** Edit selected menu entry.
542 *
543 * @param smenu Start menu
544 */
545void startmenu_edit(startmenu_t *smenu)
546{
547 smeedit_t *smee;
548 startmenu_entry_t *smentry;
549 errno_t rc;
550
551 smentry = startmenu_get_selected(smenu);
552 if (smentry == NULL)
553 return;
554
555 /* Do not edit separator entries */
556 if (smenu_entry_get_separator(smentry->entry))
557 return;
558
559 rc = smeedit_create(smenu, smentry, &smee);
560 if (rc != EOK)
561 return;
562
563 (void)smee;
564}
565
566/** Update start menu entry caption.
567 *
568 * When editing an entry the entry's label might change. We need
569 * to update the list entry caption to reflect that.
570 *
571 * @param entry Start menu entry
572 */
573errno_t startmenu_entry_update(startmenu_entry_t *entry)
574{
575 return ui_list_entry_set_caption(entry->lentry,
576 smenu_entry_get_caption(entry->entry));
577}
578
579/** Repaint start menu entry list.
580 *
581 * When editing an entry the entry's label might change. We need
582 * to update the list entry caption to reflect that.
583 *
584 * @param smenu Start menu
585 */
586void startmenu_repaint(startmenu_t *smenu)
587{
588 (void) ui_control_paint(ui_list_ctl(smenu->entries_list));
589}
590
591/** Entry in entry list is selected.
592 *
593 * @param lentry UI list entry
594 * @param arg Argument (dcfg_seats_entry_t *)
595 */
596static void startmenu_entry_selected(ui_list_entry_t *lentry, void *arg)
597{
598 (void)lentry;
599 (void)arg;
600}
601
602/** New entry button clicked.
603 *
604 * @param pbutton Push button
605 * @param arg Argument (startmenu_t *)
606 */
607static void startmenu_new_entry_clicked(ui_pbutton_t *pbutton, void *arg)
608{
609 startmenu_t *smenu = (startmenu_t *)arg;
610
611 (void)pbutton;
612 startmenu_new_entry(smenu);
613}
614
615/** Delete entry button clicked.
616 *
617 * @param pbutton Push button
618 * @param arg Argument (startmenu_t *)
619 */
620static void startmenu_delete_entry_clicked(ui_pbutton_t *pbutton, void *arg)
621{
622 startmenu_t *smenu = (startmenu_t *)arg;
623 startmenu_entry_t *smentry;
624
625 (void)pbutton;
626
627 smentry = startmenu_get_selected(smenu);
628 if (smentry == NULL)
629 return;
630
631 smenu_entry_destroy(smentry->entry);
632 ui_list_entry_delete(smentry->lentry);
633 free(smentry);
634
635 (void)ui_control_paint(ui_list_ctl(smenu->entries_list));
636 (void)tbarcfg_sync(smenu->tbarcfg->tbarcfg);
637 (void)tbarcfg_notify(TBARCFG_NOTIFY_DEFAULT);
638}
639
640/** Edit entry button clicked.
641 *
642 * @param pbutton Push button
643 * @param arg Argument (startmenu_t *)
644 */
645static void startmenu_edit_entry_clicked(ui_pbutton_t *pbutton, void *arg)
646{
647 startmenu_t *smenu = (startmenu_t *)arg;
648
649 (void)pbutton;
650 startmenu_edit(smenu);
651}
652
653/** Separator entry button clicked.
654 *
655 * @param pbutton Push button
656 * @param arg Argument (startmenu_t *)
657 */
658static void startmenu_sep_entry_clicked(ui_pbutton_t *pbutton, void *arg)
659{
660 startmenu_t *smenu = (startmenu_t *)arg;
661
662 (void)pbutton;
663 startmenu_sep_entry(smenu);
664}
665
666/** Up entry button clicked.
667 *
668 * @param pbutton Push button
669 * @param arg Argument (startmenu_t *)
670 */
671static void startmenu_up_entry_clicked(ui_pbutton_t *pbutton, void *arg)
672{
673 startmenu_t *smenu = (startmenu_t *)arg;
674 startmenu_entry_t *smentry;
675
676 (void)pbutton;
677
678 smentry = startmenu_get_selected(smenu);
679 if (smentry == NULL)
680 return;
681
682 smenu_entry_move_up(smentry->entry);
683 ui_list_entry_move_up(smentry->lentry);
684
685 (void)ui_control_paint(ui_list_ctl(smenu->entries_list));
686 (void)tbarcfg_sync(smenu->tbarcfg->tbarcfg);
687 (void)tbarcfg_notify(TBARCFG_NOTIFY_DEFAULT);
688}
689
690/** Down entry button clicked.
691 *
692 * @param pbutton Push button
693 * @param arg Argument (startmenu_t *)
694 */
695static void startmenu_down_entry_clicked(ui_pbutton_t *pbutton, void *arg)
696{
697 startmenu_t *smenu = (startmenu_t *)arg;
698 startmenu_entry_t *smentry;
699
700 (void)pbutton;
701
702 smentry = startmenu_get_selected(smenu);
703 if (smentry == NULL)
704 return;
705
706 smenu_entry_move_down(smentry->entry);
707 ui_list_entry_move_down(smentry->lentry);
708
709 (void)ui_control_paint(ui_list_ctl(smenu->entries_list));
710 (void)tbarcfg_sync(smenu->tbarcfg->tbarcfg);
711 (void)tbarcfg_notify(TBARCFG_NOTIFY_DEFAULT);
712}
713
714/** @}
715 */
Note: See TracBrowser for help on using the repository browser.