gpui_component/table/
column.rs

1use gpui::{
2    div, prelude::FluentBuilder, px, Bounds, Context, Edges, Empty, EntityId, IntoElement,
3    ParentElement as _, Pixels, Render, SharedString, Styled as _, TextAlign, Window,
4};
5
6use crate::ActiveTheme as _;
7
8/// Represents a column in a table, used for initializing table columns.
9#[derive(Debug, Clone)]
10pub struct Column {
11    pub key: SharedString,
12    pub name: SharedString,
13    pub align: TextAlign,
14    pub sort: Option<ColumnSort>,
15    pub paddings: Option<Edges<Pixels>>,
16    pub width: Pixels,
17    pub fixed: Option<ColumnFixed>,
18    pub resizable: bool,
19    pub movable: bool,
20    pub selectable: bool,
21}
22
23impl Default for Column {
24    fn default() -> Self {
25        Self {
26            key: SharedString::new(""),
27            name: SharedString::new(""),
28            align: TextAlign::Left,
29            sort: None,
30            paddings: None,
31            width: px(100.),
32            fixed: None,
33            resizable: true,
34            movable: true,
35            selectable: true,
36        }
37    }
38}
39
40impl Column {
41    /// Create a new column with the given key and name.
42    pub fn new(key: impl Into<SharedString>, name: impl Into<SharedString>) -> Self {
43        Self {
44            key: key.into(),
45            name: name.into(),
46            ..Default::default()
47        }
48    }
49
50    /// Set the column to be sortable with custom sort function, default is None (not sortable).
51    ///
52    /// See also [`Column::sortable`] to enable sorting with default.
53    pub fn sort(mut self, sort: ColumnSort) -> Self {
54        self.sort = Some(sort);
55        self
56    }
57
58    /// Set whether the column is sortable, default is true.
59    ///
60    /// See also [`Column::sort`].
61    pub fn sortable(mut self) -> Self {
62        self.sort = Some(ColumnSort::Default);
63        self
64    }
65
66    /// Set whether the column is sort with ascending order.
67    pub fn ascending(mut self) -> Self {
68        self.sort = Some(ColumnSort::Ascending);
69        self
70    }
71
72    /// Set whether the column is sort with descending order.
73    pub fn descending(mut self) -> Self {
74        self.sort = Some(ColumnSort::Descending);
75        self
76    }
77
78    /// Set the alignment of the column text, default is left.
79    ///
80    /// Only `text_left`, `text_right` is supported.
81    pub fn text_right(mut self) -> Self {
82        self.align = TextAlign::Right;
83        self
84    }
85
86    /// Set the padding of the column, default is None.
87    pub fn paddings(mut self, paddings: impl Into<Edges<Pixels>>) -> Self {
88        self.paddings = Some(paddings.into());
89        self
90    }
91
92    pub fn p_0(mut self) -> Self {
93        self.paddings = Some(Edges::all(px(0.)));
94        self
95    }
96
97    /// Set the width of the column, default is 100px.
98    pub fn width(mut self, width: impl Into<Pixels>) -> Self {
99        self.width = width.into();
100        self
101    }
102
103    /// Set whether the column is fixed, default is false.
104    pub fn fixed(mut self, fixed: impl Into<ColumnFixed>) -> Self {
105        self.fixed = Some(fixed.into());
106        self
107    }
108
109    /// Set whether the column is fixed on left side, default is false.
110    pub fn fixed_left(mut self) -> Self {
111        self.fixed = Some(ColumnFixed::Left);
112        self
113    }
114
115    /// Set whether the column is resizable, default is true.
116    pub fn resizable(mut self, resizable: bool) -> Self {
117        self.resizable = resizable;
118        self
119    }
120
121    /// Set whether the column is movable, default is true.
122    pub fn movable(mut self, movable: bool) -> Self {
123        self.movable = movable;
124        self
125    }
126
127    /// Set whether the column is selectable, default is true.
128    pub fn selectable(mut self, selectable: bool) -> Self {
129        self.selectable = selectable;
130        self
131    }
132}
133
134impl FluentBuilder for Column {}
135
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
137pub enum ColumnFixed {
138    Left,
139}
140
141/// Used to sort the column runtime info in Table internal.
142#[derive(Debug, Clone)]
143pub(crate) struct ColGroup {
144    pub(crate) column: Column,
145    /// This is the runtime width of the column, we may update it when the column is resized.
146    ///
147    /// Including the width with next columns by col_span.
148    pub(crate) width: Pixels,
149    /// The bounds of the column in the table after it renders.
150    pub(crate) bounds: Bounds<Pixels>,
151}
152
153impl ColGroup {
154    pub(crate) fn is_resizable(&self) -> bool {
155        self.column.resizable
156    }
157}
158
159#[derive(Clone)]
160pub(crate) struct DragColumn {
161    pub(crate) entity_id: EntityId,
162    pub(crate) name: SharedString,
163    pub(crate) width: Pixels,
164    pub(crate) col_ix: usize,
165}
166
167#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
168pub enum ColumnSort {
169    /// No sorting.
170    #[default]
171    Default,
172    /// Sort in ascending order.
173    Ascending,
174    /// Sort in descending order.
175    Descending,
176}
177
178impl Render for DragColumn {
179    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
180        div()
181            .px_4()
182            .py_1()
183            .bg(cx.theme().table_head)
184            .text_color(cx.theme().muted_foreground)
185            .opacity(0.9)
186            .border_1()
187            .border_color(cx.theme().border)
188            .shadow_md()
189            .w(self.width)
190            .min_w(px(100.))
191            .max_w(px(450.))
192            .child(self.name.clone())
193    }
194}
195
196#[derive(Clone)]
197pub(crate) struct ResizeColumn(pub (EntityId, usize));
198impl Render for ResizeColumn {
199    fn render(&mut self, _window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
200        Empty
201    }
202}