1use gpui::prelude::*;
4use gpui::{div, px, App, Div, FontWeight, Hsla, IntoElement, SharedString, Window};
5
6use crate::theme::{theme, ColorName, Size};
7
8fn cell(value: SharedString, color: Hsla, weight: FontWeight, font: f32) -> Div {
11 div()
12 .flex_1()
13 .px(px(12.0))
14 .py(px(8.0))
15 .text_size(px(font))
16 .text_color(color)
17 .font_weight(weight)
18 .child(value)
19}
20
21#[derive(IntoElement)]
24pub struct Table {
25 head: Vec<SharedString>,
26 rows: Vec<Vec<SharedString>>,
27 striped: bool,
28 highlight_on_hover: bool,
29 with_border: bool,
30}
31
32impl Table {
33 pub fn new() -> Self {
34 Table {
35 head: Vec::new(),
36 rows: Vec::new(),
37 striped: false,
38 highlight_on_hover: false,
39 with_border: false,
40 }
41 }
42
43 pub fn head<I, S>(mut self, head: I) -> Self
44 where
45 I: IntoIterator<Item = S>,
46 S: Into<SharedString>,
47 {
48 self.head = head.into_iter().map(Into::into).collect();
49 self
50 }
51
52 pub fn row<I, S>(mut self, row: I) -> Self
53 where
54 I: IntoIterator<Item = S>,
55 S: Into<SharedString>,
56 {
57 self.rows.push(row.into_iter().map(Into::into).collect());
58 self
59 }
60
61 pub fn striped(mut self, striped: bool) -> Self {
62 self.striped = striped;
63 self
64 }
65
66 pub fn highlight_on_hover(mut self, highlight: bool) -> Self {
67 self.highlight_on_hover = highlight;
68 self
69 }
70
71 pub fn with_border(mut self, with_border: bool) -> Self {
72 self.with_border = with_border;
73 self
74 }
75}
76
77impl Default for Table {
78 fn default() -> Self {
79 Table::new()
80 }
81}
82
83impl RenderOnce for Table {
84 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
85 let t = theme(cx);
86 let font = t.font_size(Size::Sm);
87 let text = t.text().hsla();
88 let dimmed = t.dimmed().hsla();
89 let line = t.border().hsla();
90 let stripe = t.surface_hover().hsla();
91 let hover = t
92 .color(ColorName::Gray, if t.scheme.is_dark() { 6 } else { 1 })
93 .hsla();
94 let radius = t.radius(Size::Sm);
95 let striped = self.striped;
96 let highlight = self.highlight_on_hover;
97
98 let header = div().flex().border_b_1().border_color(line).children(
99 self.head
100 .into_iter()
101 .map(move |h| cell(h, dimmed, FontWeight::SEMIBOLD, font)),
102 );
103
104 let body = self.rows.into_iter().enumerate().map(move |(i, row)| {
105 let mut tr = div().flex().border_b_1().border_color(line).children(
106 row.into_iter()
107 .map(move |c| cell(c, text, FontWeight::NORMAL, font)),
108 );
109 if striped && i % 2 == 1 {
110 tr = tr.bg(stripe);
111 }
112 if highlight {
113 tr.id(("guise-table-row", i))
114 .hover(move |s| s.bg(hover))
115 .into_any_element()
116 } else {
117 tr.into_any_element()
118 }
119 });
120
121 let mut table = div()
122 .flex()
123 .flex_col()
124 .rounded(px(radius))
125 .child(header)
126 .children(body);
127 if self.with_border {
128 table = table.border_1().border_color(line);
129 }
130 table
131 }
132}