aboutsummaryrefslogtreecommitdiff
path: root/kscurses/ui/select_list.jai
blob: 8c338c642e65bc64fb0eb45f49e175c90a22aac2 (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
UI_Select_List :: struct {
	#as using base : UI_Elem = .{type = .SELECT_LIST};
	only_one := true;
	options : []string;
	selected : []bool;

	selected_id := -1;
	cursor, offset := 0, 0;

	prefix_default  := "[ ]";
	prefix_selected := "[+]";
}
handle_key_select_list :: (ui_elem : *UI_Elem, key : Key) -> handled:bool {
	using cast(*UI_Select_List) ui_elem;
	assert(cursor_state != .OUTSIDE);
	if cursor_state == .ON {
		if key == .ENTER {
			cursor_state = .IN;
			return true;
		}
	} else {
		if key == {
			case .DOWN;
			if cursor < options.count - 1 then cursor += 1;
			case .UP;
			if cursor > 0 then cursor -= 1;
			case .ESCAPE;
			cursor_state = .ON;
			case .ENTER;
			if only_one {
				if cursor == selected_id {
					selected_id = -1;
				} else {
					selected_id = cursor;
				}
			} else {
				selected[cursor] ^= true;
			}
			case;
			return false;
		}
		return true;
	}
	return false;
}
init :: (select_list : *UI_Select_List, only_one := true) {
	select_list.only_one = only_one;
	if !only_one select_list.selected = NewArray(select_list.options.count, bool);
}
deinit :: (using select_list : *UI_Select_List) {
	array_free(selected);
}
c_draw_select_list :: (canvas : *Canvas, ui_elem : *UI_Elem, zone : Ibox2, style : *UI_Style) -> bool {
	using cast(*UI_Select_List) ui_elem;
	rows := min(cast(int) zone.height, options.count - offset);

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

	for y : 0..rows-1 {
		i := y + offset;
		is_selected := ifx only_one then i == selected_id else selected[i];
		prefix := ifx is_selected then prefix_selected else prefix_default;
		mode := ifx i == cursor && cursor_state == .IN
					ifx is_selected style.text.cursor_and_selection else style.text.cursor
				else
					ifx is_selected style.text.selection else style.text.default;

		c_draw_line_ascii(canvas, prefix, zone, .{0, xx y}, mode);
		c_draw_line_ascii(canvas, options[i], zone, .{xx prefix.count, xx y}, mode);
	}
	return true;
}