// License: MPL-2.0 // (c) 2022 Julian Hurst use libtui; use io; use unix::tty; use encoding::utf8; export type error = !(io::error | tty::error | utf8::invalid); // A function that displays the widget. 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 // register a listener with a widget, use [[addlistener]]. export type listener = *fn(w: *widget, r: libtui::key) bool; // A widget is an abstraction around a user-defined UI component. Custom widgets // can be created through sub-typing: // // export type my_widget = struct { // widget: widget::widget, // lines: []str, // }; // // fn print(w: *widget::widget) (void | widget::error) = { // const w = w: *my_widget; // for (let i = 0z; i < len(w.lines); i += 1) { // fmt::println(w.lines[i])!; // }; // }; // // fn finish(w: *widget::widget) void = { // const w = w: *my_widget; // free(w.lines); // widget::finishcommon(w); // }; // // let list = my_widget { // widget = widget::widget { // print = &print, // finish = &finish, // ... // }; // lines = strings::split("one,two,three", ","), // }; // let l = layout::newlayout(&list); // layout::print(l)!; export type widget = struct { print: nullable *print, finish: nullable *finish, setsize: nullable *setsize, listeners: []listener, ui: libtui::ttyui, }; // Add a listener to the given widget. export fn addlistener(w: *widget, listener: listener) void = { append(w.listeners, listener)!; }; // Delete a listener from the given widget. export fn dellistener(w: *widget, idx: size) void = { delete(w.listeners[idx]); }; // Clear the listeners of the given widget. export fn clearlisteners(w: *widget) void = { w.listeners = []; }; // Free the widget's listeners. export fn finishcommon(w: *widget) void = { free(w.listeners); }; // Notify (call) the widget's listeners with the widget and r as a parameter. // Returns true if a listener returned true, false otherwise. export fn notify(w: *widget, r: (rune | libtui::specialkey)) bool = { for (let i = 0z; i < len(w.listeners); i += 1) { if (w.listeners[i](w, r)) { return true; }; }; return false; };