Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file tui/list_view.c
6 : * @brief Scroll + selection helper for vertical list panes (US-11 v2).
7 : */
8 :
9 : #include "tui/list_view.h"
10 :
11 : #include <string.h>
12 :
13 6 : void list_view_init(ListView *lv) {
14 6 : if (!lv) return;
15 6 : memset(lv, 0, sizeof(*lv));
16 6 : lv->selected = -1;
17 : }
18 :
19 6 : void list_view_reveal_selected(ListView *lv) {
20 6 : if (!lv || lv->count <= 0 || lv->rows_visible <= 0) return;
21 6 : if (lv->selected < lv->scroll_top) {
22 0 : lv->scroll_top = lv->selected;
23 6 : } else if (lv->selected >= lv->scroll_top + lv->rows_visible) {
24 0 : lv->scroll_top = lv->selected - lv->rows_visible + 1;
25 : }
26 6 : if (lv->scroll_top < 0) lv->scroll_top = 0;
27 : }
28 :
29 0 : void list_view_set_viewport(ListView *lv, int rows_visible) {
30 0 : if (!lv) return;
31 0 : lv->rows_visible = rows_visible < 0 ? 0 : rows_visible;
32 0 : list_view_reveal_selected(lv);
33 : }
34 :
35 5 : void list_view_set_count(ListView *lv, int count) {
36 5 : if (!lv) return;
37 5 : if (count < 0) count = 0;
38 5 : lv->count = count;
39 5 : if (count == 0) {
40 0 : lv->selected = -1;
41 0 : lv->scroll_top = 0;
42 0 : return;
43 : }
44 5 : if (lv->selected < 0) lv->selected = 0;
45 5 : if (lv->selected >= count) lv->selected = count - 1;
46 5 : if (lv->scroll_top > count - 1) lv->scroll_top = count - 1;
47 5 : if (lv->scroll_top < 0) lv->scroll_top = 0;
48 5 : list_view_reveal_selected(lv);
49 : }
50 :
51 0 : void list_view_move_up(ListView *lv) {
52 0 : if (!lv || lv->count == 0) return;
53 0 : if (lv->selected > 0) lv->selected--;
54 0 : list_view_reveal_selected(lv);
55 : }
56 :
57 1 : void list_view_move_down(ListView *lv) {
58 1 : if (!lv || lv->count == 0) return;
59 1 : if (lv->selected < lv->count - 1) lv->selected++;
60 1 : list_view_reveal_selected(lv);
61 : }
62 :
63 0 : void list_view_page_up(ListView *lv) {
64 0 : if (!lv || lv->count == 0) return;
65 0 : int step = lv->rows_visible > 0 ? lv->rows_visible : 1;
66 0 : lv->selected -= step;
67 0 : if (lv->selected < 0) lv->selected = 0;
68 0 : list_view_reveal_selected(lv);
69 : }
70 :
71 0 : void list_view_page_down(ListView *lv) {
72 0 : if (!lv || lv->count == 0) return;
73 0 : int step = lv->rows_visible > 0 ? lv->rows_visible : 1;
74 0 : lv->selected += step;
75 0 : if (lv->selected >= lv->count) lv->selected = lv->count - 1;
76 0 : list_view_reveal_selected(lv);
77 : }
78 :
79 0 : void list_view_home(ListView *lv) {
80 0 : if (!lv || lv->count == 0) return;
81 0 : lv->selected = 0;
82 0 : lv->scroll_top = 0;
83 : }
84 :
85 0 : void list_view_end(ListView *lv) {
86 0 : if (!lv || lv->count == 0) return;
87 0 : lv->selected = lv->count - 1;
88 0 : list_view_reveal_selected(lv);
89 : }
90 :
91 0 : int list_view_is_visible(const ListView *lv, int index) {
92 0 : if (!lv || lv->rows_visible <= 0) return 0;
93 0 : return index >= lv->scroll_top
94 0 : && index < lv->scroll_top + lv->rows_visible;
95 : }
|