Changeset 54ddb59 in mainline for uspace/app/nav/panel.c


Ignore:
Timestamp:
2022-06-20T13:10:08Z (3 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
52214a2
Parents:
453f9645
git-author:
Jiri Svoboda <jiri@…> (2022-06-19 18:09:49)
git-committer:
Jiri Svoboda <jiri@…> (2022-06-20 13:10:08)
Message:

Base navigator panel on UI file list

Free scrollbar!

File:
1 edited

Legend:

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

    r453f9645 r54ddb59  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2022 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3535 */
    3636
    37 #include <dirent.h>
    3837#include <errno.h>
    3938#include <gfx/render.h>
    4039#include <gfx/text.h>
    4140#include <stdlib.h>
    42 #include <str.h>
    4341#include <task.h>
    4442#include <ui/control.h>
     43#include <ui/filelist.h>
    4544#include <ui/paint.h>
    4645#include <ui/resource.h>
    47 #include <vfs/vfs.h>
    48 #include <qsort.h>
    4946#include "panel.h"
    5047#include "nav.h"
     
    5653
    5754/** Panel control ops */
    58 ui_control_ops_t panel_ctl_ops = {
     55static ui_control_ops_t panel_ctl_ops = {
    5956        .destroy = panel_ctl_destroy,
    6057        .paint = panel_ctl_paint,
     
    6360};
    6461
     62static void panel_flist_selected(ui_file_list_t *, void *, const char *);
     63
     64/** Panel file list callbacks */
     65static ui_file_list_cb_t panel_flist_cb = {
     66        .selected = panel_flist_selected
     67};
     68
    6569/** Create panel.
    6670 *
     
    9094                goto error;
    9195
    92         rc = gfx_color_new_ega(0x30, &panel->curs_color);
     96        rc = gfx_color_new_ega(0x0f, &panel->act_border_color);
    9397        if (rc != EOK)
    9498                goto error;
    9599
    96         rc = gfx_color_new_ega(0x0f, &panel->act_border_color);
     100        rc = ui_file_list_create(window, active, &panel->flist);
    97101        if (rc != EOK)
    98102                goto error;
    99103
    100         rc = gfx_color_new_ega(0x0f, &panel->dir_color);
    101         if (rc != EOK)
    102                 goto error;
    103 
    104         rc = gfx_color_new_ega(0x0a, &panel->svc_color);
    105         if (rc != EOK)
    106                 goto error;
     104        ui_file_list_set_cb(panel->flist, &panel_flist_cb, (void *)panel);
    107105
    108106        panel->window = window;
    109         list_initialize(&panel->entries);
    110         panel->entries_cnt = 0;
    111107        panel->active = active;
    112108        *rpanel = panel;
     
    115111        if (panel->color != NULL)
    116112                gfx_color_delete(panel->color);
    117         if (panel->curs_color != NULL)
    118                 gfx_color_delete(panel->curs_color);
    119113        if (panel->act_border_color != NULL)
    120114                gfx_color_delete(panel->act_border_color);
    121         if (panel->dir_color != NULL)
    122                 gfx_color_delete(panel->dir_color);
    123         if (panel->svc_color != NULL)
    124                 gfx_color_delete(panel->svc_color);
     115        if (panel->flist != NULL)
     116                ui_file_list_destroy(panel->flist);
    125117        ui_control_delete(panel->control);
    126118        free(panel);
     
    135127{
    136128        gfx_color_delete(panel->color);
    137         gfx_color_delete(panel->curs_color);
    138129        gfx_color_delete(panel->act_border_color);
    139         gfx_color_delete(panel->dir_color);
    140         gfx_color_delete(panel->svc_color);
    141         panel_clear_entries(panel);
    142130        ui_control_delete(panel->control);
    143131        free(panel);
     
    156144}
    157145
    158 /** Paint panel entry.
    159  *
    160  * @param entry Panel entry
    161  * @param entry_idx Entry index (within list of entries)
    162  * @return EOK on success or an error code
    163  */
    164 errno_t panel_entry_paint(panel_entry_t *entry, size_t entry_idx)
    165 {
    166         panel_t *panel = entry->panel;
     146/** Paint panel.
     147 *
     148 * @param panel Panel
     149 */
     150errno_t panel_paint(panel_t *panel)
     151{
    167152        gfx_context_t *gc = ui_window_get_gc(panel->window);
    168153        ui_resource_t *res = ui_window_get_res(panel->window);
    169         gfx_font_t *font = ui_resource_get_font(res);
    170         gfx_text_fmt_t fmt;
    171         gfx_coord2_t pos;
    172         gfx_rect_t rect;
    173         size_t rows;
    174         errno_t rc;
    175 
    176         gfx_text_fmt_init(&fmt);
    177         fmt.font = font;
    178         rows = panel_page_size(panel);
    179 
    180         /* Do not display entry outside of current page */
    181         if (entry_idx < panel->page_idx ||
    182             entry_idx >= panel->page_idx + rows)
    183                 return EOK;
    184 
    185         pos.x = panel->rect.p0.x + 1;
    186         pos.y = panel->rect.p0.y + 1 + entry_idx - panel->page_idx;
    187 
    188         if (entry == panel->cursor && panel->active)
    189                 fmt.color = panel->curs_color;
    190         else if (entry->isdir)
    191                 fmt.color = panel->dir_color;
    192         else if (entry->svc != 0)
    193                 fmt.color = panel->svc_color;
    194         else
    195                 fmt.color = panel->color;
    196 
    197         /* Draw entry background */
    198         rect.p0 = pos;
    199         rect.p1.x = panel->rect.p1.x - 1;
    200         rect.p1.y = rect.p0.y + 1;
    201 
    202         rc = gfx_set_color(gc, fmt.color);
    203         if (rc != EOK)
    204                 return rc;
    205 
    206         rc = gfx_fill_rect(gc, &rect);
    207         if (rc != EOK)
    208                 return rc;
    209 
    210         /*
    211          * Make sure name does not overflow the entry rectangle.
    212          *
    213          * XXX We probably want to measure the text width, and,
    214          * if it's too long, use gfx_text_find_pos() to find where
    215          * it should be cut off (and append some sort of overflow
    216          * marker.
    217          */
    218         rc = gfx_set_clip_rect(gc, &rect);
    219         if (rc != EOK)
    220                 return rc;
    221 
    222         rc = gfx_puttext(&pos, &fmt, entry->name);
    223         if (rc != EOK) {
    224                 (void) gfx_set_clip_rect(gc, NULL);
    225                 return rc;
    226         }
    227 
    228         return gfx_set_clip_rect(gc, NULL);
    229 }
    230 
    231 /** Paint panel.
    232  *
    233  * @param panel Panel
    234  */
    235 errno_t panel_paint(panel_t *panel)
    236 {
    237         gfx_context_t *gc = ui_window_get_gc(panel->window);
    238         ui_resource_t *res = ui_window_get_res(panel->window);
    239         panel_entry_t *entry;
    240154        ui_box_style_t bstyle;
    241155        gfx_color_t *bcolor;
    242         int i, lines;
     156        ui_control_t *ctl;
    243157        errno_t rc;
    244158
     
    263177                return rc;
    264178
    265         lines = panel_page_size(panel);
    266         i = 0;
    267 
    268         entry = panel->page;
    269         while (entry != NULL && i < lines) {
    270                 rc = panel_entry_paint(entry, panel->page_idx + i);
    271                 if (rc != EOK)
    272                         return rc;
    273 
    274                 ++i;
    275                 entry = panel_next(entry);
    276         }
     179        ctl = ui_file_list_ctl(panel->flist);
     180        rc = ui_control_paint(ctl);
     181        if (rc != EOK)
     182                return rc;
    277183
    278184        rc = gfx_update(gc);
     
    291197ui_evclaim_t panel_kbd_event(panel_t *panel, kbd_event_t *event)
    292198{
     199        ui_control_t *ctl;
     200
    293201        if (!panel->active)
    294202                return ui_unclaimed;
    295203
    296         if (event->type == KEY_PRESS) {
    297                 if ((event->mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
    298                         switch (event->key) {
    299                         case KC_UP:
    300                                 panel_cursor_up(panel);
    301                                 break;
    302                         case KC_DOWN:
    303                                 panel_cursor_down(panel);
    304                                 break;
    305                         case KC_HOME:
    306                                 panel_cursor_top(panel);
    307                                 break;
    308                         case KC_END:
    309                                 panel_cursor_bottom(panel);
    310                                 break;
    311                         case KC_PAGE_UP:
    312                                 panel_page_up(panel);
    313                                 break;
    314                         case KC_PAGE_DOWN:
    315                                 panel_page_down(panel);
    316                                 break;
    317                         case KC_ENTER:
    318                                 panel_open(panel, panel->cursor);
    319                                 break;
    320                         default:
    321                                 break;
    322                         }
    323                 }
    324         }
    325 
    326         return ui_claimed;
     204        ctl = ui_file_list_ctl(panel->flist);
     205        return ui_control_kbd_event(ctl, event);
    327206}
    328207
     
    336215{
    337216        gfx_coord2_t pos;
    338         gfx_rect_t irect;
    339         panel_entry_t *entry;
    340         size_t entry_idx;
    341         int n;
     217        ui_control_t *ctl;
    342218
    343219        pos.x = event->hpos;
     
    349225                panel_activate_req(panel);
    350226
     227        ctl = ui_file_list_ctl(panel->flist);
     228        return ui_control_pos_event(ctl, event);
     229}
     230
     231/** Get base control for panel.
     232 *
     233 * @param panel Panel
     234 * @return Base UI control
     235 */
     236ui_control_t *panel_ctl(panel_t *panel)
     237{
     238        return panel->control;
     239}
     240
     241/** Set panel rectangle.
     242 *
     243 * @param panel Panel
     244 * @param rect Rectangle
     245 */
     246void panel_set_rect(panel_t *panel, gfx_rect_t *rect)
     247{
     248        gfx_rect_t irect;
     249
     250        panel->rect = *rect;
     251
    351252        irect.p0.x = panel->rect.p0.x + 1;
    352253        irect.p0.y = panel->rect.p0.y + 1;
    353         irect.p1.x = panel->rect.p1.x - 1;
     254        irect.p1.x = panel->rect.p1.x;
    354255        irect.p1.y = panel->rect.p1.y - 1;
    355256
    356         if (event->type == POS_PRESS || event->type == POS_DCLICK) {
    357                 /* Did we click on one of the entries? */
    358                 if (gfx_pix_inside_rect(&pos, &irect)) {
    359                         /* Index within page */
    360                         n = pos.y - irect.p0.y;
    361 
    362                         /* Entry and its index within entire listing */
    363                         entry = panel_page_nth_entry(panel, n, &entry_idx);
    364 
    365                         if (event->type == POS_PRESS) {
    366                                 /* Move to the entry found */
    367                                 panel_cursor_move(panel, entry, entry_idx);
    368                         } else {
    369                                 /* event->type == POS_DCLICK */
    370                                 panel_open(panel, entry);
    371                         }
    372                 } else {
    373                         /* It's in the border. */
    374                         if (event->type == POS_PRESS) {
    375                                 /* Top or bottom half? */
    376                                 if (pos.y >= (irect.p0.y + irect.p1.y) / 2)
    377                                         panel_page_down(panel);
    378                                 else
    379                                         panel_page_up(panel);
    380                         }
    381                 }
    382         }
    383 
    384         return ui_claimed;
    385 }
    386 
    387 /** Get base control for panel.
    388  *
    389  * @param panel Panel
    390  * @return Base UI control
    391  */
    392 ui_control_t *panel_ctl(panel_t *panel)
    393 {
    394         return panel->control;
    395 }
    396 
    397 /** Set panel rectangle.
    398  *
    399  * @param panel Panel
    400  * @param rect Rectangle
    401  */
    402 void panel_set_rect(panel_t *panel, gfx_rect_t *rect)
    403 {
    404         panel->rect = *rect;
    405 }
    406 
    407 /** Get panel page size.
    408  *
    409  * @param panel Panel
    410  * @return Number of entries that fit in panel at the same time.
    411  */
    412 unsigned panel_page_size(panel_t *panel)
    413 {
    414         return panel->rect.p1.y - panel->rect.p0.y - 2;
     257        ui_file_list_set_rect(panel->flist, &irect);
    415258}
    416259
     
    435278        errno_t rc;
    436279
    437         if (panel->dir != NULL) {
    438                 rc = vfs_cwd_set(panel->dir);
    439                 if (rc != EOK)
    440                         return rc;
    441         }
     280        rc = ui_file_list_activate(panel->flist);
     281        if (rc != EOK)
     282                return rc;
    442283
    443284        panel->active = true;
     
    452293void panel_deactivate(panel_t *panel)
    453294{
     295        ui_file_list_deactivate(panel->flist);
    454296        panel->active = false;
    455297        (void) panel_paint(panel);
    456 }
    457 
    458 /** Initialize panel entry attributes.
    459  *
    460  * @param attr Attributes
    461  */
    462 void panel_entry_attr_init(panel_entry_attr_t *attr)
    463 {
    464         memset(attr, 0, sizeof(*attr));
    465298}
    466299
     
    514347}
    515348
    516 /** Append new panel entry.
    517  *
    518  * @param panel Panel
    519  * @param attr Entry attributes
    520  * @return EOK on success or an error code
    521  */
    522 errno_t panel_entry_append(panel_t *panel, panel_entry_attr_t *attr)
    523 {
    524         panel_entry_t *entry;
    525 
    526         entry = calloc(1, sizeof(panel_entry_t));
    527         if (entry == NULL)
    528                 return ENOMEM;
    529 
    530         entry->panel = panel;
    531         entry->name = str_dup(attr->name);
    532         if (entry->name == NULL) {
    533                 free(entry);
    534                 return ENOMEM;
    535         }
    536 
    537         entry->size = attr->size;
    538         entry->isdir = attr->isdir;
    539         entry->svc = attr->svc;
    540         link_initialize(&entry->lentries);
    541         list_append(&entry->lentries, &panel->entries);
    542         ++panel->entries_cnt;
    543         return EOK;
    544 }
    545 
    546 /** Delete panel entry.
    547  *
    548  * @param entry Panel entry
    549  */
    550 void panel_entry_delete(panel_entry_t *entry)
    551 {
    552         if (entry->panel->cursor == entry)
    553                 entry->panel->cursor = NULL;
    554         if (entry->panel->page == entry)
    555                 entry->panel->page = NULL;
    556 
    557         list_remove(&entry->lentries);
    558         --entry->panel->entries_cnt;
    559         free((char *) entry->name);
    560         free(entry);
    561 }
    562 
    563 /** Clear panel entry list.
    564  *
    565  * @param panel Panel
    566  */
    567 void panel_clear_entries(panel_t *panel)
    568 {
    569         panel_entry_t *entry;
    570 
    571         entry = panel_first(panel);
    572         while (entry != NULL) {
    573                 panel_entry_delete(entry);
    574                 entry = panel_first(panel);
    575         }
    576 }
    577 
    578349/** Read directory into panel entry list.
    579350 *
     
    584355errno_t panel_read_dir(panel_t *panel, const char *dirname)
    585356{
    586         DIR *dir;
    587         struct dirent *dirent;
    588         vfs_stat_t finfo;
    589         char newdir[256];
    590         char *ndir = NULL;
    591         panel_entry_attr_t attr;
    592         panel_entry_t *next;
    593         panel_entry_t *prev;
    594         char *olddn;
    595         size_t pg_size;
    596         size_t max_idx;
    597         size_t i;
    598         errno_t rc;
    599 
    600         rc = vfs_cwd_set(dirname);
    601         if (rc != EOK)
    602                 return rc;
    603 
    604         rc = vfs_cwd_get(newdir, sizeof(newdir));
    605         if (rc != EOK)
    606                 return rc;
    607 
    608         ndir = str_dup(newdir);
    609         if (ndir == NULL)
    610                 return ENOMEM;
    611 
    612         dir = opendir(".");
    613         if (dir == NULL) {
    614                 rc = errno;
    615                 goto error;
    616         }
    617 
    618         if (str_cmp(ndir, "/") != 0) {
    619                 /* Need to add a synthetic up-dir entry */
    620                 panel_entry_attr_init(&attr);
    621                 attr.name = "..";
    622                 attr.isdir = true;
    623 
    624                 rc = panel_entry_append(panel, &attr);
    625                 if (rc != EOK)
    626                         goto error;
    627         }
    628 
    629         dirent = readdir(dir);
    630         while (dirent != NULL) {
    631                 rc = vfs_stat_path(dirent->d_name, &finfo);
    632                 if (rc != EOK) {
    633                         /* Possibly a stale entry */
    634                         dirent = readdir(dir);
    635                         continue;
    636                 }
    637 
    638                 panel_entry_attr_init(&attr);
    639                 attr.name = dirent->d_name;
    640                 attr.size = finfo.size;
    641                 attr.isdir = finfo.is_directory;
    642                 attr.svc = finfo.service;
    643 
    644                 rc = panel_entry_append(panel, &attr);
    645                 if (rc != EOK)
    646                         goto error;
    647 
    648                 dirent = readdir(dir);
    649         }
    650 
    651         closedir(dir);
    652 
    653         rc = panel_sort(panel);
    654         if (rc != EOK)
    655                 goto error;
    656 
    657         panel->cursor = panel_first(panel);
    658         panel->cursor_idx = 0;
    659         panel->page = panel_first(panel);
    660         panel->page_idx = 0;
    661 
    662         /* Moving up? */
    663         if (str_cmp(dirname, "..") == 0) {
    664                 /* Get the last component of old path */
    665                 olddn = str_rchr(panel->dir, '/');
    666                 if (olddn != NULL && *olddn != '\0') {
    667                         /* Find corresponding entry */
    668                         ++olddn;
    669                         next = panel_next(panel->cursor);
    670                         while (next != NULL && str_cmp(next->name, olddn) <= 0 &&
    671                             next->isdir) {
    672                                 panel->cursor = next;
    673                                 ++panel->cursor_idx;
    674                                 next = panel_next(panel->cursor);
    675                         }
    676 
    677                         /* Move page so that cursor is in the center */
    678                         panel->page = panel->cursor;
    679                         panel->page_idx = panel->cursor_idx;
    680 
    681                         pg_size = panel_page_size(panel);
    682 
    683                         for (i = 0; i < pg_size / 2; i++) {
    684                                 prev = panel_prev(panel->page);
    685                                 if (prev == NULL)
    686                                         break;
    687 
    688                                 panel->page = prev;
    689                                 --panel->page_idx;
    690                         }
    691 
    692                         /* Make sure page is not beyond the end if possible */
    693                         if (panel->entries_cnt > pg_size)
    694                                 max_idx = panel->entries_cnt - pg_size;
    695                         else
    696                                 max_idx = 0;
    697 
    698                         while (panel->page_idx > 0 && panel->page_idx > max_idx) {
    699                                 prev = panel_prev(panel->page);
    700                                 if (prev == NULL)
    701                                         break;
    702 
    703                                 panel->page = prev;
    704                                 --panel->page_idx;
    705                         }
    706                 }
    707         }
    708 
    709         free(panel->dir);
    710         panel->dir = ndir;
    711 
    712         return EOK;
    713 error:
    714         (void) vfs_cwd_set(panel->dir);
    715         if (ndir != NULL)
    716                 free(ndir);
    717         if (dir != NULL)
    718                 closedir(dir);
    719         return rc;
    720 }
    721 
    722 /** Sort panel entries.
    723  *
    724  * @param panel Panel
    725  * @return EOK on success, ENOMEM if out of memory
    726  */
    727 errno_t panel_sort(panel_t *panel)
    728 {
    729         panel_entry_t **emap;
    730         panel_entry_t *entry;
    731         size_t i;
    732 
    733         /* Create an array to hold pointer to each entry */
    734         emap = calloc(panel->entries_cnt, sizeof(panel_entry_t *));
    735         if (emap == NULL)
    736                 return ENOMEM;
    737 
    738         /* Write entry pointers to array */
    739         entry = panel_first(panel);
    740         i = 0;
    741         while (entry != NULL) {
    742                 assert(i < panel->entries_cnt);
    743                 emap[i++] = entry;
    744                 entry = panel_next(entry);
    745         }
    746 
    747         /* Sort the array of pointers */
    748         qsort(emap, panel->entries_cnt, sizeof(panel_entry_t *),
    749             panel_entry_ptr_cmp);
    750 
    751         /* Unlink entries from entry list */
    752         entry = panel_first(panel);
    753         while (entry != NULL) {
    754                 list_remove(&entry->lentries);
    755                 entry = panel_first(panel);
    756         }
    757 
    758         /* Add entries back to entry list sorted */
    759         for (i = 0; i < panel->entries_cnt; i++)
    760                 list_append(&emap[i]->lentries, &panel->entries);
    761 
    762         free(emap);
    763         return EOK;
    764 }
    765 
    766 /** Compare two panel entries indirectly referenced by pointers.
    767  *
    768  * @param pa Pointer to pointer to first entry
    769  * @param pb Pointer to pointer to second entry
    770  * @return <0, =0, >=0 if pa < b, pa == pb, pa > pb, resp.
    771  */
    772 int panel_entry_ptr_cmp(const void *pa, const void *pb)
    773 {
    774         panel_entry_t *a = *(panel_entry_t **)pa;
    775         panel_entry_t *b = *(panel_entry_t **)pb;
    776         int dcmp;
    777 
    778         /* Sort directories first */
    779         dcmp = b->isdir - a->isdir;
    780         if (dcmp != 0)
    781                 return dcmp;
    782 
    783         return str_cmp(a->name, b->name);
    784 }
    785 
    786 /** Return first panel entry.
    787  *
    788  * @panel Panel
    789  * @return First panel entry or @c NULL if there are no entries
    790  */
    791 panel_entry_t *panel_first(panel_t *panel)
    792 {
    793         link_t *link;
    794 
    795         link = list_first(&panel->entries);
    796         if (link == NULL)
    797                 return NULL;
    798 
    799         return list_get_instance(link, panel_entry_t, lentries);
    800 }
    801 
    802 /** Return last panel entry.
    803  *
    804  * @panel Panel
    805  * @return Last panel entry or @c NULL if there are no entries
    806  */
    807 panel_entry_t *panel_last(panel_t *panel)
    808 {
    809         link_t *link;
    810 
    811         link = list_last(&panel->entries);
    812         if (link == NULL)
    813                 return NULL;
    814 
    815         return list_get_instance(link, panel_entry_t, lentries);
    816 }
    817 
    818 /** Return next panel entry.
    819  *
    820  * @param cur Current entry
    821  * @return Next entry or @c NULL if @a cur is the last entry
    822  */
    823 panel_entry_t *panel_next(panel_entry_t *cur)
    824 {
    825         link_t *link;
    826 
    827         link = list_next(&cur->lentries, &cur->panel->entries);
    828         if (link == NULL)
    829                 return NULL;
    830 
    831         return list_get_instance(link, panel_entry_t, lentries);
    832 }
    833 
    834 /** Return previous panel entry.
    835  *
    836  * @param cur Current entry
    837  * @return Previous entry or @c NULL if @a cur is the first entry
    838  */
    839 panel_entry_t *panel_prev(panel_entry_t *cur)
    840 {
    841         link_t *link;
    842 
    843         link = list_prev(&cur->lentries, &cur->panel->entries);
    844         if (link == NULL)
    845                 return NULL;
    846 
    847         return list_get_instance(link, panel_entry_t, lentries);
    848 }
    849 
    850 /** Find the n-th entry of the current panel page.
    851  *
    852  * If the page is short and has less than n+1 entries, return the last entry.
    853  *
    854  * @param panel Panel
    855  * @param n Which entry to get (starting from 0)
    856  * @param ridx Place to store index (within listing) of the entry
    857  * @return n-th entry of the page
    858  */
    859 panel_entry_t *panel_page_nth_entry(panel_t *panel, size_t n, size_t *ridx)
    860 {
    861         panel_entry_t *entry;
    862         panel_entry_t *next;
    863         size_t i;
    864         size_t idx;
    865 
    866         assert(n < panel_page_size(panel));
    867 
    868         entry = panel->page;
    869         idx = panel->page_idx;
    870         for (i = 0; i < n; i++) {
    871                 next = panel_next(entry);
    872                 if (next == NULL)
    873                         break;
    874 
    875                 entry = next;
    876                 ++idx;
    877         }
    878 
    879         *ridx = idx;
    880         return entry;
    881 }
    882 
    883 /** Move cursor to a new position, possibly scrolling.
    884  *
    885  * @param panel Panel
    886  * @param entry New entry under cursor
    887  * @param entry_idx Index of new entry under cursor
    888  */
    889 void panel_cursor_move(panel_t *panel, panel_entry_t *entry, size_t entry_idx)
    890 {
    891         gfx_context_t *gc = ui_window_get_gc(panel->window);
    892         panel_entry_t *old_cursor;
    893         size_t old_idx;
    894         size_t rows;
    895         panel_entry_t *e;
    896         size_t i;
    897 
    898         rows = panel_page_size(panel);
    899 
    900         old_cursor = panel->cursor;
    901         old_idx = panel->cursor_idx;
    902 
    903         panel->cursor = entry;
    904         panel->cursor_idx = entry_idx;
    905 
    906         if (entry_idx >= panel->page_idx &&
    907             entry_idx < panel->page_idx + rows) {
    908                 /*
    909                  * If cursor is still on the current page, we're not
    910                  * scrolling. Just unpaint old cursor and paint new
    911                  * cursor.
    912                  */
    913                 panel_entry_paint(old_cursor, old_idx);
    914                 panel_entry_paint(panel->cursor, panel->cursor_idx);
    915 
    916                 (void) gfx_update(gc);
    917         } else {
    918                 /*
    919                  * Need to scroll and update all rows.
    920                  */
    921 
    922                 /* Scrolling up */
    923                 if (entry_idx < panel->page_idx) {
    924                         panel->page = entry;
    925                         panel->page_idx = entry_idx;
    926                 }
    927 
    928                 /* Scrolling down */
    929                 if (entry_idx >= panel->page_idx + rows) {
    930                         if (entry_idx >= rows) {
    931                                 panel->page_idx = entry_idx - rows + 1;
    932                                 /* Find first page entry (go back rows - 1) */
    933                                 e = entry;
    934                                 for (i = 0; i < rows - 1; i++) {
    935                                         e = panel_prev(e);
    936                                 }
    937 
    938                                 /* Should be valid */
    939                                 assert(e != NULL);
    940                                 panel->page = e;
    941                         } else {
    942                                 panel->page = panel_first(panel);
    943                                 panel->page_idx = 0;
    944                         }
    945                 }
    946 
    947                 (void) panel_paint(panel);
    948         }
    949 }
    950 
    951 /** Move cursor one entry up.
    952  *
    953  * @param panel Panel
    954  */
    955 void panel_cursor_up(panel_t *panel)
    956 {
    957         panel_entry_t *prev;
    958         size_t prev_idx;
    959 
    960         prev = panel_prev(panel->cursor);
    961         prev_idx = panel->cursor_idx - 1;
    962         if (prev != NULL)
    963                 panel_cursor_move(panel, prev, prev_idx);
    964 }
    965 
    966 /** Move cursor one entry down.
    967  *
    968  * @param panel Panel
    969  */
    970 void panel_cursor_down(panel_t *panel)
    971 {
    972         panel_entry_t *next;
    973         size_t next_idx;
    974 
    975         next = panel_next(panel->cursor);
    976         next_idx = panel->cursor_idx + 1;
    977         if (next != NULL)
    978                 panel_cursor_move(panel, next, next_idx);
    979 }
    980 
    981 /** Move cursor to top.
    982  *
    983  * @param panel Panel
    984  */
    985 void panel_cursor_top(panel_t *panel)
    986 {
    987         panel_cursor_move(panel, panel_first(panel), 0);
    988 }
    989 
    990 /** Move cursor to bottom.
    991  *
    992  * @param panel Panel
    993  */
    994 void panel_cursor_bottom(panel_t *panel)
    995 {
    996         panel_cursor_move(panel, panel_last(panel), panel->entries_cnt - 1);
    997 }
    998 
    999 /** Move one page up.
    1000  *
    1001  * @param panel Panel
    1002  */
    1003 void panel_page_up(panel_t *panel)
    1004 {
    1005         gfx_context_t *gc = ui_window_get_gc(panel->window);
    1006         panel_entry_t *old_page;
    1007         panel_entry_t *old_cursor;
    1008         size_t old_idx;
    1009         size_t rows;
    1010         panel_entry_t *entry;
    1011         size_t i;
    1012 
    1013         rows = panel_page_size(panel);
    1014 
    1015         old_page = panel->page;
    1016         old_cursor = panel->cursor;
    1017         old_idx = panel->cursor_idx;
    1018 
    1019         /* Move page by rows entries up (if possible) */
    1020         for (i = 0; i < rows; i++) {
    1021                 entry = panel_prev(panel->page);
    1022                 if (entry != NULL) {
    1023                         panel->page = entry;
    1024                         --panel->page_idx;
    1025                 }
    1026         }
    1027 
    1028         /* Move cursor by rows entries up (if possible) */
    1029 
    1030         for (i = 0; i < rows; i++) {
    1031                 entry = panel_prev(panel->cursor);
    1032                 if (entry != NULL) {
    1033                         panel->cursor = entry;
    1034                         --panel->cursor_idx;
    1035                 }
    1036         }
    1037 
    1038         if (panel->page != old_page) {
    1039                 /* We have scrolled. Need to repaint all entries */
    1040                 (void) panel_paint(panel);
    1041         } else if (panel->cursor != old_cursor) {
    1042                 /* No scrolling, but cursor has moved */
    1043                 panel_entry_paint(old_cursor, old_idx);
    1044                 panel_entry_paint(panel->cursor, panel->cursor_idx);
    1045 
    1046                 (void) gfx_update(gc);
    1047         }
    1048 }
    1049 
    1050 /** Move one page down.
    1051  *
    1052  * @param panel Panel
    1053  */
    1054 void panel_page_down(panel_t *panel)
    1055 {
    1056         gfx_context_t *gc = ui_window_get_gc(panel->window);
    1057         panel_entry_t *old_page;
    1058         panel_entry_t *old_cursor;
    1059         size_t old_idx;
    1060         size_t max_idx;
    1061         size_t rows;
    1062         panel_entry_t *entry;
    1063         size_t i;
    1064 
    1065         rows = panel_page_size(panel);
    1066 
    1067         old_page = panel->page;
    1068         old_cursor = panel->cursor;
    1069         old_idx = panel->cursor_idx;
    1070 
    1071         if (panel->entries_cnt > rows)
    1072                 max_idx = panel->entries_cnt - rows;
    1073         else
    1074                 max_idx = 0;
    1075 
    1076         /* Move page by rows entries down (if possible) */
    1077         for (i = 0; i < rows; i++) {
    1078                 entry = panel_next(panel->page);
    1079                 /* Do not scroll that results in a short page */
    1080                 if (entry != NULL && panel->page_idx < max_idx) {
    1081                         panel->page = entry;
    1082                         ++panel->page_idx;
    1083                 }
    1084         }
    1085 
    1086         /* Move cursor by rows entries down (if possible) */
    1087 
    1088         for (i = 0; i < rows; i++) {
    1089                 entry = panel_next(panel->cursor);
    1090                 if (entry != NULL) {
    1091                         panel->cursor = entry;
    1092                         ++panel->cursor_idx;
    1093                 }
    1094         }
    1095 
    1096         if (panel->page != old_page) {
    1097                 /* We have scrolled. Need to repaint all entries */
    1098                 (void) panel_paint(panel);
    1099         } else if (panel->cursor != old_cursor) {
    1100                 /* No scrolling, but cursor has moved */
    1101                 panel_entry_paint(old_cursor, old_idx);
    1102                 panel_entry_paint(panel->cursor, panel->cursor_idx);
    1103 
    1104                 (void) gfx_update(gc);
    1105         }
    1106 }
    1107 
    1108 /** Open panel entry.
    1109  *
    1110  * Perform Open action on a panel entry (e.g. switch to a subdirectory).
    1111  *
    1112  * @param panel Panel
    1113  * @param entry Panel entry
     357        return ui_file_list_read_dir(panel->flist, dirname);
     358}
     359
     360/** Request panel activation.
     361 *
     362 * Call back to request panel activation.
     363 *
     364 * @param panel Panel
     365 */
     366void panel_activate_req(panel_t *panel)
     367{
     368        if (panel->cb != NULL && panel->cb->activate_req != NULL)
     369                panel->cb->activate_req(panel->cb_arg, panel);
     370}
     371
     372/** Open panel file entry.
     373 *
     374 * Perform Open action on a file entry (i.e. try running it).
     375 *
     376 * @param panel Panel
     377 * @param fname File name
    1114378 *
    1115379 * @return EOK on success or an error code
    1116380 */
    1117 errno_t panel_open(panel_t *panel, panel_entry_t *entry)
    1118 {
    1119         if (entry->isdir)
    1120                 return panel_open_dir(panel, entry);
    1121         else if (entry->svc == 0)
    1122                 return panel_open_file(panel, entry);
    1123         else
    1124                 return EOK;
    1125 }
    1126 
    1127 /** Open panel directory entry.
    1128  *
    1129  * Perform Open action on a directory entry (i.e. switch to the directory).
    1130  *
    1131  * @param panel Panel
    1132  * @param entry Panel entry (which is a directory)
    1133  *
    1134  * @return EOK on success or an error code
    1135  */
    1136 errno_t panel_open_dir(panel_t *panel, panel_entry_t *entry)
    1137 {
    1138         gfx_context_t *gc = ui_window_get_gc(panel->window);
    1139         char *dirname;
    1140         errno_t rc;
    1141 
    1142         assert(entry->isdir);
    1143 
    1144         /*
    1145          * Need to copy out name before we free the entry below
    1146          * via panel_clear_entries().
    1147          */
    1148         dirname = str_dup(entry->name);
    1149         if (dirname == NULL)
    1150                 return ENOMEM;
    1151 
    1152         panel_clear_entries(panel);
    1153 
    1154         rc = panel_read_dir(panel, dirname);
    1155         if (rc != EOK) {
    1156                 free(dirname);
    1157                 return rc;
    1158         }
    1159 
    1160         free(dirname);
    1161 
    1162         rc = panel_paint(panel);
    1163         if (rc != EOK)
    1164                 return rc;
    1165 
    1166         return gfx_update(gc);
    1167 }
    1168 
    1169 /** Open panel file entry.
    1170  *
    1171  * Perform Open action on a file entry (i.e. try running it).
    1172  *
    1173  * @param panel Panel
    1174  * @param entry Panel entry (which is a file)
    1175  *
    1176  * @return EOK on success or an error code
    1177  */
    1178 errno_t panel_open_file(panel_t *panel, panel_entry_t *entry)
     381static errno_t panel_open_file(panel_t *panel, const char *fname)
    1179382{
    1180383        task_id_t id;
     
    1185388        ui_t *ui;
    1186389
    1187         /* It's not a directory */
    1188         assert(!entry->isdir);
    1189         /* It's not a service-special file */
    1190         assert(entry->svc == 0);
    1191 
    1192390        ui = ui_window_get_ui(panel->window);
    1193391
     
    1197395                return rc;
    1198396
    1199         rc = task_spawnl(&id, &wait, entry->name, entry->name, NULL);
     397        rc = task_spawnl(&id, &wait, fname, fname, NULL);
    1200398        if (rc != EOK)
    1201399                goto error;
     
    1218416}
    1219417
    1220 /** Request panel activation.
    1221  *
    1222  * Call back to request panel activation.
    1223  *
    1224  * @param panel Panel
    1225  */
    1226 void panel_activate_req(panel_t *panel)
    1227 {
    1228         if (panel->cb != NULL && panel->cb->activate_req != NULL)
    1229                 panel->cb->activate_req(panel->cb_arg, panel);
     418/** File in panel file list was selected.
     419 *
     420 * @param flist File list
     421 * @param arg Argument (panel_t *)
     422 * @param fname File name
     423 */
     424static void panel_flist_selected(ui_file_list_t *flist, void *arg,
     425    const char *fname)
     426{
     427        panel_t *panel = (panel_t *)arg;
     428
     429        (void) panel_open_file(panel, fname);
    1230430}
    1231431
Note: See TracChangeset for help on using the changeset viewer.