Changes in uspace/lib/ui/src/menu.c [d92b8e8f:ff6e91b] in mainline
- File:
-
- 1 edited
-
uspace/lib/ui/src/menu.c (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ui/src/menu.c
rd92b8e8f rff6e91b 1 1 /* 2 * Copyright (c) 202 4Jiri Svoboda2 * Copyright (c) 2021 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 35 35 36 36 #include <adt/list.h> 37 #include <ctype.h>38 37 #include <errno.h> 39 38 #include <gfx/color.h> … … 44 43 #include <stdlib.h> 45 44 #include <str.h> 46 #include <uchar.h>47 #include <ui/ui.h>48 #include <ui/accel.h>49 45 #include <ui/control.h> 50 46 #include <ui/paint.h> … … 54 50 #include <ui/resource.h> 55 51 #include <ui/window.h> 52 #include "../private/menubar.h" 56 53 #include "../private/menu.h" 57 54 #include "../private/resource.h" … … 66 63 67 64 static void ui_menu_popup_close(ui_popup_t *, void *); 68 static void ui_menu_popup_kbd(ui_popup_t *, void *, kbd_event_t *);69 65 static void ui_menu_popup_pos(ui_popup_t *, void *, pos_event_t *); 70 static void ui_menu_key_press_unmod(ui_menu_t *, kbd_event_t *);71 66 72 67 static ui_popup_cb_t ui_menu_popup_cb = { 73 68 .close = ui_menu_popup_close, 74 .kbd = ui_menu_popup_kbd,75 69 .pos = ui_menu_popup_pos 76 70 }; … … 78 72 /** Create new menu. 79 73 * 80 * @param parent Parent window81 74 * @param mbar Menu bar 75 * @param caption Caption 82 76 * @param rmenu Place to store pointer to new menu 83 77 * @return EOK on success, ENOMEM if out of memory 84 78 */ 85 errno_t ui_menu_create(ui_window_t *parent, ui_menu_t **rmenu) 79 errno_t ui_menu_create(ui_menu_bar_t *mbar, const char *caption, 80 ui_menu_t **rmenu) 86 81 { 87 82 ui_menu_t *menu; … … 91 86 return ENOMEM; 92 87 93 menu->parent = parent; 88 menu->caption = str_dup(caption); 89 if (menu->caption == NULL) { 90 free(menu); 91 return ENOMEM; 92 } 93 94 menu->mbar = mbar; 95 list_append(&menu->lmenus, &mbar->menus); 94 96 list_initialize(&menu->entries); 95 97 … … 116 118 } 117 119 120 list_remove(&menu->lmenus); 118 121 free(menu->caption); 119 122 free(menu); 120 123 } 121 124 122 /** Set menu callbacks. 123 * 124 * @param menu Menu 125 * @param cb Callbacks 126 * @param arg Callback argument 127 */ 128 void ui_menu_set_cb(ui_menu_t *menu, ui_menu_cb_t *cb, void *arg) 129 { 130 menu->cb = cb; 131 menu->arg = arg; 125 /** Get first menu in menu bar. 126 * 127 * @param mbar Menu bar 128 * @return First menu or @c NULL if there is none 129 */ 130 ui_menu_t *ui_menu_first(ui_menu_bar_t *mbar) 131 { 132 link_t *link; 133 134 link = list_first(&mbar->menus); 135 if (link == NULL) 136 return NULL; 137 138 return list_get_instance(link, ui_menu_t, lmenus); 139 } 140 141 /** Get next menu in menu bar. 142 * 143 * @param cur Current menu 144 * @return Next menu or @c NULL if @a cur is the last one 145 */ 146 ui_menu_t *ui_menu_next(ui_menu_t *cur) 147 { 148 link_t *link; 149 150 link = list_next(&cur->lmenus, &cur->mbar->menus); 151 if (link == NULL) 152 return NULL; 153 154 return list_get_instance(link, ui_menu_t, lmenus); 155 } 156 157 /** Get menu caption. 158 * 159 * @param menu Menu 160 * @return Caption (owned by @a menu) 161 */ 162 const char *ui_menu_caption(ui_menu_t *menu) 163 { 164 return menu->caption; 132 165 } 133 166 … … 141 174 ui_menu_geom_t *geom) 142 175 { 176 ui_resource_t *res; 143 177 gfx_coord2_t edim; 144 178 gfx_coord_t frame_w; 145 179 gfx_coord_t frame_h; 146 ui_resource_t *res; 147 148 res = ui_window_get_res(menu->parent); 180 181 res = ui_window_get_res(menu->mbar->window); 149 182 150 183 if (res->textmode) { … … 170 203 } 171 204 205 /** Get menu rectangle. 206 * 207 * @param menu Menu 208 * @param spos Starting position (top-left corner) 209 * @param rect Place to store menu rectangle 210 */ 211 void ui_menu_get_rect(ui_menu_t *menu, gfx_coord2_t *spos, gfx_rect_t *rect) 212 { 213 ui_menu_geom_t geom; 214 215 ui_menu_get_geom(menu, spos, &geom); 216 *rect = geom.outer_rect; 217 } 218 172 219 /** Get UI resource from menu. 173 220 * … … 184 231 * @param menu Menu 185 232 * @param prect Parent rectangle around which the menu should be placed 186 * @param idev_id Input device associated with the menu's seat 187 */ 188 errno_t ui_menu_open(ui_menu_t *menu, gfx_rect_t *prect, sysarg_t idev_id) 233 */ 234 errno_t ui_menu_open(ui_menu_t *menu, gfx_rect_t *prect) 189 235 { 190 236 ui_popup_t *popup = NULL; … … 193 239 gfx_coord2_t mpos; 194 240 errno_t rc; 195 196 /* Select first entry */197 menu->selected = ui_menu_entry_first(menu);198 241 199 242 /* Determine menu dimensions */ … … 206 249 params.rect = geom.outer_rect; 207 250 params.place = *prect; 208 params.idev_id = idev_id; 209 210 rc = ui_popup_create(ui_window_get_ui(menu->parent), menu->parent, 211 ¶ms, &popup); 251 252 rc = ui_popup_create(menu->mbar->ui, menu->mbar->window, ¶ms, 253 &popup); 212 254 if (rc != EOK) 213 255 return rc; … … 227 269 ui_popup_destroy(menu->popup); 228 270 menu->popup = NULL; 229 }230 231 /** Determine if menu is open.232 *233 * @param menu Menu234 * @return @c true iff menu is open235 */236 bool ui_menu_is_open(ui_menu_t *menu)237 {238 return menu->popup != NULL;239 271 } 240 272 … … 407 439 /* Press outside menu - close it */ 408 440 if (event->type == POS_PRESS) 409 ui_menu_ close_req(menu);441 ui_menu_bar_select(menu->mbar, NULL, NULL); 410 442 } 411 443 412 444 return ui_unclaimed; 413 }414 415 /** Handle keyboard event in menu.416 *417 * @param menu Menu418 * @param event Keyboard event419 * @return ui_claimed iff the event was claimed420 */421 ui_evclaim_t ui_menu_kbd_event(ui_menu_t *menu, kbd_event_t *event)422 {423 if (event->type == KEY_PRESS && (event->mods &424 (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {425 ui_menu_key_press_unmod(menu, event);426 }427 428 if (event->type == KEY_PRESS && (event->mods & KM_ALT) != 0 &&429 (event->mods & (KM_CTRL | KM_SHIFT)) == 0 && event->c != '\0')430 ui_menu_press_accel(menu, event->c, event->kbd_id);431 432 return ui_claimed;433 }434 435 /** Move one entry up.436 *437 * Non-selectable entries are skipped. If we are already at the top,438 * we wrap around.439 *440 * @param menu Menu441 */442 void ui_menu_up(ui_menu_t *menu)443 {444 gfx_coord2_t mpos;445 ui_menu_entry_t *nentry;446 447 if (menu->selected == NULL)448 return;449 450 nentry = ui_menu_entry_prev(menu->selected);451 if (nentry == NULL)452 nentry = ui_menu_entry_last(menu);453 454 /* Need to find a selectable entry */455 while (!ui_menu_entry_selectable(nentry)) {456 nentry = ui_menu_entry_prev(nentry);457 if (nentry == NULL)458 nentry = ui_menu_entry_last(menu);459 460 /* Went completely around and found nothing? */461 if (nentry == menu->selected)462 return;463 }464 465 menu->selected = nentry;466 467 mpos.x = 0;468 mpos.y = 0;469 (void) ui_menu_paint(menu, &mpos);470 }471 472 /** Move one entry down.473 *474 * Non-selectable entries are skipped. If we are already at the bottom,475 * we wrap around.476 *477 * @param menu Menu478 */479 void ui_menu_down(ui_menu_t *menu)480 {481 gfx_coord2_t mpos;482 ui_menu_entry_t *nentry;483 484 if (menu->selected == NULL)485 return;486 487 nentry = ui_menu_entry_next(menu->selected);488 if (nentry == NULL)489 nentry = ui_menu_entry_first(menu);490 491 /* Need to find a selectable entry */492 while (!ui_menu_entry_selectable(nentry)) {493 nentry = ui_menu_entry_next(nentry);494 if (nentry == NULL)495 nentry = ui_menu_entry_first(menu);496 497 /* Went completely around and found nothing? */498 if (nentry == menu->selected)499 return;500 }501 502 menu->selected = nentry;503 504 mpos.x = 0;505 mpos.y = 0;506 (void) ui_menu_paint(menu, &mpos);507 }508 509 /** Handle key press without modifiers in menu popup window.510 *511 * @param menu Menu512 * @param event Keyboard event513 */514 static void ui_menu_key_press_unmod(ui_menu_t *menu, kbd_event_t *event)515 {516 ui_menu_entry_t *mentry;517 char32_t c;518 519 switch (event->key) {520 case KC_ESCAPE:521 ui_menu_close_req(menu);522 break;523 case KC_LEFT:524 ui_menu_left(menu, event->kbd_id);525 break;526 case KC_RIGHT:527 ui_menu_right(menu, event->kbd_id);528 break;529 case KC_UP:530 ui_menu_up(menu);531 break;532 case KC_DOWN:533 ui_menu_down(menu);534 break;535 case KC_ENTER:536 if (menu->selected != NULL &&537 !ui_menu_entry_is_disabled(menu->selected))538 ui_menu_entry_activate(menu->selected);539 break;540 default:541 if (event->c != '\0') {542 mentry = ui_menu_entry_first(menu);543 while (mentry != NULL) {544 c = ui_menu_entry_get_accel(mentry);545 if (c == (char32_t)tolower(event->c) &&546 !ui_menu_entry_is_disabled(mentry)) {547 ui_menu_entry_activate(mentry);548 break;549 }550 mentry = ui_menu_entry_next(mentry);551 }552 }553 break;554 }555 445 } 556 446 … … 564 454 ui_menu_t *menu = (ui_menu_t *)arg; 565 455 566 /* Forward close request to caller */ 567 ui_menu_close_req(menu); 568 } 569 570 /** Handle keyboard event in menu popup window. 571 * 572 * @param popup Menu popup window 573 * @param arg Argument (ui_menu_t *) 574 * @param event Keyboard event 575 */ 576 static void ui_menu_popup_kbd(ui_popup_t *popup, void *arg, kbd_event_t *event) 577 { 578 ui_menu_t *menu = (ui_menu_t *)arg; 579 580 menu->idev_id = ui_popup_get_idev_id(menu->popup); 581 ui_menu_kbd_event(menu, event); 456 /* Close the menu */ 457 ui_menu_bar_select(menu->mbar, NULL, NULL); 582 458 } 583 459 … … 593 469 gfx_coord2_t spos; 594 470 595 menu->idev_id = ui_popup_get_idev_id(menu->popup);596 597 471 spos.x = 0; 598 472 spos.y = 0; … … 600 474 } 601 475 602 /** Send menu left event.603 *604 * @param menu Menu605 * @param idev_id Input device ID606 */607 void ui_menu_left(ui_menu_t *menu, sysarg_t idev_id)608 {609 if (menu->cb != NULL && menu->cb->left != NULL)610 menu->cb->left(menu, menu->arg, idev_id);611 }612 613 /** Send menu right event.614 *615 * @param menu Menu616 * @param idev_id Input device ID617 */618 void ui_menu_right(ui_menu_t *menu, sysarg_t idev_id)619 {620 if (menu->cb != NULL && menu->cb->right != NULL)621 menu->cb->right(menu, menu->arg, idev_id);622 }623 624 /** Send menu close request event.625 *626 * @param menu Menu627 */628 void ui_menu_close_req(ui_menu_t *menu)629 {630 if (menu->cb != NULL && menu->cb->close_req != NULL)631 menu->cb->close_req(menu, menu->arg);632 }633 634 /** Send menu accelerator key press event.635 *636 * @param menu Menu637 * @param c Character638 * @param kbd_id Keyboard ID639 */640 void ui_menu_press_accel(ui_menu_t *menu, char32_t c, sysarg_t kbd_id)641 {642 if (menu->cb != NULL && menu->cb->press_accel != NULL)643 menu->cb->press_accel(menu, menu->arg, c, kbd_id);644 }645 646 /** Get ID of last device that input event.647 *648 * @param menu Menu649 * @return Input device ID650 */651 sysarg_t ui_menu_get_idev_id(ui_menu_t *menu)652 {653 return menu->idev_id;654 }655 656 476 /** @} 657 477 */
Note:
See TracChangeset
for help on using the changeset viewer.
