aboutsummaryrefslogtreecommitdiff
path: root/kscurses/ui/table.jai
blob: dadc1c36f39a2cb40dd2a6b9c3eb447ba8f76bfd (plain)
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
UI_Table :: struct {
	#as using base : UI_Elem = .{type = .TABLE};

	// auto_scale := false;
	// metrics : []int;
	columns := 0;
	rows := 0;

	// description : []string;
	content : [..]string;

	cursor, offset := 0;
	show_cursor := false;
}

handle_key_table :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
	return false;
}

c_draw_table_content :: (canvas : *Canvas, using ui_table : *UI_Table, zone : Ibox2, style : *UI_Style, rows_visible : int) -> bool {
	for y : 0..zone.height-1 {
		is_selected := y == cursor && show_cursor;
		mode := ifx is_selected then style.text.selection else style.text.default;
		separator_char := Char.{code = style.box.default.tb, mode = mode};

		if zone.width < columns {
			for x : 0..zone.width {
				c_putchar(canvas, separator_char, zone.corner + ivec2.{xx x, xx y});				
			}
		} else {
			i := y + offset;
			for x : 0..columns-1 {
				l := (zone.width + 1) *       x / columns;
				r := (zone.width + 1) * (x + 1) / columns - 1;
				if y < rows_visible {
					field_content := content[i * columns + x];
					field_content.count = min(field_content.count, r - l);					
					c_draw_line_ascii(canvas, field_content, zone, .{xx l, xx y}, mode);
				}
				if x != columns-1 c_putchar(canvas, separator_char, zone.corner + ivec2.{xx r, xx y});
			}			
		}
	}
	return true;
}

c_draw_table :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
	using ui_table := cast(*UI_Table) ui_elem;
	assert(rows * columns == content.count);

	rows_visible := min(cast(int) zone.height, rows - offset);

	fix_offset :: () #expand {
		if cursor - offset < 0 {
			offset = cursor;
		} else if cursor - offset >= zone.height {
			offset = cursor - zone.height + 1;
		}
	}
	fix_offset();

	ok := c_draw_table_content(canvas, ui_table, zone, style, rows_visible);
	return ok;
}
init :: (table : *UI_Table, description : []string) {
	table.columns = description.count;
	table.description = description;
}
init :: (table : *UI_Table, columns : int) {
	table.columns = columns;
}

add_line :: (using table : *UI_Table, line : ..string) {
	assert(line.count == columns);
	array_add(*content, ..line);
	rows += 1;
}
deinit :: (using table : *UI_Table) {
	array_free(content);
}

// TODO
// variadic columns count, different content types
// empty separator
// automatic scale, as option
// description
// align content left/right/center