Changeset 54ddb59 in mainline for uspace/app/nav/panel.c
- Timestamp:
- 2022-06-20T13:10:08Z (3 years ago)
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/nav/panel.c
r453f9645 r54ddb59 1 1 /* 2 * Copyright (c) 202 1Jiri Svoboda2 * Copyright (c) 2022 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 35 35 */ 36 36 37 #include <dirent.h>38 37 #include <errno.h> 39 38 #include <gfx/render.h> 40 39 #include <gfx/text.h> 41 40 #include <stdlib.h> 42 #include <str.h>43 41 #include <task.h> 44 42 #include <ui/control.h> 43 #include <ui/filelist.h> 45 44 #include <ui/paint.h> 46 45 #include <ui/resource.h> 47 #include <vfs/vfs.h>48 #include <qsort.h>49 46 #include "panel.h" 50 47 #include "nav.h" … … 56 53 57 54 /** Panel control ops */ 58 ui_control_ops_t panel_ctl_ops = {55 static ui_control_ops_t panel_ctl_ops = { 59 56 .destroy = panel_ctl_destroy, 60 57 .paint = panel_ctl_paint, … … 63 60 }; 64 61 62 static void panel_flist_selected(ui_file_list_t *, void *, const char *); 63 64 /** Panel file list callbacks */ 65 static ui_file_list_cb_t panel_flist_cb = { 66 .selected = panel_flist_selected 67 }; 68 65 69 /** Create panel. 66 70 * … … 90 94 goto error; 91 95 92 rc = gfx_color_new_ega(0x 30, &panel->curs_color);96 rc = gfx_color_new_ega(0x0f, &panel->act_border_color); 93 97 if (rc != EOK) 94 98 goto error; 95 99 96 rc = gfx_color_new_ega(0x0f, &panel->act_border_color);100 rc = ui_file_list_create(window, active, &panel->flist); 97 101 if (rc != EOK) 98 102 goto error; 99 103 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); 107 105 108 106 panel->window = window; 109 list_initialize(&panel->entries);110 panel->entries_cnt = 0;111 107 panel->active = active; 112 108 *rpanel = panel; … … 115 111 if (panel->color != NULL) 116 112 gfx_color_delete(panel->color); 117 if (panel->curs_color != NULL)118 gfx_color_delete(panel->curs_color);119 113 if (panel->act_border_color != NULL) 120 114 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); 125 117 ui_control_delete(panel->control); 126 118 free(panel); … … 135 127 { 136 128 gfx_color_delete(panel->color); 137 gfx_color_delete(panel->curs_color);138 129 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);142 130 ui_control_delete(panel->control); 143 131 free(panel); … … 156 144 } 157 145 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 */ 150 errno_t panel_paint(panel_t *panel) 151 { 167 152 gfx_context_t *gc = ui_window_get_gc(panel->window); 168 153 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 else195 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 where215 * it should be cut off (and append some sort of overflow216 * 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 Panel234 */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;240 154 ui_box_style_t bstyle; 241 155 gfx_color_t *bcolor; 242 int i, lines;156 ui_control_t *ctl; 243 157 errno_t rc; 244 158 … … 263 177 return rc; 264 178 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; 277 183 278 184 rc = gfx_update(gc); … … 291 197 ui_evclaim_t panel_kbd_event(panel_t *panel, kbd_event_t *event) 292 198 { 199 ui_control_t *ctl; 200 293 201 if (!panel->active) 294 202 return ui_unclaimed; 295 203 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); 327 206 } 328 207 … … 336 215 { 337 216 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; 342 218 343 219 pos.x = event->hpos; … … 349 225 panel_activate_req(panel); 350 226 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 */ 236 ui_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 */ 246 void panel_set_rect(panel_t *panel, gfx_rect_t *rect) 247 { 248 gfx_rect_t irect; 249 250 panel->rect = *rect; 251 351 252 irect.p0.x = panel->rect.p0.x + 1; 352 253 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; 354 255 irect.p1.y = panel->rect.p1.y - 1; 355 256 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); 415 258 } 416 259 … … 435 278 errno_t rc; 436 279 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; 442 283 443 284 panel->active = true; … … 452 293 void panel_deactivate(panel_t *panel) 453 294 { 295 ui_file_list_deactivate(panel->flist); 454 296 panel->active = false; 455 297 (void) panel_paint(panel); 456 }457 458 /** Initialize panel entry attributes.459 *460 * @param attr Attributes461 */462 void panel_entry_attr_init(panel_entry_attr_t *attr)463 {464 memset(attr, 0, sizeof(*attr));465 298 } 466 299 … … 514 347 } 515 348 516 /** Append new panel entry.517 *518 * @param panel Panel519 * @param attr Entry attributes520 * @return EOK on success or an error code521 */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 entry549 */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 Panel566 */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 578 349 /** Read directory into panel entry list. 579 350 * … … 584 355 errno_t panel_read_dir(panel_t *panel, const char *dirname) 585 356 { 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 */ 366 void 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 1114 378 * 1115 379 * @return EOK on success or an error code 1116 380 */ 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) 381 static errno_t panel_open_file(panel_t *panel, const char *fname) 1179 382 { 1180 383 task_id_t id; … … 1185 388 ui_t *ui; 1186 389 1187 /* It's not a directory */1188 assert(!entry->isdir);1189 /* It's not a service-special file */1190 assert(entry->svc == 0);1191 1192 390 ui = ui_window_get_ui(panel->window); 1193 391 … … 1197 395 return rc; 1198 396 1199 rc = task_spawnl(&id, &wait, entry->name, entry->name, NULL);397 rc = task_spawnl(&id, &wait, fname, fname, NULL); 1200 398 if (rc != EOK) 1201 399 goto error; … … 1218 416 } 1219 417 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 */ 424 static 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); 1230 430 } 1231 431
Note:
See TracChangeset
for help on using the changeset viewer.