1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
// License: MPL-2.0
// (c) 2022 Julian Hurst <ark@mansus.space>
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;
};
|