diff options
| -rw-r--r-- | libtui/widget/list/list.ha | 96 | ||||
| -rw-r--r-- | libtui/widget/widget.ha | 3 |
2 files changed, 65 insertions, 34 deletions
diff --git a/libtui/widget/list/list.ha b/libtui/widget/list/list.ha index a897bb8..070e4f7 100644 --- a/libtui/widget/list/list.ha +++ b/libtui/widget/list/list.ha @@ -29,6 +29,7 @@ export type frame = struct { start: u16, // largest value is nb of items end: u16, + sz: ttysize, }; export type ttysize = struct { @@ -46,9 +47,16 @@ export type listener = *fn(l: *listwidget, r: (rune | libtui::specialkey)) bool; // using [[strings::dupall]]], so the original items can be freed. export fn newlist(ui: libtui::ttyui, items: str...) listwidget = { let sz = libtui::getwinsize(ui)!; - //let rows = sz.rows - 1; - let rows: (u16 | size) = if (sz.rows - 1 < len(items)) { - yield sz.rows - 1; + return newlistsz(ui, sz, items...); +}; + +// Create a new list with the given items and size. The given items will be +// duplicated using [[strings::dupall]]], so the original items can be freed. +export fn newlistsz(ui: libtui::ttyui, sz: tty::ttysize, items: str...) listwidget = { + //let sz = libtui::getwinsize(ui)!; + let rows = sz.rows; + let rows: (u16 | size) = if (sz.rows < len(items)) { + yield sz.rows; } else { yield len(items); }; @@ -66,9 +74,13 @@ export fn newlist(ui: libtui::ttyui, items: str...) listwidget = { frame = frame { start = 0u16, end = rows: u16, + sz = ttysize { + rows = rows: u16, + cols = sz.columns, + }, }, sz = ttysize { - rows = rows: u16, + rows = sz.rows, cols = sz.columns, }, }; @@ -128,22 +140,22 @@ export fn print(list: *widget::widget) (void | widget::error) = { let st = strio::dynamic(); strio::concat(&st, "\r")?; - let end = if (list.frame.end < len(list.items)) { - yield list.frame.end; - } else { - yield len(list.items); - }; - for (let i = list.frame.start; i < end: u16; i += 1) { - const item = list.items[i]; - const truncitem = wcwidth::truncate(item, list.sz.cols); - if (list.cursor == i) { - strio::concat(&st, SELECTED, truncitem, RESET)?; - //libtui::print(list.ui, strings::concat("\x1B[31;1m> ", list.items[i], "\x1B[0m")); - } else if (set::contains(&list.marked, i)) { - strio::concat(&st, MARKED, truncitem, RESET)?; - //libtui::print(list.ui, list.items[i]); - } else { - strio::concat(&st, truncitem)?; + + let end = list.frame.start + list.sz.rows; + + for (let i = list.frame.start; i < end; i += 1) { + if (i < len(list.items)) { + const item = list.items[i]; + const truncitem = wcwidth::truncate(item, list.sz.cols); + if (list.cursor == i) { + strio::concat(&st, SELECTED, truncitem, RESET)?; + //libtui::print(list.ui, strings::concat("\x1B[31;1m> ", list.items[i], "\x1B[0m")); + } else if (set::contains(&list.marked, i)) { + strio::concat(&st, MARKED, truncitem, RESET)?; + //libtui::print(list.ui, list.items[i]); + } else { + strio::concat(&st, truncitem)?; + }; }; strio::concat(&st, "\r\n")?; }; @@ -171,7 +183,7 @@ export fn reframe(l: *listwidget) bool = { let reframed: bool = false; if (l.cursor < l.frame.start) { l.frame.start = l.cursor: u16; - l.frame.end = l.frame.start + l.sz.rows; + l.frame.end = l.frame.start + l.frame.sz.rows; //l.frame.end -= l.frame.start - l.cursor: u16; reframed = true; }; @@ -186,24 +198,24 @@ export fn reframe(l: *listwidget) bool = { // Use signalfd and [[unix::signal::SIGWINCH]] and call this function in the // handler to support resizing the list. export fn resize(l: *listwidget, oldsz: ttysize) bool = { - if (l.frame.end - l.frame.start != l.sz.rows) { + if (l.frame.end - l.frame.start != l.frame.sz.rows) { if (l.cursor < (l.frame.end / 2)) { - l.frame.end = if (l.frame.start + l.sz.rows > len(l.items)) { - l.frame.start = len(l.items): u16 - l.sz.rows; + l.frame.end = if (l.frame.start + l.frame.sz.rows > len(l.items)) { + l.frame.start = len(l.items): u16 - l.frame.sz.rows; yield len(l.items): u16; } else { - yield l.frame.start + l.sz.rows; + yield l.frame.start + l.frame.sz.rows; }; for (l.cursor > l.frame.end) { l.frame.start += 1; l.frame.end += 1; }; } else { - l.frame.start = if (l.frame.end: int - l.sz.rows: int < 0) { - l.frame.end = 0 + l.sz.rows; + l.frame.start = if (l.frame.end: int - l.frame.sz.rows: int < 0) { + l.frame.end = 0 + l.frame.sz.rows; yield 0; } else { - yield l.frame.end - l.sz.rows; + yield l.frame.end - l.frame.sz.rows; }; for (l.cursor < l.frame.start) { l.frame.start -= 1; @@ -215,6 +227,22 @@ export fn resize(l: *listwidget, oldsz: ttysize) bool = { return false; }; +export fn setsize(l: *listwidget, sz: tty::ttysize) void = { + let rows: (u16 | size) = if (sz.rows < len(l.items)) { + yield sz.rows; + } else { + yield len(l.items); + }; + l.sz = ttysize { + rows = sz.rows, + cols = sz.columns, + }; + l.frame.sz = ttysize { + rows = rows: u16, + cols = sz.columns, + }; +}; + fn cursorinframe(l: *listwidget) bool = { return l.cursor >= l.frame.start && l.cursor < l.frame.end; }; @@ -239,8 +267,8 @@ export fn up(l: *listwidget) size = { // Move the list's cursor up one page. Returns the new cursor. export fn pageup(l: *listwidget) size = { - if (l.cursor: int - l.sz.rows: int >= 0) { - l.cursor -= l.sz.rows; + if (l.cursor: int - l.frame.sz.rows: int >= 0) { + l.cursor -= l.frame.sz.rows; } else { l.cursor = 0z; }; @@ -250,8 +278,8 @@ export fn pageup(l: *listwidget) size = { // Move the list's cursor down one page. Returns the new cursor. export fn pagedown(l: *listwidget) size = { - if (l.cursor + l.sz.rows < len(l.items)) { - l.cursor += l.sz.rows; + if (l.cursor + l.frame.sz.rows < len(l.items)) { + l.cursor += l.frame.sz.rows; } else { l.cursor = len(l.items) - 1; }; @@ -263,7 +291,7 @@ export fn pagedown(l: *listwidget) size = { export fn top(l: *listwidget) size = { l.cursor = 0; l.frame.start = 0; - l.frame.end = l.frame.start + l.sz.rows; + l.frame.end = l.frame.start + l.frame.sz.rows; return l.cursor; }; @@ -271,7 +299,7 @@ export fn top(l: *listwidget) size = { export fn bottom(l: *listwidget) size = { l.cursor = len(l.items) - 1; l.frame.end = len(l.items): u16; - l.frame.start = l.frame.end - l.sz.rows; + l.frame.start = l.frame.end - l.frame.sz.rows; return l.cursor; }; diff --git a/libtui/widget/widget.ha b/libtui/widget/widget.ha index 6875692..307378d 100644 --- a/libtui/widget/widget.ha +++ b/libtui/widget/widget.ha @@ -13,6 +13,8 @@ export type print = fn(w: *widget) (void | error); // A function that frees the resources associated to the widget. export type finish = fn(w: *widget) void; +export type setsize = fn(w: *widget, sz: tty::ttysize) void; + // An input listener on a widget. The returning value is intended to be used as // a signal that will be returned by [[notify]] in order to trigger certain more // global ui events (terminate the program, change widget focus, etc.). To @@ -53,6 +55,7 @@ export type listener = *fn(w: *widget, r: libtui::key) bool; export type widget = struct { print: nullable *print, finish: nullable *finish, + setsize: nullable *setsize, listeners: []listener, ui: libtui::ttyui, }; |
