Changeset af2ea83 in mainline for uspace/app/nav/panel.c


Ignore:
Timestamp:
2021-10-12T17:06:45Z (3 years ago)
Author:
Jiri Svoboda <jiri@…>
Children:
3e6c51f
Parents:
166aba54
git-author:
Jiri Svoboda <jiri@…> (2021-10-12 17:06:35)
git-committer:
Jiri Svoboda <jiri@…> (2021-10-12 17:06:45)
Message:

Cursor movement (up, down, to top, to bottom)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/nav/panel.c

    r166aba54 raf2ea83  
    4949static void panel_ctl_destroy(void *);
    5050static errno_t panel_ctl_paint(void *);
     51static ui_evclaim_t panel_ctl_kbd_event(void *, kbd_event_t *);
    5152static ui_evclaim_t panel_ctl_pos_event(void *, pos_event_t *);
    5253
     
    5556        .destroy = panel_ctl_destroy,
    5657        .paint = panel_ctl_paint,
     58        .kbd_event = panel_ctl_kbd_event,
    5759        .pos_event = panel_ctl_pos_event
    5860};
     
    9092        panel->window = window;
    9193        list_initialize(&panel->entries);
     94        panel->entries_cnt = 0;
    9295        *rpanel = panel;
    9396        return EOK;
     
    115118}
    116119
    117 /** Paint panel.
    118  *
    119  * @param panel Panel
    120  */
    121 errno_t panel_paint(panel_t *panel)
    122 {
     120/** Paint panel entry.
     121 *
     122 * @param entry Panel entry
     123 * @param entry_idx Entry index (within list of entries)
     124 * @return EOK on success or an error code
     125 */
     126errno_t panel_entry_paint(panel_entry_t *entry, size_t entry_idx)
     127{
     128        panel_t *panel = entry->panel;
    123129        gfx_context_t *gc = ui_window_get_gc(panel->window);
    124130        ui_resource_t *res = ui_window_get_res(panel->window);
    125131        gfx_font_t *font = ui_resource_get_font(res);
    126132        gfx_text_fmt_t fmt;
    127         panel_entry_t *entry;
    128133        gfx_coord2_t pos;
    129134        gfx_rect_t rect;
     135        size_t rows;
     136        errno_t rc;
     137
     138        gfx_text_fmt_init(&fmt);
     139
     140        rows = panel->rect.p1.y - panel->rect.p0.y - 2;
     141
     142        /* Do not display entry outside of current page */
     143        if (entry_idx < panel->page_idx ||
     144            entry_idx >= panel->page_idx + rows)
     145                return EOK;
     146
     147        pos.x = panel->rect.p0.x + 1;
     148        pos.y = panel->rect.p0.y + 1 + entry_idx - panel->page_idx;
     149
     150        if (entry == panel->cursor)
     151                fmt.color = panel->curs_color;
     152        else
     153                fmt.color = panel->color;
     154
     155        /* Draw entry background */
     156        rect.p0 = pos;
     157        rect.p1.x = panel->rect.p1.x - 1;
     158        rect.p1.y = rect.p0.y + 1;
     159
     160        rc = gfx_set_color(gc, fmt.color);
     161        if (rc != EOK)
     162                return rc;
     163
     164        rc = gfx_fill_rect(gc, &rect);
     165        if (rc != EOK)
     166                return rc;
     167
     168        rc = gfx_puttext(font, &pos, &fmt, entry->name);
     169        if (rc != EOK)
     170                return rc;
     171
     172        return EOK;
     173}
     174
     175/** Paint panel.
     176 *
     177 * @param panel Panel
     178 */
     179errno_t panel_paint(panel_t *panel)
     180{
     181        gfx_context_t *gc = ui_window_get_gc(panel->window);
     182        ui_resource_t *res = ui_window_get_res(panel->window);
     183        gfx_text_fmt_t fmt;
     184        panel_entry_t *entry;
     185        int i, lines;
    130186        errno_t rc;
    131187
     
    145201                return rc;
    146202
    147         pos.x = panel->rect.p0.x + 1;
    148         pos.y = panel->rect.p0.y + 1;
     203        lines = panel->rect.p1.y - panel->rect.p0.y - 2;
     204        i = 0;
    149205
    150206        entry = panel->page;
    151         while (entry != NULL && pos.y < panel->rect.p1.y - 1) {
    152                 if (entry == panel->cursor) {
    153                         /* Draw cursor background */
    154                         rect.p0 = pos;
    155                         rect.p1.x = panel->rect.p1.x - 1;
    156                         rect.p1.y = rect.p0.y + 1;
    157 
    158                         rc = gfx_set_color(gc, panel->curs_color);
    159                         if (rc != EOK)
    160                                 return rc;
    161 
    162                         rc = gfx_fill_rect(gc, &rect);
    163                         if (rc != EOK)
    164                                 return rc;
    165 
    166                         fmt.color = panel->curs_color;
    167                 } else {
    168                         fmt.color = panel->color;
    169                 }
    170 
    171                 rc = gfx_puttext(font, &pos, &fmt, entry->name);
     207        while (entry != NULL && i < lines) {
     208                rc = panel_entry_paint(entry, panel->page_idx + i);
    172209                if (rc != EOK)
    173210                        return rc;
    174211
    175                 pos.y++;
     212                ++i;
    176213                entry = panel_next(entry);
    177214        }
     
    184221}
    185222
     223/** Handle panel keyboard event.
     224 *
     225 * @param panel Panel
     226 * @param event Keyboard event
     227 * @return ui_claimed iff event was claimed
     228 */
     229ui_evclaim_t panel_kbd_event(panel_t *panel, kbd_event_t *event)
     230{
     231        if (event->type == KEY_PRESS) {
     232                if ((event->mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
     233                        switch (event->key) {
     234                        case KC_UP:
     235                                panel_cursor_up(panel);
     236                                break;
     237                        case KC_DOWN:
     238                                panel_cursor_down(panel);
     239                                break;
     240                        case KC_HOME:
     241                                panel_cursor_top(panel);
     242                                break;
     243                        case KC_END:
     244                                panel_cursor_bottom(panel);
     245                                break;
     246                        default:
     247                                break;
     248                        }
     249                }
     250        }
     251
     252        return ui_unclaimed;
     253}
     254
    186255/** Handle panel position event.
    187256 *
     
    236305
    237306        return panel_paint(panel);
     307}
     308
     309/** Handle panel control keyboard event.
     310 *
     311 * @param arg Argument (panel_t *)
     312 * @param kbd_event Keyboard event
     313 * @return @c ui_claimed iff the event is claimed
     314 */
     315ui_evclaim_t panel_ctl_kbd_event(void *arg, kbd_event_t *event)
     316{
     317        panel_t *panel = (panel_t *) arg;
     318
     319        return panel_kbd_event(panel, event);
    238320}
    239321
     
    276358        link_initialize(&entry->lentries);
    277359        list_append(&entry->lentries, &panel->entries);
     360        ++panel->entries_cnt;
    278361        return EOK;
    279362}
     
    291374
    292375        list_remove(&entry->lentries);
     376        --entry->panel->entries_cnt;
    293377        free(entry->name);
    294378        free(entry);
     
    337421
    338422        panel->cursor = panel_first(panel);
     423        panel->cursor_idx = 0;
    339424        panel->page = panel_first(panel);
     425        panel->page_idx = 0;
    340426        return EOK;
    341427error:
     
    360446}
    361447
     448/** Return last panel entry.
     449 *
     450 * @panel Panel
     451 * @return Last panel entry or @c NULL if there are no entries
     452 */
     453panel_entry_t *panel_last(panel_t *panel)
     454{
     455        link_t *link;
     456
     457        link = list_last(&panel->entries);
     458        if (link == NULL)
     459                return NULL;
     460
     461        return list_get_instance(link, panel_entry_t, lentries);
     462}
     463
    362464/** Return next panel entry.
    363465 *
     
    376478}
    377479
     480/** Return previous panel entry.
     481 *
     482 * @param cur Current entry
     483 * @return Previous entry or @c NULL if @a cur is the first entry
     484 */
     485panel_entry_t *panel_prev(panel_entry_t *cur)
     486{
     487        link_t *link;
     488
     489        link = list_prev(&cur->lentries, &cur->panel->entries);
     490        if (link == NULL)
     491                return NULL;
     492
     493        return list_get_instance(link, panel_entry_t, lentries);
     494}
     495
     496void panel_cursor_move(panel_t *panel, panel_entry_t *entry, size_t entry_idx)
     497{
     498        gfx_context_t *gc = ui_window_get_gc(panel->window);
     499        panel_entry_t *old_cursor;
     500        size_t old_idx;
     501        size_t rows;
     502        panel_entry_t *e;
     503        size_t i;
     504
     505        rows = panel->rect.p1.y - panel->rect.p0.y - 2;
     506
     507        old_cursor = panel->cursor;
     508        old_idx = panel->cursor_idx;
     509
     510        panel->cursor = entry;
     511        panel->cursor_idx = entry_idx;
     512
     513        if (entry_idx >= panel->page_idx &&
     514            entry_idx < panel->page_idx + rows) {
     515                /*
     516                 * If cursor is still on the current page, we're not
     517                 * scrolling. Just unpaint old cursor and paint new
     518                 * cursor.
     519                 */
     520                panel_entry_paint(old_cursor, old_idx);
     521                panel_entry_paint(panel->cursor, panel->cursor_idx);
     522
     523                (void) gfx_update(gc);
     524        } else {
     525                /*
     526                 * Need to scroll and update all rows.
     527                 */
     528
     529                /* Scrolling up */
     530                if (entry_idx < panel->page_idx) {
     531                        panel->page = entry;
     532                        panel->page_idx = entry_idx;
     533                }
     534
     535                /* Scrolling down */
     536                if (entry_idx >= panel->page_idx + rows) {
     537                        if (entry_idx >= rows) {
     538                                panel->page_idx = entry_idx - rows + 1;
     539                                /* Find first page entry (go back rows - 1) */
     540                                e = entry;
     541                                for (i = 0; i < rows - 1; i++) {
     542                                        e = panel_prev(e);
     543                                }
     544
     545                                /* Should be valid */
     546                                assert(e != NULL);
     547                                panel->page = e;
     548                        } else {
     549                                panel->page = panel_first(panel);
     550                                panel->page_idx = 0;
     551                        }
     552                }
     553
     554                (void) panel_paint(panel);
     555        }
     556}
     557
     558/** Move cursor one entry up.
     559 *
     560 * @param panel Panel
     561 */
     562void panel_cursor_up(panel_t *panel)
     563{
     564        panel_entry_t *prev;
     565        size_t prev_idx;
     566
     567        prev = panel_prev(panel->cursor);
     568        prev_idx = panel->cursor_idx - 1;
     569        if (prev != NULL)
     570                panel_cursor_move(panel, prev, prev_idx);
     571}
     572
     573/** Move cursor one entry down.
     574 *
     575 * @param panel Panel
     576 */
     577void panel_cursor_down(panel_t *panel)
     578{
     579        panel_entry_t *next;
     580        size_t next_idx;
     581
     582        next = panel_next(panel->cursor);
     583        next_idx = panel->cursor_idx + 1;
     584        if (next != NULL)
     585                panel_cursor_move(panel, next, next_idx);
     586}
     587
     588/** Move cursor to top.
     589 *
     590 * @param panel Panel
     591 */
     592void panel_cursor_top(panel_t *panel)
     593{
     594        panel_cursor_move(panel, panel_first(panel), 0);
     595}
     596
     597/** Move cursor to bottom.
     598 *
     599 * @param panel Panel
     600 */
     601void panel_cursor_bottom(panel_t *panel)
     602{
     603        panel_cursor_move(panel, panel_last(panel), panel->entries_cnt - 1);
     604}
     605
    378606/** @}
    379607 */
Note: See TracChangeset for help on using the changeset viewer.