Changeset 7cf5ddb in mainline for uspace/lib/ui/src/filelist.c


Ignore:
Timestamp:
2023-03-08T18:21:22Z (2 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
42c2e65, 72ac106
Parents:
bea6233
Message:

Generic UI list control

Derived from file list, now file list is based on UI list.
Whew!

File:
1 edited

Legend:

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

    rbea6233 r7cf5ddb  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3030 * @{
    3131 */
    32 /** @file File list.
     32/** @file File list control.
    3333 *
    3434 * Displays a file listing.
     
    3737#include <dirent.h>
    3838#include <errno.h>
    39 #include <gfx/render.h>
    40 #include <gfx/text.h>
    4139#include <stdlib.h>
    4240#include <str.h>
    4341#include <ui/control.h>
    4442#include <ui/filelist.h>
    45 #include <ui/paint.h>
     43#include <ui/list.h>
    4644#include <ui/resource.h>
    47 #include <ui/scrollbar.h>
    4845#include <vfs/vfs.h>
    4946#include <qsort.h>
     
    5653static ui_evclaim_t ui_file_list_ctl_pos_event(void *, pos_event_t *);
    5754
    58 /** File list control ops */
     55/** List control ops */
    5956ui_control_ops_t ui_file_list_ctl_ops = {
    6057        .destroy = ui_file_list_ctl_destroy,
     
    6461};
    6562
    66 enum {
    67         file_list_entry_hpad = 2,
    68         file_list_entry_vpad = 2,
    69         file_list_entry_hpad_text = 1,
    70         file_list_entry_vpad_text = 0,
    71 };
    72 
    73 static void ui_file_list_scrollbar_up(ui_scrollbar_t *, void *);
    74 static void ui_file_list_scrollbar_down(ui_scrollbar_t *, void *);
    75 static void ui_file_list_scrollbar_page_up(ui_scrollbar_t *, void *);
    76 static void ui_file_list_scrollbar_page_down(ui_scrollbar_t *, void *);
    77 static void ui_file_list_scrollbar_moved(ui_scrollbar_t *, void *, gfx_coord_t);
    78 
    79 /** File list scrollbar callbacks */
    80 static ui_scrollbar_cb_t ui_file_list_scrollbar_cb = {
    81         .up = ui_file_list_scrollbar_up,
    82         .down = ui_file_list_scrollbar_down,
    83         .page_up = ui_file_list_scrollbar_page_up,
    84         .page_down = ui_file_list_scrollbar_page_down,
    85         .moved = ui_file_list_scrollbar_moved
     63static void ui_file_list_list_activate_req(ui_list_t *, void *);
     64static void ui_file_list_list_selected(ui_list_entry_t *, void *);
     65
     66/** List callbacks */
     67ui_list_cb_t ui_file_list_list_cb = {
     68        .activate_req = ui_file_list_list_activate_req,
     69        .selected = ui_file_list_list_selected,
     70        .compare = ui_file_list_list_compare,
    8671};
    8772
     
    10590        rc = ui_control_new(&ui_file_list_ctl_ops, (void *)flist,
    10691            &flist->control);
    107         if (rc != EOK) {
    108                 free(flist);
    109                 return rc;
    110         }
     92        if (rc != EOK)
     93                goto error;
    11194
    11295        rc = gfx_color_new_ega(0x0f, &flist->dir_color);
     
    118101                goto error;
    119102
    120         rc = ui_scrollbar_create(ui_window_get_ui(window), window,
    121             ui_sbd_vert, &flist->scrollbar);
     103        rc = ui_list_create(window, active, &flist->list);
    122104        if (rc != EOK)
    123105                goto error;
    124106
    125         ui_scrollbar_set_cb(flist->scrollbar, &ui_file_list_scrollbar_cb,
    126             (void *) flist);
     107        ui_list_set_cb(flist->list, &ui_file_list_list_cb, (void *)flist);
    127108
    128109        flist->window = window;
    129         list_initialize(&flist->entries);
    130         flist->entries_cnt = 0;
    131         flist->active = active;
    132 
    133110        *rflist = flist;
    134111        return EOK;
    135112error:
     113        ui_control_delete(flist->control);
    136114        if (flist->dir_color != NULL)
    137115                gfx_color_delete(flist->dir_color);
    138116        if (flist->svc_color != NULL)
    139117                gfx_color_delete(flist->svc_color);
     118        free(flist);
     119        return rc;
     120}
     121
     122/** Destroy file list.
     123 *
     124 * @param flist File list
     125 */
     126void ui_file_list_destroy(ui_file_list_t *flist)
     127{
     128        ui_file_list_clear_entries(flist);
     129        ui_list_destroy(flist->list);
    140130        ui_control_delete(flist->control);
    141131        free(flist);
    142         return rc;
    143 }
    144 
    145 /** Destroy file list.
    146  *
    147  * @param flist File list
    148  */
    149 void ui_file_list_destroy(ui_file_list_t *flist)
    150 {
    151         ui_file_list_clear_entries(flist);
    152         ui_control_delete(flist->control);
    153         free(flist);
    154132}
    155133
     
    166144}
    167145
    168 /** Get height of file list entry.
    169  *
    170  * @param flist File list
    171  * @return Entry height in pixels
    172  */
    173 gfx_coord_t ui_file_list_entry_height(ui_file_list_t *flist)
    174 {
    175         ui_resource_t *res;
    176         gfx_font_metrics_t metrics;
    177         gfx_coord_t height;
    178         gfx_coord_t vpad;
    179 
    180         res = ui_window_get_res(flist->window);
    181 
    182         if (res->textmode) {
    183                 vpad = file_list_entry_vpad_text;
    184         } else {
    185                 vpad = file_list_entry_vpad;
    186         }
    187 
    188         /* Normal menu entry */
    189         gfx_font_get_metrics(res->font, &metrics);
    190         height = metrics.ascent + metrics.descent + 1;
    191 
    192         return height + 2 * vpad;
    193 }
    194 
    195 /** Paint file list entry.
    196  *
    197  * @param entry File list entry
    198  * @param entry_idx Entry index (within list of entries)
    199  * @return EOK on success or an error code
    200  */
    201 errno_t ui_file_list_entry_paint(ui_file_list_entry_t *entry, size_t entry_idx)
    202 {
    203         ui_file_list_t *flist = entry->flist;
    204         gfx_context_t *gc = ui_window_get_gc(flist->window);
    205         ui_resource_t *res = ui_window_get_res(flist->window);
    206         gfx_font_t *font = ui_resource_get_font(res);
    207         gfx_text_fmt_t fmt;
    208         gfx_coord2_t pos;
    209         gfx_rect_t rect;
    210         gfx_rect_t lrect;
    211         gfx_rect_t crect;
    212         gfx_color_t *bgcolor;
    213         char *caption;
    214         gfx_coord_t hpad, vpad;
    215         gfx_coord_t line_height;
    216         size_t rows;
    217         errno_t rc;
    218         int rv;
    219 
    220         line_height = ui_file_list_entry_height(flist);
    221         ui_file_list_inside_rect(entry->flist, &lrect);
    222 
    223         gfx_text_fmt_init(&fmt);
    224         fmt.font = font;
    225         rows = ui_file_list_page_size(flist) + 1;
    226 
    227         /* Do not display entry outside of current page */
    228         if (entry_idx < flist->page_idx ||
    229             entry_idx >= flist->page_idx + rows)
    230                 return EOK;
    231 
    232         if (res->textmode) {
    233                 hpad = file_list_entry_hpad_text;
    234                 vpad = file_list_entry_vpad_text;
    235         } else {
    236                 hpad = file_list_entry_hpad;
    237                 vpad = file_list_entry_vpad;
    238         }
    239 
    240         pos.x = lrect.p0.x;
    241         pos.y = lrect.p0.y + line_height * (entry_idx - flist->page_idx);
    242 
    243         if (entry == flist->cursor && flist->active) {
    244                 fmt.color = res->entry_sel_text_fg_color;
    245                 bgcolor = res->entry_sel_text_bg_color;
    246         } else if (entry->isdir) {
    247                 if (res->textmode) {
    248                         fmt.color = flist->dir_color;
    249                         bgcolor = flist->dir_color;
    250                 } else {
    251                         fmt.color = res->entry_fg_color;
    252                         bgcolor = res->entry_bg_color;
    253                 }
    254         } else if (entry->svc != 0) {
    255                 if (res->textmode) {
    256                         fmt.color = flist->svc_color;
    257                         bgcolor = flist->svc_color;
    258                 } else {
    259                         fmt.color = res->entry_fg_color;
    260                         bgcolor = res->entry_bg_color;
    261                 }
    262         } else {
    263                 fmt.color = res->entry_fg_color;
    264                 bgcolor = res->entry_bg_color;
    265         }
    266 
    267         /* Draw entry background */
    268         rect.p0 = pos;
    269         rect.p1.x = lrect.p1.x;
    270         rect.p1.y = rect.p0.y + line_height;
    271 
    272         /* Clip to file list interior */
    273         gfx_rect_clip(&rect, &lrect, &crect);
    274 
    275         rc = gfx_set_color(gc, bgcolor);
    276         if (rc != EOK)
    277                 return rc;
    278 
    279         rc = gfx_fill_rect(gc, &crect);
    280         if (rc != EOK)
    281                 return rc;
    282 
    283         /*
    284          * Make sure name does not overflow the entry rectangle.
    285          *
    286          * XXX We probably want to measure the text width, and,
    287          * if it's too long, use gfx_text_find_pos() to find where
    288          * it should be cut off (and append some sort of overflow
    289          * marker.
    290          */
    291         rc = gfx_set_clip_rect(gc, &crect);
    292         if (rc != EOK)
    293                 return rc;
    294 
    295         pos.x += hpad;
    296         pos.y += vpad;
    297 
    298         if (res->textmode || !entry->isdir) {
    299                 rc = gfx_puttext(&pos, &fmt, entry->name);
    300                 if (rc != EOK) {
    301                         (void) gfx_set_clip_rect(gc, NULL);
    302                         return rc;
    303                 }
    304         } else {
    305                 /*
    306                  * XXX This is mostly a hack to distinguish directories
    307                  * util a better solution is available. (E.g. a Size
    308                  * column where we can put <dir>, an icon.)
    309                  */
    310                 rv = asprintf(&caption, "[%s]", entry->name);
    311                 if (rv < 0) {
    312                         (void) gfx_set_clip_rect(gc, NULL);
    313                         return rc;
    314                 }
    315 
    316                 rc = gfx_puttext(&pos, &fmt, caption);
    317                 if (rc != EOK) {
    318                         free(caption);
    319                         (void) gfx_set_clip_rect(gc, NULL);
    320                         return rc;
    321                 }
    322 
    323                 free(caption);
    324         }
    325 
    326         return gfx_set_clip_rect(gc, NULL);
    327 }
    328 
    329 /** Paint file list.
    330  *
    331  * @param flist File list
    332  */
    333 errno_t ui_file_list_paint(ui_file_list_t *flist)
    334 {
    335         gfx_context_t *gc = ui_window_get_gc(flist->window);
    336         ui_resource_t *res = ui_window_get_res(flist->window);
    337         ui_file_list_entry_t *entry;
    338         int i, lines;
    339         errno_t rc;
    340 
    341         rc = gfx_set_color(gc, res->entry_bg_color);
    342         if (rc != EOK)
    343                 return rc;
    344 
    345         rc = gfx_fill_rect(gc, &flist->rect);
    346         if (rc != EOK)
    347                 return rc;
    348 
    349         if (!res->textmode) {
    350                 rc = ui_paint_inset_frame(res, &flist->rect, NULL);
    351                 if (rc != EOK)
    352                         return rc;
    353         }
    354 
    355         lines = ui_file_list_page_size(flist) + 1;
    356         i = 0;
    357 
    358         entry = flist->page;
    359         while (entry != NULL && i < lines) {
    360                 rc = ui_file_list_entry_paint(entry, flist->page_idx + i);
    361                 if (rc != EOK)
    362                         return rc;
    363 
    364                 ++i;
    365                 entry = ui_file_list_next(entry);
    366         }
    367 
    368         rc = ui_scrollbar_paint(flist->scrollbar);
    369         if (rc != EOK)
    370                 return rc;
    371 
    372         rc = gfx_update(gc);
    373         if (rc != EOK)
    374                 return rc;
    375 
    376         return EOK;
    377 }
    378 
    379 /** Handle file list keyboard event.
    380  *
    381  * @param flist File list
    382  * @param event Keyboard event
    383  * @return ui_claimed iff event was claimed
    384  */
    385 ui_evclaim_t ui_file_list_kbd_event(ui_file_list_t *flist, kbd_event_t *event)
    386 {
    387         if (!flist->active)
    388                 return ui_unclaimed;
    389 
    390         if (event->type == KEY_PRESS) {
    391                 if ((event->mods & (KM_CTRL | KM_ALT | KM_SHIFT)) == 0) {
    392                         switch (event->key) {
    393                         case KC_UP:
    394                                 ui_file_list_cursor_up(flist);
    395                                 break;
    396                         case KC_DOWN:
    397                                 ui_file_list_cursor_down(flist);
    398                                 break;
    399                         case KC_HOME:
    400                                 ui_file_list_cursor_top(flist);
    401                                 break;
    402                         case KC_END:
    403                                 ui_file_list_cursor_bottom(flist);
    404                                 break;
    405                         case KC_PAGE_UP:
    406                                 ui_file_list_page_up(flist);
    407                                 break;
    408                         case KC_PAGE_DOWN:
    409                                 ui_file_list_page_down(flist);
    410                                 break;
    411                         case KC_ENTER:
    412                                 ui_file_list_open(flist, flist->cursor);
    413                                 break;
    414                         default:
    415                                 break;
    416                         }
    417                 }
    418         }
    419 
    420         return ui_claimed;
    421 }
    422 
    423 /** Handle file list position event.
    424  *
    425  * @param flist File list
    426  * @param event Position event
    427  * @return ui_claimed iff event was claimed
    428  */
    429 ui_evclaim_t ui_file_list_pos_event(ui_file_list_t *flist, pos_event_t *event)
    430 {
    431         gfx_coord2_t pos;
    432         gfx_rect_t irect;
    433         ui_file_list_entry_t *entry;
    434         gfx_coord_t line_height;
    435         size_t entry_idx;
    436         ui_evclaim_t claim;
    437         int n;
    438 
    439         claim = ui_scrollbar_pos_event(flist->scrollbar, event);
    440         if (claim == ui_claimed)
    441                 return ui_claimed;
    442 
    443         line_height = ui_file_list_entry_height(flist);
    444 
    445         pos.x = event->hpos;
    446         pos.y = event->vpos;
    447         if (!gfx_pix_inside_rect(&pos, &flist->rect))
    448                 return ui_unclaimed;
    449 
    450         if (!flist->active && event->type == POS_PRESS)
    451                 ui_file_list_activate_req(flist);
    452 
    453         if (event->type == POS_PRESS || event->type == POS_DCLICK) {
    454                 ui_file_list_inside_rect(flist, &irect);
    455 
    456                 /* Did we click on one of the entries? */
    457                 if (gfx_pix_inside_rect(&pos, &irect)) {
    458                         /* Index within page */
    459                         n = (pos.y - irect.p0.y) / line_height;
    460 
    461                         /* Entry and its index within entire listing */
    462                         entry = ui_file_list_page_nth_entry(flist, n, &entry_idx);
    463                         if (entry == NULL)
    464                                 return ui_claimed;
    465 
    466                         if (event->type == POS_PRESS) {
    467                                 /* Move to the entry found */
    468                                 ui_file_list_cursor_move(flist, entry, entry_idx);
    469                         } else {
    470                                 /* event->type == POS_DCLICK */
    471                                 ui_file_list_open(flist, entry);
    472                         }
    473                 } else {
    474                         /* It's in the border. */
    475                         if (event->type == POS_PRESS) {
    476                                 /* Top or bottom half? */
    477                                 if (pos.y >= (irect.p0.y + irect.p1.y) / 2)
    478                                         ui_file_list_page_down(flist);
    479                                 else
    480                                         ui_file_list_page_up(flist);
    481                         }
    482                 }
    483         }
    484 
    485         return ui_claimed;
    486 }
    487 
    488146/** Get base control for file list.
    489147 *
     
    503161void ui_file_list_set_rect(ui_file_list_t *flist, gfx_rect_t *rect)
    504162{
    505         gfx_rect_t srect;
    506 
    507         flist->rect = *rect;
    508 
    509         ui_file_list_scrollbar_rect(flist, &srect);
    510         ui_scrollbar_set_rect(flist->scrollbar, &srect);
    511 }
    512 
    513 /** Get file list page size.
    514  *
    515  * @param flist File list
    516  * @return Number of entries that fit in flist at the same time.
    517  */
    518 unsigned ui_file_list_page_size(ui_file_list_t *flist)
    519 {
    520         gfx_coord_t line_height;
    521         gfx_rect_t irect;
    522 
    523         line_height = ui_file_list_entry_height(flist);
    524         ui_file_list_inside_rect(flist, &irect);
    525         return (irect.p1.y - irect.p0.y) / line_height;
    526 }
    527 
    528 /** Get file list interior rectangle.
    529  *
    530  * @param flist File list
    531  * @param irect Place to store interior rectangle
    532  */
    533 void ui_file_list_inside_rect(ui_file_list_t *flist, gfx_rect_t *irect)
    534 {
    535         ui_resource_t *res = ui_window_get_res(flist->window);
    536         gfx_rect_t rect;
    537         gfx_coord_t width;
    538 
    539         if (res->textmode) {
    540                 rect = flist->rect;
    541         } else {
    542                 ui_paint_get_inset_frame_inside(res, &flist->rect, &rect);
    543         }
    544 
    545         if (res->textmode) {
    546                 width = 1;
    547         } else {
    548                 width = 23;
    549         }
    550 
    551         irect->p0 = rect.p0;
    552         irect->p1.x = rect.p1.x - width;
    553         irect->p1.y = rect.p1.y;
    554 }
    555 
    556 /** Get file list scrollbar rectangle.
    557  *
    558  * @param flist File list
    559  * @param irect Place to store interior rectangle
    560  */
    561 void ui_file_list_scrollbar_rect(ui_file_list_t *flist, gfx_rect_t *srect)
    562 {
    563         ui_resource_t *res = ui_window_get_res(flist->window);
    564         gfx_rect_t rect;
    565         gfx_coord_t width;
    566 
    567         if (res->textmode) {
    568                 rect = flist->rect;
    569         } else {
    570                 ui_paint_get_inset_frame_inside(res, &flist->rect, &rect);
    571         }
    572 
    573         if (res->textmode) {
    574                 width = 1;
    575         } else {
    576                 width = 23;
    577         }
    578 
    579         srect->p0.x = rect.p1.x - width;
    580         srect->p0.y = rect.p0.y;
    581         srect->p1 = rect.p1;
    582 }
    583 
    584 /** Compute new position for file list scrollbar thumb.
    585  *
    586  * @param flist File list
    587  * @return New position
    588  */
    589 gfx_coord_t ui_file_list_scrollbar_pos(ui_file_list_t *flist)
    590 {
    591         size_t entries;
    592         size_t pglen;
    593         size_t sbar_len;
    594 
    595         entries = list_count(&flist->entries);
    596         pglen = ui_file_list_page_size(flist);
    597         sbar_len = ui_scrollbar_move_length(flist->scrollbar);
    598 
    599         if (entries > pglen)
    600                 return sbar_len * flist->page_idx / (entries - pglen);
    601         else
    602                 return 0;
    603 }
    604 
    605 /** Update file list scrollbar position.
    606  *
    607  * @param flist File list
    608  */
    609 void ui_file_list_scrollbar_update(ui_file_list_t *flist)
    610 {
    611         ui_scrollbar_set_pos(flist->scrollbar,
    612             ui_file_list_scrollbar_pos(flist));
     163        ui_list_set_rect(flist->list, rect);
    613164}
    614165
     
    620171bool ui_file_list_is_active(ui_file_list_t *flist)
    621172{
    622         return flist->active;
     173        return ui_list_is_active(flist->list);
    623174}
    624175
     
    639190        }
    640191
    641         flist->active = true;
    642         (void) ui_file_list_paint(flist);
    643         return EOK;
     192        return ui_list_activate(flist->list);
    644193}
    645194
     
    650199void ui_file_list_deactivate(ui_file_list_t *flist)
    651200{
    652         flist->active = false;
    653         (void) ui_file_list_paint(flist);
     201        ui_list_deactivate(flist->list);
    654202}
    655203
     
    661209{
    662210        memset(attr, 0, sizeof(*attr));
    663 }
    664 
    665 /** Destroy file list control.
    666  *
    667  * @param arg Argument (ui_file_list_t *)
    668  */
    669 void ui_file_list_ctl_destroy(void *arg)
    670 {
    671         ui_file_list_t *flist = (ui_file_list_t *) arg;
    672 
    673         ui_file_list_destroy(flist);
    674 }
    675 
    676 /** Paint file list control.
    677  *
    678  * @param arg Argument (ui_file_list_t *)
    679  * @return EOK on success or an error code
    680  */
    681 errno_t ui_file_list_ctl_paint(void *arg)
    682 {
    683         ui_file_list_t *flist = (ui_file_list_t *) arg;
    684 
    685         return ui_file_list_paint(flist);
    686 }
    687 
    688 /** Handle file list control keyboard event.
    689  *
    690  * @param arg Argument (ui_file_list_t *)
    691  * @param kbd_event Keyboard event
    692  * @return @c ui_claimed iff the event is claimed
    693  */
    694 ui_evclaim_t ui_file_list_ctl_kbd_event(void *arg, kbd_event_t *event)
    695 {
    696         ui_file_list_t *flist = (ui_file_list_t *) arg;
    697 
    698         return ui_file_list_kbd_event(flist, event);
    699 }
    700 
    701 /** Handle file list control position event.
    702  *
    703  * @param arg Argument (ui_file_list_t *)
    704  * @param pos_event Position event
    705  * @return @c ui_claimed iff the event is claimed
    706  */
    707 ui_evclaim_t ui_file_list_ctl_pos_event(void *arg, pos_event_t *event)
    708 {
    709         ui_file_list_t *flist = (ui_file_list_t *) arg;
    710 
    711         return ui_file_list_pos_event(flist, event);
    712211}
    713212
     
    721220{
    722221        ui_file_list_entry_t *entry;
     222        ui_list_entry_attr_t lattr;
     223        ui_list_entry_t *lentry;
     224        ui_resource_t *res;
     225        char *caption;
     226        errno_t rc;
     227        int rv;
     228
     229        res = ui_window_get_res(flist->window);
    723230
    724231        entry = calloc(1, sizeof(ui_file_list_entry_t));
     
    736243        entry->isdir = attr->isdir;
    737244        entry->svc = attr->svc;
    738         link_initialize(&entry->lentries);
    739         list_append(&entry->lentries, &flist->entries);
    740         ++flist->entries_cnt;
     245
     246        if (attr->isdir && !res->textmode) {
     247                rv = asprintf(&caption, "[%s]", attr->name);
     248                if (rv < 0)
     249                        caption = NULL;
     250        } else {
     251                caption = str_dup(attr->name);
     252        }
     253
     254        if (caption == NULL) {
     255                free(entry->name);
     256                free(entry);
     257                return ENOMEM;
     258        }
     259
     260        lattr.caption = caption;
     261        lattr.arg = (void *)entry;
     262        lattr.color = NULL;
     263        lattr.bgcolor = NULL;
     264
     265        if (res->textmode) {
     266                if (attr->isdir) {
     267                        lattr.color = flist->dir_color;
     268                        lattr.bgcolor = flist->dir_color;
     269                } else if (attr->svc != 0) {
     270                        lattr.color = flist->svc_color;
     271                        lattr.bgcolor = flist->svc_color;
     272                }
     273        }
     274
     275        rc = ui_list_entry_append(flist->list, &lattr, &lentry);
     276        if (rc != EOK) {
     277                free(caption);
     278                free(entry->name);
     279                free(entry);
     280                return rc;
     281        }
     282
     283        free(caption);
     284        entry->entry = lentry;
    741285        return EOK;
    742286}
     
    748292void ui_file_list_entry_delete(ui_file_list_entry_t *entry)
    749293{
    750         if (entry->flist->cursor == entry)
    751                 entry->flist->cursor = NULL;
    752         if (entry->flist->page == entry)
    753                 entry->flist->page = NULL;
    754 
    755         list_remove(&entry->lentries);
    756         --entry->flist->entries_cnt;
    757         free((char *) entry->name);
     294        ui_list_entry_delete(entry->entry);
     295        free(entry->name);
    758296        free(entry);
    759297}
     
    788326        char *ndir = NULL;
    789327        ui_file_list_entry_attr_t attr;
     328        ui_file_list_entry_t *cur;
    790329        ui_file_list_entry_t *next;
    791         ui_file_list_entry_t *prev;
    792330        char *olddn;
    793         size_t pg_size;
    794         size_t max_idx;
    795         size_t i;
    796331        errno_t rc;
    797332
     
    853388                goto error;
    854389
    855         flist->cursor = ui_file_list_first(flist);
    856         flist->cursor_idx = 0;
    857         flist->page = ui_file_list_first(flist);
    858         flist->page_idx = 0;
    859 
    860390        /* Moving up? */
    861391        if (str_cmp(dirname, "..") == 0) {
     
    865395                        /* Find corresponding entry */
    866396                        ++olddn;
    867                         next = ui_file_list_next(flist->cursor);
     397                        cur = ui_file_list_first(flist);
     398                        next = ui_file_list_next(cur);
    868399                        while (next != NULL && str_cmp(next->name, olddn) <= 0 &&
    869400                            next->isdir) {
    870                                 flist->cursor = next;
    871                                 ++flist->cursor_idx;
    872                                 next = ui_file_list_next(flist->cursor);
     401                                cur = next;
     402                                next = ui_file_list_next(cur);
    873403                        }
    874404
    875                         /* Move page so that cursor is in the center */
    876                         flist->page = flist->cursor;
    877                         flist->page_idx = flist->cursor_idx;
    878 
    879                         pg_size = ui_file_list_page_size(flist);
    880 
    881                         for (i = 0; i < pg_size / 2; i++) {
    882                                 prev = ui_file_list_prev(flist->page);
    883                                 if (prev == NULL)
    884                                         break;
    885 
    886                                 flist->page = prev;
    887                                 --flist->page_idx;
    888                         }
    889 
    890                         /* Make sure page is not beyond the end if possible */
    891                         if (flist->entries_cnt > pg_size)
    892                                 max_idx = flist->entries_cnt - pg_size;
    893                         else
    894                                 max_idx = 0;
    895 
    896                         while (flist->page_idx > 0 && flist->page_idx > max_idx) {
    897                                 prev = ui_file_list_prev(flist->page);
    898                                 if (prev == NULL)
    899                                         break;
    900 
    901                                 flist->page = prev;
    902                                 --flist->page_idx;
    903                         }
     405                        /* Center on the entry */
     406                        ui_list_cursor_center(flist->list, cur->entry);
    904407                }
    905408        }
     
    925428errno_t ui_file_list_sort(ui_file_list_t *flist)
    926429{
    927         ui_file_list_entry_t **emap;
    928         ui_file_list_entry_t *entry;
    929         size_t i;
    930 
    931         /* Create an array to hold pointer to each entry */
    932         emap = calloc(flist->entries_cnt, sizeof(ui_file_list_entry_t *));
    933         if (emap == NULL)
    934                 return ENOMEM;
    935 
    936         /* Write entry pointers to array */
    937         entry = ui_file_list_first(flist);
    938         i = 0;
    939         while (entry != NULL) {
    940                 assert(i < flist->entries_cnt);
    941                 emap[i++] = entry;
    942                 entry = ui_file_list_next(entry);
    943         }
    944 
    945         /* Sort the array of pointers */
    946         qsort(emap, flist->entries_cnt, sizeof(ui_file_list_entry_t *),
    947             ui_file_list_entry_ptr_cmp);
    948 
    949         /* Unlink entries from entry list */
    950         entry = ui_file_list_first(flist);
    951         while (entry != NULL) {
    952                 list_remove(&entry->lentries);
    953                 entry = ui_file_list_first(flist);
    954         }
    955 
    956         /* Add entries back to entry list sorted */
    957         for (i = 0; i < flist->entries_cnt; i++)
    958                 list_append(&emap[i]->lentries, &flist->entries);
    959 
    960         free(emap);
    961         return EOK;
    962 }
    963 
    964 /** Compare two file list entries indirectly referenced by pointers.
    965  *
    966  * @param pa Pointer to pointer to first entry
    967  * @param pb Pointer to pointer to second entry
    968  * @return <0, =0, >=0 if pa < b, pa == pb, pa > pb, resp.
    969  */
    970 int ui_file_list_entry_ptr_cmp(const void *pa, const void *pb)
    971 {
    972         ui_file_list_entry_t *a = *(ui_file_list_entry_t **)pa;
    973         ui_file_list_entry_t *b = *(ui_file_list_entry_t **)pb;
     430        return ui_list_sort(flist->list);
     431}
     432
     433/** Compare two list entries within file list entries.
     434 *
     435 * @param ea First UI list entry
     436 * @param eb Second UI list entry
     437 * @return <0, =0, >=0 if a < b, a == b, a > b, resp.
     438 */
     439int ui_file_list_list_compare(ui_list_entry_t *ea, ui_list_entry_t *eb)
     440{
     441        ui_file_list_entry_t *a;
     442        ui_file_list_entry_t *b;
    974443        int dcmp;
     444
     445        a = (ui_file_list_entry_t *)ui_list_entry_get_arg(ea);
     446        b = (ui_file_list_entry_t *)ui_list_entry_get_arg(eb);
    975447
    976448        /* Sort directories first */
     
    989461ui_file_list_entry_t *ui_file_list_first(ui_file_list_t *flist)
    990462{
    991         link_t *link;
    992 
    993         link = list_first(&flist->entries);
    994         if (link == NULL)
     463        ui_list_entry_t *lentry;
     464
     465        lentry = ui_list_first(flist->list);
     466        if (lentry == NULL)
    995467                return NULL;
    996468
    997         return list_get_instance(link, ui_file_list_entry_t, lentries);
     469        return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
    998470}
    999471
     
    1005477ui_file_list_entry_t *ui_file_list_last(ui_file_list_t *flist)
    1006478{
    1007         link_t *link;
    1008 
    1009         link = list_last(&flist->entries);
    1010         if (link == NULL)
     479        ui_list_entry_t *lentry;
     480
     481        lentry = ui_list_last(flist->list);
     482        if (lentry == NULL)
    1011483                return NULL;
    1012484
    1013         return list_get_instance(link, ui_file_list_entry_t, lentries);
     485        return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
    1014486}
    1015487
     
    1021493ui_file_list_entry_t *ui_file_list_next(ui_file_list_entry_t *cur)
    1022494{
    1023         link_t *link;
    1024 
    1025         link = list_next(&cur->lentries, &cur->flist->entries);
    1026         if (link == NULL)
     495        ui_list_entry_t *lentry;
     496
     497        lentry = ui_list_next(cur->entry);
     498        if (lentry == NULL)
    1027499                return NULL;
    1028500
    1029         return list_get_instance(link, ui_file_list_entry_t, lentries);
     501        return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
    1030502}
    1031503
     
    1037509ui_file_list_entry_t *ui_file_list_prev(ui_file_list_entry_t *cur)
    1038510{
    1039         link_t *link;
    1040 
    1041         link = list_prev(&cur->lentries, &cur->flist->entries);
    1042         if (link == NULL)
     511        ui_list_entry_t *lentry;
     512
     513        lentry = ui_list_prev(cur->entry);
     514        if (lentry == NULL)
    1043515                return NULL;
    1044516
    1045         return list_get_instance(link, ui_file_list_entry_t, lentries);
    1046 }
    1047 
    1048 /** Find the n-th entry of the current file list page.
    1049  *
    1050  * @param flist File list
    1051  * @param n Which entry to get (starting from 0)
    1052  * @param ridx Place to store index (within listing) of the entry
    1053  * @return n-th entry of the page
    1054  */
    1055 ui_file_list_entry_t *ui_file_list_page_nth_entry(ui_file_list_t *flist,
    1056     size_t n, size_t *ridx)
    1057 {
    1058         ui_file_list_entry_t *entry;
    1059         size_t i;
    1060         size_t idx;
    1061 
    1062         assert(n <= ui_file_list_page_size(flist));
    1063 
    1064         entry = flist->page;
     517        return (ui_file_list_entry_t *)ui_list_entry_get_arg(lentry);
     518}
     519
     520/** Get entry under cursor.
     521 *
     522 * @param flist File list
     523 * @return Current cursor
     524 */
     525ui_file_list_entry_t *ui_file_list_get_cursor(ui_file_list_t *flist)
     526{
     527        ui_list_entry_t *entry;
     528
     529        entry = ui_list_get_cursor(flist->list);
    1065530        if (entry == NULL)
    1066531                return NULL;
    1067532
    1068         idx = flist->page_idx;
    1069         for (i = 0; i < n; i++) {
    1070                 entry = ui_file_list_next(entry);
    1071                 if (entry == NULL)
    1072                         return NULL;
    1073 
    1074                 ++idx;
    1075         }
    1076 
    1077         *ridx = idx;
    1078         return entry;
    1079 }
    1080 
    1081 /** Get entry under cursor.
    1082  *
    1083  * @param flist File list
    1084  * @return Current cursor
    1085  */
    1086 ui_file_list_entry_t *ui_file_list_get_cursor(ui_file_list_t *flist)
    1087 {
    1088         return flist->cursor;
    1089 }
    1090 
    1091 /** Move cursor to a new position, possibly scrolling.
    1092  *
    1093  * @param flist File list
    1094  * @param entry New entry under cursor
    1095  * @param entry_idx Index of new entry under cursor
    1096  */
    1097 void ui_file_list_cursor_move(ui_file_list_t *flist,
    1098     ui_file_list_entry_t *entry, size_t entry_idx)
    1099 {
    1100         gfx_context_t *gc = ui_window_get_gc(flist->window);
    1101         ui_file_list_entry_t *old_cursor;
    1102         size_t old_idx;
    1103         size_t rows;
    1104         ui_file_list_entry_t *e;
    1105         size_t i;
    1106 
    1107         rows = ui_file_list_page_size(flist);
    1108 
    1109         old_cursor = flist->cursor;
    1110         old_idx = flist->cursor_idx;
    1111 
    1112         flist->cursor = entry;
    1113         flist->cursor_idx = entry_idx;
    1114 
    1115         if (entry_idx >= flist->page_idx &&
    1116             entry_idx < flist->page_idx + rows) {
    1117                 /*
    1118                  * If cursor is still on the current page, we're not
    1119                  * scrolling. Just unpaint old cursor and paint new
    1120                  * cursor.
    1121                  */
    1122                 ui_file_list_entry_paint(old_cursor, old_idx);
    1123                 ui_file_list_entry_paint(flist->cursor, flist->cursor_idx);
    1124 
    1125                 (void) gfx_update(gc);
    1126         } else {
    1127                 /*
    1128                  * Need to scroll and update all rows.
    1129                  */
    1130 
    1131                 /* Scrolling up */
    1132                 if (entry_idx < flist->page_idx) {
    1133                         flist->page = entry;
    1134                         flist->page_idx = entry_idx;
    1135                 }
    1136 
    1137                 /* Scrolling down */
    1138                 if (entry_idx >= flist->page_idx + rows) {
    1139                         if (entry_idx >= rows) {
    1140                                 flist->page_idx = entry_idx - rows + 1;
    1141                                 /* Find first page entry (go back rows - 1) */
    1142                                 e = entry;
    1143                                 for (i = 0; i < rows - 1; i++) {
    1144                                         e = ui_file_list_prev(e);
    1145                                 }
    1146 
    1147                                 /* Should be valid */
    1148                                 assert(e != NULL);
    1149                                 flist->page = e;
    1150                         } else {
    1151                                 flist->page = ui_file_list_first(flist);
    1152                                 flist->page_idx = 0;
    1153                         }
    1154                 }
    1155 
    1156                 ui_file_list_scrollbar_update(flist);
    1157                 (void) ui_file_list_paint(flist);
    1158         }
    1159 }
    1160 
    1161 /** Move cursor one entry up.
    1162  *
    1163  * @param flist File list
    1164  */
    1165 void ui_file_list_cursor_up(ui_file_list_t *flist)
    1166 {
    1167         ui_file_list_entry_t *prev;
    1168         size_t prev_idx;
    1169 
    1170         prev = ui_file_list_prev(flist->cursor);
    1171         prev_idx = flist->cursor_idx - 1;
    1172         if (prev != NULL)
    1173                 ui_file_list_cursor_move(flist, prev, prev_idx);
    1174 }
    1175 
    1176 /** Move cursor one entry down.
    1177  *
    1178  * @param flist File list
    1179  */
    1180 void ui_file_list_cursor_down(ui_file_list_t *flist)
    1181 {
    1182         ui_file_list_entry_t *next;
    1183         size_t next_idx;
    1184 
    1185         next = ui_file_list_next(flist->cursor);
    1186         next_idx = flist->cursor_idx + 1;
    1187         if (next != NULL)
    1188                 ui_file_list_cursor_move(flist, next, next_idx);
    1189 }
    1190 
    1191 /** Move cursor to top.
    1192  *
    1193  * @param flist File list
    1194  */
    1195 void ui_file_list_cursor_top(ui_file_list_t *flist)
    1196 {
    1197         ui_file_list_cursor_move(flist, ui_file_list_first(flist), 0);
    1198 }
    1199 
    1200 /** Move cursor to bottom.
    1201  *
    1202  * @param flist File list
    1203  */
    1204 void ui_file_list_cursor_bottom(ui_file_list_t *flist)
    1205 {
    1206         ui_file_list_cursor_move(flist, ui_file_list_last(flist),
    1207             flist->entries_cnt - 1);
    1208 }
    1209 
    1210 /** Move cursor one page up.
    1211  *
    1212  * @param flist File list
    1213  */
    1214 void ui_file_list_page_up(ui_file_list_t *flist)
    1215 {
    1216         gfx_context_t *gc = ui_window_get_gc(flist->window);
    1217         ui_file_list_entry_t *old_page;
    1218         ui_file_list_entry_t *old_cursor;
    1219         size_t old_idx;
    1220         size_t rows;
    1221         ui_file_list_entry_t *entry;
    1222         size_t i;
    1223 
    1224         rows = ui_file_list_page_size(flist);
    1225 
    1226         old_page = flist->page;
    1227         old_cursor = flist->cursor;
    1228         old_idx = flist->cursor_idx;
    1229 
    1230         /* Move page by rows entries up (if possible) */
    1231         for (i = 0; i < rows; i++) {
    1232                 entry = ui_file_list_prev(flist->page);
    1233                 if (entry != NULL) {
    1234                         flist->page = entry;
    1235                         --flist->page_idx;
    1236                 }
    1237         }
    1238 
    1239         /* Move cursor by rows entries up (if possible) */
    1240 
    1241         for (i = 0; i < rows; i++) {
    1242                 entry = ui_file_list_prev(flist->cursor);
    1243                 if (entry != NULL) {
    1244                         flist->cursor = entry;
    1245                         --flist->cursor_idx;
    1246                 }
    1247         }
    1248 
    1249         if (flist->page != old_page) {
    1250                 /* We have scrolled. Need to repaint all entries */
    1251                 ui_file_list_scrollbar_update(flist);
    1252                 (void) ui_file_list_paint(flist);
    1253         } else if (flist->cursor != old_cursor) {
    1254                 /* No scrolling, but cursor has moved */
    1255                 ui_file_list_entry_paint(old_cursor, old_idx);
    1256                 ui_file_list_entry_paint(flist->cursor, flist->cursor_idx);
    1257 
    1258                 (void) gfx_update(gc);
    1259         }
    1260 }
    1261 
    1262 /** Move cursor one page down.
    1263  *
    1264  * @param flist File list
    1265  */
    1266 void ui_file_list_page_down(ui_file_list_t *flist)
    1267 {
    1268         gfx_context_t *gc = ui_window_get_gc(flist->window);
    1269         ui_file_list_entry_t *old_page;
    1270         ui_file_list_entry_t *old_cursor;
    1271         size_t old_idx;
    1272         size_t max_idx;
    1273         size_t rows;
    1274         ui_file_list_entry_t *entry;
    1275         size_t i;
    1276 
    1277         rows = ui_file_list_page_size(flist);
    1278 
    1279         old_page = flist->page;
    1280         old_cursor = flist->cursor;
    1281         old_idx = flist->cursor_idx;
    1282 
    1283         if (flist->entries_cnt > rows)
    1284                 max_idx = flist->entries_cnt - rows;
    1285         else
    1286                 max_idx = 0;
    1287 
    1288         /* Move page by rows entries down (if possible) */
    1289         for (i = 0; i < rows; i++) {
    1290                 entry = ui_file_list_next(flist->page);
    1291                 /* Do not scroll that results in a short page */
    1292                 if (entry != NULL && flist->page_idx < max_idx) {
    1293                         flist->page = entry;
    1294                         ++flist->page_idx;
    1295                 }
    1296         }
    1297 
    1298         /* Move cursor by rows entries down (if possible) */
    1299 
    1300         for (i = 0; i < rows; i++) {
    1301                 entry = ui_file_list_next(flist->cursor);
    1302                 if (entry != NULL) {
    1303                         flist->cursor = entry;
    1304                         ++flist->cursor_idx;
    1305                 }
    1306         }
    1307 
    1308         if (flist->page != old_page) {
    1309                 /* We have scrolled. Need to repaint all entries */
    1310                 ui_file_list_scrollbar_update(flist);
    1311                 (void) ui_file_list_paint(flist);
    1312         } else if (flist->cursor != old_cursor) {
    1313                 /* No scrolling, but cursor has moved */
    1314                 ui_file_list_entry_paint(old_cursor, old_idx);
    1315                 ui_file_list_entry_paint(flist->cursor, flist->cursor_idx);
    1316 
    1317                 (void) gfx_update(gc);
    1318         }
    1319 }
    1320 
    1321 /** Scroll one entry up.
    1322  *
    1323  * @param flist File list
    1324  */
    1325 void ui_file_list_scroll_up(ui_file_list_t *flist)
    1326 {
    1327         ui_file_list_entry_t *prev;
    1328 
    1329         prev = ui_file_list_prev(flist->page);
    1330         if (prev == NULL)
    1331                 return;
    1332 
    1333         flist->page = prev;
    1334         assert(flist->page_idx > 0);
    1335         --flist->page_idx;
    1336 
    1337         ui_file_list_scrollbar_update(flist);
    1338         (void) ui_file_list_paint(flist);
    1339 }
    1340 
    1341 /** Scroll one entry down.
    1342  *
    1343  * @param flist File list
    1344  */
    1345 void ui_file_list_scroll_down(ui_file_list_t *flist)
    1346 {
    1347         ui_file_list_entry_t *next;
    1348         ui_file_list_entry_t *pgend;
    1349         size_t i;
    1350         size_t rows;
    1351 
    1352         next = ui_file_list_next(flist->page);
    1353         if (next == NULL)
    1354                 return;
    1355 
    1356         rows = ui_file_list_page_size(flist);
    1357 
    1358         /* Find last page entry */
    1359         pgend = flist->page;
    1360         for (i = 0; i < rows && pgend != NULL; i++) {
    1361                 pgend = ui_file_list_next(pgend);
    1362         }
    1363 
    1364         /* Scroll down by one entry, if the page remains full */
    1365         if (pgend != NULL) {
    1366                 flist->page = next;
    1367                 ++flist->page_idx;
    1368         }
    1369 
    1370         ui_file_list_scrollbar_update(flist);
    1371         (void) ui_file_list_paint(flist);
    1372 }
    1373 
    1374 /** Scroll one page up.
    1375  *
    1376  * @param flist File list
    1377  */
    1378 void ui_file_list_scroll_page_up(ui_file_list_t *flist)
    1379 {
    1380         ui_file_list_entry_t *prev;
    1381         size_t i;
    1382         size_t rows;
    1383 
    1384         prev = ui_file_list_prev(flist->page);
    1385         if (prev == NULL)
    1386                 return;
    1387 
    1388         rows = ui_file_list_page_size(flist);
    1389 
    1390         for (i = 0; i < rows && prev != NULL; i++) {
    1391                 flist->page = prev;
    1392                 assert(flist->page_idx > 0);
    1393                 --flist->page_idx;
    1394                 prev = ui_file_list_prev(prev);
    1395         }
    1396 
    1397         ui_file_list_scrollbar_update(flist);
    1398         (void) ui_file_list_paint(flist);
    1399 }
    1400 
    1401 /** Scroll one page down.
    1402  *
    1403  * @param flist File list
    1404  */
    1405 void ui_file_list_scroll_page_down(ui_file_list_t *flist)
    1406 {
    1407         ui_file_list_entry_t *next;
    1408         ui_file_list_entry_t *pgend;
    1409         size_t i;
    1410         size_t rows;
    1411 
    1412         next = ui_file_list_next(flist->page);
    1413         if (next == NULL)
    1414                 return;
    1415 
    1416         rows = ui_file_list_page_size(flist);
    1417 
    1418         /* Find last page entry */
    1419         pgend = flist->page;
    1420         for (i = 0; i < rows && pgend != NULL; i++) {
    1421                 pgend = ui_file_list_next(pgend);
    1422         }
    1423 
    1424         /* Scroll by up to 'rows' entries, keeping the page full */
    1425         for (i = 0; i < rows && pgend != NULL; i++) {
    1426                 flist->page = next;
    1427                 ++flist->page_idx;
    1428                 next = ui_file_list_next(next);
    1429                 pgend = ui_file_list_next(pgend);
    1430         }
    1431 
    1432         ui_file_list_scrollbar_update(flist);
    1433         (void) ui_file_list_paint(flist);
    1434 }
    1435 
    1436 /** Scroll to a specific entry
    1437  *
    1438  * @param flist File list
    1439  * @param page_idx New index of first entry on the page
    1440  */
    1441 void ui_file_list_scroll_pos(ui_file_list_t *flist, size_t page_idx)
    1442 {
    1443         ui_file_list_entry_t *entry;
    1444         size_t i;
    1445 
    1446         entry = ui_file_list_first(flist);
    1447         for (i = 0; i < page_idx; i++) {
    1448                 entry = ui_file_list_next(entry);
    1449                 assert(entry != NULL);
    1450         }
    1451 
    1452         flist->page = entry;
    1453         flist->page_idx = page_idx;
    1454 
    1455         (void) ui_file_list_paint(flist);
     533        return (ui_file_list_entry_t *)ui_list_entry_get_arg(entry);
    1456534}
    1457535
     
    1487565    ui_file_list_entry_t *entry)
    1488566{
    1489         gfx_context_t *gc = ui_window_get_gc(flist->window);
    1490567        char *dirname;
    1491568        errno_t rc;
     
    1515592                return rc;
    1516593
    1517         return gfx_update(gc);
     594        return EOK;
    1518595}
    1519596
     
    1557634}
    1558635
    1559 /** File list scrollbar up button pressed.
    1560  *
    1561  * @param scrollbar Scrollbar
     636/** Paint file list.
     637 *
     638 * @param flist File list
     639 * @return EOK on success or an error code.
     640 */
     641errno_t ui_file_list_paint(ui_file_list_t *flist)
     642{
     643        return ui_control_paint(ui_list_ctl(flist->list));
     644}
     645
     646/** Destroy file list control.
     647 *
     648 * @param arg Argument (ui_list_t *)
     649 */
     650void ui_file_list_ctl_destroy(void *arg)
     651{
     652        ui_file_list_t *flist = (ui_file_list_t *) arg;
     653
     654        ui_file_list_destroy(flist);
     655}
     656
     657/** Paint file list control.
     658 *
    1562659 * @param arg Argument (ui_file_list_t *)
    1563  */
    1564 static void ui_file_list_scrollbar_up(ui_scrollbar_t *scrollbar, void *arg)
     660 * @return EOK on success or an error code
     661 */
     662errno_t ui_file_list_ctl_paint(void *arg)
     663{
     664        ui_file_list_t *flist = (ui_file_list_t *) arg;
     665
     666        return ui_file_list_paint(flist);
     667}
     668
     669/** Handle file list control keyboard event.
     670 *
     671 * @param arg Argument (ui_file_list_t *)
     672 * @param kbd_event Keyboard event
     673 * @return @c ui_claimed iff the event is claimed
     674 */
     675ui_evclaim_t ui_file_list_ctl_kbd_event(void *arg, kbd_event_t *event)
     676{
     677        ui_file_list_t *flist = (ui_file_list_t *) arg;
     678
     679        return ui_control_kbd_event(ui_list_ctl(flist->list), event);
     680}
     681
     682/** Handle file list control position event.
     683 *
     684 * @param arg Argument (ui_file_list_t *)
     685 * @param pos_event Position event
     686 * @return @c ui_claimed iff the event is claimed
     687 */
     688ui_evclaim_t ui_file_list_ctl_pos_event(void *arg, pos_event_t *event)
     689{
     690        ui_file_list_t *flist = (ui_file_list_t *) arg;
     691
     692        return ui_control_pos_event(ui_list_ctl(flist->list), event);
     693}
     694
     695/** Activate request callback handler for UI list within file list.
     696 *
     697 * @param list UI list
     698 * @param arg Argument (File list)
     699 */
     700static void ui_file_list_list_activate_req(ui_list_t *list, void *arg)
    1565701{
    1566702        ui_file_list_t *flist = (ui_file_list_t *)arg;
    1567         ui_file_list_scroll_up(flist);
    1568 }
    1569 
    1570 /** File list scrollbar down button pressed.
    1571  *
    1572  * @param scrollbar Scrollbar
    1573  * @param arg Argument (ui_file_list_t *)
    1574  */
    1575 static void ui_file_list_scrollbar_down(ui_scrollbar_t *scrollbar, void *arg)
    1576 {
    1577         ui_file_list_t *flist = (ui_file_list_t *)arg;
    1578         ui_file_list_scroll_down(flist);
    1579 }
    1580 
    1581 /** File list scrollbar page up pressed.
    1582  *
    1583  * @param scrollbar Scrollbar
    1584  * @param arg Argument (ui_file_list_t *)
    1585  */
    1586 static void ui_file_list_scrollbar_page_up(ui_scrollbar_t *scrollbar, void *arg)
    1587 {
    1588         ui_file_list_t *flist = (ui_file_list_t *)arg;
    1589         ui_file_list_scroll_page_up(flist);
    1590 }
    1591 
    1592 /** File list scrollbar page down pressed.
    1593  *
    1594  * @param scrollbar Scrollbar
    1595  * @param arg Argument (ui_file_list_t *)
    1596  */
    1597 static void ui_file_list_scrollbar_page_down(ui_scrollbar_t *scrollbar,
    1598     void *arg)
    1599 {
    1600         ui_file_list_t *flist = (ui_file_list_t *)arg;
    1601         ui_file_list_scroll_page_down(flist);
    1602 }
    1603 
    1604 /** File list scrollbar moved.
    1605  *
    1606  * @param scrollbar Scrollbar
    1607  * @param arg Argument (ui_file_list_t *)
    1608  */
    1609 static void ui_file_list_scrollbar_moved(ui_scrollbar_t *scrollbar, void *arg,
    1610     gfx_coord_t pos)
    1611 {
    1612         ui_file_list_t *flist = (ui_file_list_t *)arg;
    1613         size_t entries;
    1614         size_t pglen;
    1615         size_t sbar_len;
    1616         size_t pgstart;
    1617 
    1618         entries = list_count(&flist->entries);
    1619         pglen = ui_file_list_page_size(flist);
    1620         sbar_len = ui_scrollbar_move_length(flist->scrollbar);
    1621 
    1622         if (entries > pglen)
    1623                 pgstart = (entries - pglen) * pos / (sbar_len - 1);
    1624         else
    1625                 pgstart = 0;
    1626 
    1627         ui_file_list_scroll_pos(flist, pgstart);
     703
     704        ui_file_list_activate_req(flist);
     705}
     706
     707/** Entry selected callback handler for UI list within file list.
     708 *
     709 * @param entr Activated UI list entry
     710 * @param arg Argument (File list entry)
     711 */
     712static void ui_file_list_list_selected(ui_list_entry_t *entry, void *arg)
     713{
     714        ui_file_list_entry_t *fentry = (void *)arg;
     715
     716        (void) ui_file_list_open(fentry->flist, fentry);
    1628717}
    1629718
Note: See TracChangeset for help on using the changeset viewer.