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


Ignore:
Timestamp:
2022-01-10T19:29:00Z (2 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/menubar.c

    r9754ed2 r59768c7  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2022 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    6060static void ui_menu_bar_ctl_destroy(void *);
    6161static errno_t ui_menu_bar_ctl_paint(void *);
     62static ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *, kbd_event_t *);
    6263static ui_evclaim_t ui_menu_bar_ctl_pos_event(void *, pos_event_t *);
    6364
     
    6667        .destroy = ui_menu_bar_ctl_destroy,
    6768        .paint = ui_menu_bar_ctl_paint,
    68         .pos_event = ui_menu_bar_ctl_pos_event,
     69        .kbd_event = ui_menu_bar_ctl_kbd_event,
     70        .pos_event = ui_menu_bar_ctl_pos_event
    6971};
    7072
     
    236238 *
    237239 * @param mbar Menu bar
    238  * @param rect Menu bar entry rectangle
    239240 * @param menu Menu to select (or deselect if selected) or @c NULL
    240  */
    241 void ui_menu_bar_select(ui_menu_bar_t *mbar, gfx_rect_t *rect,
    242     ui_menu_t *menu)
     241 * @param openup Open menu even if not currently open
     242 */
     243void ui_menu_bar_select(ui_menu_bar_t *mbar, ui_menu_t *menu, bool openup)
    243244{
    244245        ui_menu_t *old_menu;
     246        gfx_rect_t rect;
     247        bool was_open;
    245248
    246249        old_menu = mbar->selected;
     
    252255
    253256        /* Close previously open menu */
    254         if (old_menu != NULL)
     257        if (old_menu != NULL && ui_menu_is_open(old_menu)) {
     258                was_open = true;
    255259                (void) ui_menu_close(old_menu);
     260        } else {
     261                was_open = false;
     262        }
    256263
    257264        (void) ui_menu_bar_paint(mbar);
    258265
    259266        if (mbar->selected != NULL) {
    260                 (void) ui_menu_open(mbar->selected, rect);
    261         }
     267                ui_menu_bar_entry_rect(mbar, mbar->selected, &rect);
     268                if (openup || was_open) {
     269                        /*
     270                         * Open the newly selected menu if either
     271                         * the old menu was open or @a openup was
     272                         * specified.
     273                         */
     274                        (void) ui_menu_open(mbar->selected, &rect);
     275                }
     276        }
     277}
     278
     279/** Move one entry left.
     280 *
     281 * If the selected menu is open, the newly selected menu will be open
     282 * as well. If we are already at the first entry, we wrap around.
     283 *
     284 * @param mbar Menu bar
     285 */
     286void ui_menu_bar_left(ui_menu_bar_t *mbar)
     287{
     288        ui_menu_t *nmenu;
     289
     290        if (mbar->selected == NULL)
     291                return;
     292
     293        nmenu = ui_menu_prev(mbar->selected);
     294        if (nmenu == NULL)
     295                nmenu = ui_menu_last(mbar);
     296
     297        ui_menu_bar_select(mbar, nmenu, false);
     298}
     299
     300/** Move one entry right.
     301 *
     302 * If the selected menu is open, the newly selected menu will be open
     303 * as well. If we are already at the last entry, we wrap around.
     304 *
     305 * @param mbar Menu bar
     306 */
     307void ui_menu_bar_right(ui_menu_bar_t *mbar)
     308{
     309        ui_menu_t *nmenu;
     310
     311        if (mbar->selected == NULL)
     312                return;
     313
     314        nmenu = ui_menu_next(mbar->selected);
     315        if (nmenu == NULL)
     316                nmenu = ui_menu_first(mbar);
     317
     318        ui_menu_bar_select(mbar, nmenu, false);
     319}
     320
     321/** Handle menu bar key press without modifiers.
     322 *
     323 * @param mbar Menu bar
     324 * @param kbd_event Keyboard event
     325 * @return @c ui_claimed iff the event is claimed
     326 */
     327ui_evclaim_t ui_menu_bar_key_press_unmod(ui_menu_bar_t *mbar, kbd_event_t *event)
     328{
     329        gfx_rect_t rect;
     330
     331        if (event->key == KC_F10) {
     332                ui_menu_bar_activate(mbar);
     333                return ui_claimed;
     334        }
     335
     336        if (!mbar->active)
     337                return ui_unclaimed;
     338
     339        if (event->key == KC_ESCAPE) {
     340                ui_menu_bar_deactivate(mbar);
     341                return ui_claimed;
     342        }
     343
     344        if (event->key == KC_LEFT)
     345                ui_menu_bar_left(mbar);
     346
     347        if (event->key == KC_RIGHT)
     348                ui_menu_bar_right(mbar);
     349
     350        if (event->key == KC_ENTER || event->key == KC_DOWN) {
     351                if (mbar->selected != NULL && !ui_menu_is_open(mbar->selected)) {
     352                        ui_menu_bar_entry_rect(mbar, mbar->selected,
     353                            &rect);
     354                        ui_menu_open(mbar->selected, &rect);
     355                }
     356
     357                return ui_claimed;
     358        }
     359
     360        return ui_claimed;
     361}
     362
     363/** Handle menu bar keyboard event.
     364 *
     365 * @param mbar Menu bar
     366 * @param kbd_event Keyboard event
     367 * @return @c ui_claimed iff the event is claimed
     368 */
     369ui_evclaim_t ui_menu_bar_kbd_event(ui_menu_bar_t *mbar, kbd_event_t *event)
     370{
     371        if (event->type == KEY_PRESS && (event->mods &
     372            (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
     373                ui_menu_bar_key_press_unmod(mbar, event);
     374                return ui_claimed;
     375        }
     376
     377        return ui_claimed;
    262378}
    263379
     
    304420                if (event->type == POS_PRESS &&
    305421                    gfx_pix_inside_rect(&ppos, &rect)) {
    306                         ui_menu_bar_select(mbar, &rect, menu);
     422                        mbar->active = true;
     423                        ui_menu_bar_select(mbar, menu, true);
    307424                        return ui_claimed;
    308425                }
     
    315432}
    316433
     434/** Handle menu bar position event.
     435 *
     436 * @param mbar Menu bar
     437 * @param menu Menu whose entry's rectangle is to be returned
     438 * @param rrect Place to store entry rectangle
     439 */
     440void ui_menu_bar_entry_rect(ui_menu_bar_t *mbar, ui_menu_t *menu,
     441    gfx_rect_t *rrect)
     442{
     443        ui_resource_t *res;
     444        gfx_coord2_t pos;
     445        gfx_rect_t rect;
     446        ui_menu_t *cur;
     447        const char *caption;
     448        gfx_coord_t width;
     449        gfx_coord_t hpad;
     450
     451        res = ui_window_get_res(mbar->window);
     452
     453        if (res->textmode) {
     454                hpad = menubar_hpad_text;
     455        } else {
     456                hpad = menubar_hpad;
     457        }
     458
     459        pos = mbar->rect.p0;
     460
     461        cur = ui_menu_first(mbar);
     462        while (cur != NULL) {
     463                caption = ui_menu_caption(cur);
     464                width = gfx_text_width(res->font, caption) + 2 * hpad;
     465
     466                rect.p0 = pos;
     467                rect.p1.x = rect.p0.x + width;
     468                rect.p1.y = mbar->rect.p1.y;
     469
     470                if (cur == menu) {
     471                        *rrect = rect;
     472                        return;
     473                }
     474
     475                pos.x += width;
     476                cur = ui_menu_next(cur);
     477        }
     478
     479        /* We should never get here */
     480        assert(false);
     481}
     482
     483/** Activate menu bar.
     484 *
     485 * @param mbar Menu bar
     486 */
     487void ui_menu_bar_activate(ui_menu_bar_t *mbar)
     488{
     489        if (mbar->active)
     490                return;
     491
     492        mbar->active = true;
     493        if (mbar->selected == NULL)
     494                mbar->selected = ui_menu_first(mbar);
     495
     496        (void) ui_menu_bar_paint(mbar);
     497}
     498
     499void ui_menu_bar_deactivate(ui_menu_bar_t *mbar)
     500{
     501        ui_menu_bar_select(mbar, NULL, false);
     502        mbar->active = false;
     503}
     504
    317505/** Destroy menu bar control.
    318506 *
     
    338526}
    339527
    340 /** Handle menu bar control position event.
     528/** Handle menu bar control keyboard event.
    341529 *
    342530 * @param arg Argument (ui_menu_bar_t *)
     
    344532 * @return @c ui_claimed iff the event is claimed
    345533 */
     534ui_evclaim_t ui_menu_bar_ctl_kbd_event(void *arg, kbd_event_t *event)
     535{
     536        ui_menu_bar_t *mbar = (ui_menu_bar_t *) arg;
     537
     538        return ui_menu_bar_kbd_event(mbar, event);
     539}
     540
     541/** Handle menu bar control position event.
     542 *
     543 * @param arg Argument (ui_menu_bar_t *)
     544 * @param pos_event Position event
     545 * @return @c ui_claimed iff the event is claimed
     546 */
    346547ui_evclaim_t ui_menu_bar_ctl_pos_event(void *arg, pos_event_t *event)
    347548{
Note: See TracChangeset for help on using the changeset viewer.