use std::f32;
use gpui::{
Bounds, Context, Edges, Empty, EntityId, IntoElement, ParentElement as _, Pixels, Render,
SharedString, Styled as _, TextAlign, Window, div, prelude::FluentBuilder, px,
};
use crate::{ActiveTheme as _, TableThemeExt};
#[derive(Debug, Clone)]
pub struct Column {
pub key: SharedString,
pub name: SharedString,
pub align: TextAlign,
pub sort: Option<ColumnSort>,
pub paddings: Option<Edges<Pixels>>,
pub width: Pixels,
pub auto_width: Option<Pixels>,
pub fixed: Option<ColumnFixed>,
pub resizable: bool,
pub movable: bool,
pub selectable: bool,
pub min_width: Pixels,
pub max_width: Pixels,
}
impl Default for Column {
fn default() -> Self {
Self {
key: SharedString::new(""),
name: SharedString::new(""),
align: TextAlign::Left,
sort: None,
paddings: None,
width: px(100.),
auto_width: None,
fixed: None,
resizable: true,
movable: true,
selectable: true,
min_width: px(20.0),
max_width: px(f32::MAX),
}
}
}
impl Column {
pub fn new(key: impl Into<SharedString>, name: impl Into<SharedString>) -> Self {
Self {
key: key.into(),
name: name.into(),
..Default::default()
}
}
pub fn sort(mut self, sort: ColumnSort) -> Self {
self.sort = Some(sort);
self
}
pub fn sortable(mut self) -> Self {
self.sort = Some(ColumnSort::Default);
self
}
pub fn ascending(mut self) -> Self {
self.sort = Some(ColumnSort::Ascending);
self
}
pub fn descending(mut self) -> Self {
self.sort = Some(ColumnSort::Descending);
self
}
pub fn text_center(mut self) -> Self {
self.align = TextAlign::Center;
self
}
pub fn text_right(mut self) -> Self {
self.align = TextAlign::Right;
self
}
pub fn paddings(mut self, paddings: impl Into<Edges<Pixels>>) -> Self {
self.paddings = Some(paddings.into());
self
}
pub fn p_0(mut self) -> Self {
self.paddings = Some(Edges::all(px(0.)));
self
}
pub fn width(mut self, width: impl Into<Pixels>) -> Self {
self.width = width.into();
self
}
pub fn force_width_in_auto_mode(mut self, width: impl Into<Pixels>) -> Self {
self.auto_width = Some(width.into());
self
}
pub fn fixed(mut self, fixed: impl Into<ColumnFixed>) -> Self {
self.fixed = Some(fixed.into());
self
}
pub fn fixed_left(mut self) -> Self {
self.fixed = Some(ColumnFixed::Left);
self
}
pub fn resizable(mut self, resizable: bool) -> Self {
self.resizable = resizable;
self
}
pub fn movable(mut self, movable: bool) -> Self {
self.movable = movable;
self
}
pub fn selectable(mut self, selectable: bool) -> Self {
self.selectable = selectable;
self
}
pub fn min_width(mut self, min_width: impl Into<Pixels>) -> Self {
let min_width = min_width.into();
self.min_width = min_width;
if self.width < min_width {
self.width = min_width;
}
self
}
pub fn max_width(mut self, max_width: impl Into<Pixels>) -> Self {
let max_width = max_width.into();
self.max_width = max_width;
if self.width > max_width {
self.width = max_width;
}
self
}
}
impl FluentBuilder for Column {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColumnFixed {
Left,
}
#[derive(Debug, Clone)]
pub(crate) struct ColGroup {
pub(crate) column: Column,
pub(crate) width: Pixels,
pub(crate) preview_width: Option<Pixels>,
pub(crate) bounds: Bounds<Pixels>,
}
impl ColGroup {
pub(crate) fn is_resizable(&self) -> bool {
self.column.resizable
}
pub(crate) fn current_width(&self) -> Pixels {
self.preview_width.unwrap_or(self.width)
}
pub(crate) fn commit_preview_width(&mut self) -> bool {
let Some(preview_width) = self.preview_width.take() else {
return false;
};
if self.width == preview_width {
return false;
}
self.width = preview_width;
true
}
}
#[derive(Clone)]
pub(crate) struct DragColumn {
pub(crate) entity_id: EntityId,
pub(crate) name: SharedString,
pub(crate) width: Pixels,
pub(crate) col_ix: usize,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
pub enum ColumnSort {
#[default]
Default,
Ascending,
Descending,
}
impl Render for DragColumn {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.px_4()
.py_1()
.bg(cx.theme().table_head())
.text_color(cx.theme().muted_foreground)
.opacity(0.9)
.border_1()
.border_color(cx.theme().border)
.shadow_md()
.w(self.width)
.min_w(px(100.))
.max_w(px(450.))
.child(self.name.clone())
}
}
#[derive(Clone)]
pub(crate) struct ResizeColumn(pub (EntityId, usize));
impl Render for ResizeColumn {
fn render(&mut self, _window: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
Empty
}
}