Changeset 59768c7 in mainline for uspace/lib/ui/src/menu.c


Ignore:
Timestamp:
2022-01-10T19:29:00Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5de852c
Parents:
9754ed2
git-author:
Jiri Svoboda <jiri@…> (2022-01-10 19:27:55)
git-committer:
Jiri Svoboda <jiri@…> (2022-01-10 19:29:00)
Message:

Menu control using F10, cursor keys, Enter, Escape

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/src/menu.c

    r9754ed2 r59768c7  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2022 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4747#include <ui/popup.h>
    4848#include <ui/menu.h>
     49#include <ui/menubar.h>
    4950#include <ui/menuentry.h>
    5051#include <ui/resource.h>
     
    6364
    6465static void ui_menu_popup_close(ui_popup_t *, void *);
     66static void ui_menu_popup_kbd(ui_popup_t *, void *, kbd_event_t *);
    6567static void ui_menu_popup_pos(ui_popup_t *, void *, pos_event_t *);
    6668
    6769static ui_popup_cb_t ui_menu_popup_cb = {
    6870        .close = ui_menu_popup_close,
     71        .kbd = ui_menu_popup_kbd,
    6972        .pos = ui_menu_popup_pos
    7073};
     
    149152
    150153        link = list_next(&cur->lmenus, &cur->mbar->menus);
     154        if (link == NULL)
     155                return NULL;
     156
     157        return list_get_instance(link, ui_menu_t, lmenus);
     158}
     159
     160/** Get last menu in menu bar.
     161 *
     162 * @param mbar Menu bar
     163 * @return Last menu or @c NULL if there is none
     164 */
     165ui_menu_t *ui_menu_last(ui_menu_bar_t *mbar)
     166{
     167        link_t *link;
     168
     169        link = list_last(&mbar->menus);
     170        if (link == NULL)
     171                return NULL;
     172
     173        return list_get_instance(link, ui_menu_t, lmenus);
     174}
     175
     176/** Get previous menu in menu bar.
     177 *
     178 * @param cur Current menu
     179 * @return Previous menu or @c NULL if @a cur is the fist one
     180 */
     181ui_menu_t *ui_menu_prev(ui_menu_t *cur)
     182{
     183        link_t *link;
     184
     185        link = list_prev(&cur->lmenus, &cur->mbar->menus);
    151186        if (link == NULL)
    152187                return NULL;
     
    240275        errno_t rc;
    241276
     277        /* Select first entry */
     278        menu->selected = ui_menu_entry_first(menu);
     279
    242280        /* Determine menu dimensions */
    243281
     
    269307        ui_popup_destroy(menu->popup);
    270308        menu->popup = NULL;
     309}
     310
     311/** Determine if menu is open.
     312 *
     313 * @param menu Menu
     314 * @return @c true iff menu is open
     315 */
     316bool ui_menu_is_open(ui_menu_t *menu)
     317{
     318        return menu->popup != NULL;
    271319}
    272320
     
    439487                /* Press outside menu - close it */
    440488                if (event->type == POS_PRESS)
    441                         ui_menu_bar_select(menu->mbar, NULL, NULL);
     489                        ui_menu_bar_deactivate(menu->mbar);
    442490        }
    443491
     
    454502        ui_menu_t *menu = (ui_menu_t *)arg;
    455503
    456         /* Close the menu */
    457         ui_menu_bar_select(menu->mbar, NULL, NULL);
     504        /* Deactivate menu bar, close menu */
     505        ui_menu_bar_deactivate(menu->mbar);
     506}
     507
     508/** Move one entry up.
     509 *
     510 * Non-selectable entries are skipped. If we are already at the top,
     511 * we wrap around.
     512 *
     513 * @param menu Menu
     514 */
     515void ui_menu_up(ui_menu_t *menu)
     516{
     517        gfx_coord2_t mpos;
     518        ui_menu_entry_t *nentry;
     519
     520        if (menu->selected == NULL)
     521                return;
     522
     523        nentry = ui_menu_entry_prev(menu->selected);
     524        if (nentry == NULL)
     525                nentry = ui_menu_entry_last(menu);
     526
     527        /* Need to find a selectable entry */
     528        while (!ui_menu_entry_selectable(nentry)) {
     529                nentry = ui_menu_entry_prev(nentry);
     530                if (nentry == NULL)
     531                        nentry = ui_menu_entry_last(menu);
     532
     533                /* Went completely around and found nothing? */
     534                if (nentry == menu->selected)
     535                        return;
     536        }
     537
     538        menu->selected = nentry;
     539
     540        mpos.x = 0;
     541        mpos.y = 0;
     542        (void) ui_menu_paint(menu, &mpos);
     543}
     544
     545/** Move one entry down.
     546 *
     547 * Non-selectable entries are skipped. If we are already at the bottom,
     548 * we wrap around.
     549 *
     550 * @param menu Menu
     551 */
     552void ui_menu_down(ui_menu_t *menu)
     553{
     554        gfx_coord2_t mpos;
     555        ui_menu_entry_t *nentry;
     556
     557        if (menu->selected == NULL)
     558                return;
     559
     560        nentry = ui_menu_entry_next(menu->selected);
     561        if (nentry == NULL)
     562                nentry = ui_menu_entry_first(menu);
     563
     564        /* Need to find a selectable entry */
     565        while (!ui_menu_entry_selectable(nentry)) {
     566                nentry = ui_menu_entry_next(nentry);
     567                if (nentry == NULL)
     568                        nentry = ui_menu_entry_first(menu);
     569
     570                /* Went completely around and found nothing? */
     571                if (nentry == menu->selected)
     572                        return;
     573        }
     574
     575        menu->selected = nentry;
     576
     577        mpos.x = 0;
     578        mpos.y = 0;
     579        (void) ui_menu_paint(menu, &mpos);
     580}
     581
     582/** Handle key press without modifiers in menu popup window.
     583 *
     584 * @param menu Menu
     585 * @param event Keyboard event
     586 */
     587static void ui_menu_key_press_unmod(ui_menu_t *menu, kbd_event_t *event)
     588{
     589        switch (event->key) {
     590        case KC_ESCAPE:
     591                ui_menu_bar_deactivate(menu->mbar);
     592                break;
     593        case KC_LEFT:
     594                ui_menu_bar_left(menu->mbar);
     595                break;
     596        case KC_RIGHT:
     597                ui_menu_bar_right(menu->mbar);
     598                break;
     599        case KC_UP:
     600                ui_menu_up(menu);
     601                break;
     602        case KC_DOWN:
     603                ui_menu_down(menu);
     604                break;
     605        case KC_ENTER:
     606                if (menu->selected != NULL)
     607                        ui_menu_entry_activate(menu->selected);
     608                break;
     609        default:
     610                break;
     611        }
     612}
     613
     614/** Handle keyboard event in menu popup window.
     615 *
     616 * @param popup Menu popup window
     617 * @param arg Argument (ui_menu_t *)
     618 * @param event Keyboard event
     619 */
     620static void ui_menu_popup_kbd(ui_popup_t *popup, void *arg, kbd_event_t *event)
     621{
     622        ui_menu_t *menu = (ui_menu_t *)arg;
     623
     624        if (event->type == KEY_PRESS && (event->mods &
     625            (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
     626                ui_menu_key_press_unmod(menu, event);
     627        }
    458628}
    459629
Note: See TracChangeset for help on using the changeset viewer.