table: Improve table render performance. (#421)
Before: ~85 - 100FPS After: ~110 - 115FPS
This commit is contained in:
parent
fa6abe5a9e
commit
e6012fcc8f
1 changed files with 58 additions and 73 deletions
|
|
@ -11,9 +11,10 @@ use crate::{
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, canvas, div, prelude::FluentBuilder, px, uniform_list, AppContext, Bounds, Div,
|
actions, canvas, div, prelude::FluentBuilder, px, uniform_list, AppContext, Bounds, Div,
|
||||||
DragMoveEvent, Edges, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
|
DragMoveEvent, Edges, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
|
||||||
InteractiveElement, IntoElement, KeyBinding, MouseButton, ParentElement, Pixels, Point, Render,
|
InteractiveElement, IntoElement, KeyBinding, ListSizingBehavior, MouseButton, ParentElement,
|
||||||
ScrollHandle, ScrollStrategy, SharedString, Stateful, StatefulInteractiveElement as _, Styled,
|
Pixels, Point, Render, ScrollHandle, ScrollStrategy, SharedString, Stateful,
|
||||||
UniformListScrollHandle, ViewContext, VisualContext as _, WindowContext,
|
StatefulInteractiveElement as _, Styled, UniformListScrollHandle, ViewContext,
|
||||||
|
VisualContext as _, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
actions!(
|
actions!(
|
||||||
|
|
@ -102,6 +103,11 @@ pub enum TableEvent {
|
||||||
ColWidthsChanged(Vec<Option<Pixels>>),
|
ColWidthsChanged(Vec<Option<Pixels>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
struct FixedCols {
|
||||||
|
left: usize,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Table<D: TableDelegate> {
|
pub struct Table<D: TableDelegate> {
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
delegate: D,
|
delegate: D,
|
||||||
|
|
@ -113,6 +119,7 @@ pub struct Table<D: TableDelegate> {
|
||||||
head_content_bounds: Bounds<Pixels>,
|
head_content_bounds: Bounds<Pixels>,
|
||||||
|
|
||||||
col_groups: Vec<ColGroup>,
|
col_groups: Vec<ColGroup>,
|
||||||
|
fixed_cols: FixedCols,
|
||||||
|
|
||||||
pub vertical_scroll_handle: UniformListScrollHandle,
|
pub vertical_scroll_handle: UniformListScrollHandle,
|
||||||
pub scrollbar_state: Rc<Cell<ScrollbarState>>,
|
pub scrollbar_state: Rc<Cell<ScrollbarState>>,
|
||||||
|
|
@ -272,6 +279,7 @@ where
|
||||||
focus_handle: cx.focus_handle(),
|
focus_handle: cx.focus_handle(),
|
||||||
delegate,
|
delegate,
|
||||||
col_groups: Vec::new(),
|
col_groups: Vec::new(),
|
||||||
|
fixed_cols: FixedCols::default(),
|
||||||
horizontal_scroll_handle: ScrollHandle::new(),
|
horizontal_scroll_handle: ScrollHandle::new(),
|
||||||
vertical_scroll_handle: UniformListScrollHandle::new(),
|
vertical_scroll_handle: UniformListScrollHandle::new(),
|
||||||
scrollbar_state: Rc::new(Cell::new(ScrollbarState::new())),
|
scrollbar_state: Rc::new(Cell::new(ScrollbarState::new())),
|
||||||
|
|
@ -339,6 +347,11 @@ where
|
||||||
fixed: self.delegate.col_fixed(col_ix, cx),
|
fixed: self.delegate.col_fixed(col_ix, cx),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
self.fixed_cols.left = self
|
||||||
|
.col_groups
|
||||||
|
.iter()
|
||||||
|
.filter(|col| col.fixed == Some(ColFixed::Left))
|
||||||
|
.count();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -733,14 +746,12 @@ where
|
||||||
fn render_sort_icon(
|
fn render_sort_icon(
|
||||||
&self,
|
&self,
|
||||||
col_ix: usize,
|
col_ix: usize,
|
||||||
|
col_group: &ColGroup,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Option<impl IntoElement> {
|
) -> Option<impl IntoElement> {
|
||||||
let sort = self.col_groups.get(col_ix).and_then(|g| g.sort);
|
let Some(sort) = col_group.sort else {
|
||||||
if sort.is_none() {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
};
|
||||||
|
|
||||||
let sort = sort.unwrap();
|
|
||||||
|
|
||||||
let (icon, is_on) = match sort {
|
let (icon, is_on) = match sort {
|
||||||
ColSort::Ascending => (IconName::SortAscending, true),
|
ColSort::Ascending => (IconName::SortAscending, true),
|
||||||
|
|
@ -776,8 +787,10 @@ where
|
||||||
fn render_th(&self, col_ix: usize, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render_th(&self, col_ix: usize, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
let entity_id = cx.entity_id();
|
let entity_id = cx.entity_id();
|
||||||
let col_group = self.col_groups.get(col_ix).expect("BUG: invalid col index");
|
let col_group = self.col_groups.get(col_ix).expect("BUG: invalid col index");
|
||||||
|
let moveable = self.delegate.can_move_col(col_ix, cx);
|
||||||
|
let paddings = self.delegate.col_padding(col_ix, cx);
|
||||||
let name = self.delegate.col_name(col_ix, cx);
|
let name = self.delegate.col_name(col_ix, cx);
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.child(
|
.child(
|
||||||
self.render_cell(col_ix, cx)
|
self.render_cell(col_ix, cx)
|
||||||
|
|
@ -794,16 +807,15 @@ where
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.items_center()
|
.items_center()
|
||||||
.child(self.delegate.render_th(col_ix, cx))
|
.child(self.delegate.render_th(col_ix, cx))
|
||||||
.when_some(self.delegate().col_padding(col_ix, cx), |this, padding| {
|
.when_some(paddings, |this, paddings| {
|
||||||
// Leave right space for the sort icon, if this column have custom padding
|
// Leave right space for the sort icon, if this column have custom padding
|
||||||
let offset_pr =
|
let offset_pr =
|
||||||
self.size.table_cell_padding().right - padding.right;
|
self.size.table_cell_padding().right - paddings.right;
|
||||||
|
|
||||||
this.pr(offset_pr.max(px(0.)))
|
this.pr(offset_pr.max(px(0.)))
|
||||||
})
|
})
|
||||||
.children(self.render_sort_icon(col_ix, cx)),
|
.children(self.render_sort_icon(col_ix, &col_group, cx)),
|
||||||
)
|
)
|
||||||
.when(self.delegate.can_move_col(col_ix, cx), |this| {
|
.when(moveable, |this| {
|
||||||
this.on_drag(
|
this.on_drag(
|
||||||
DragCol {
|
DragCol {
|
||||||
entity_id,
|
entity_id,
|
||||||
|
|
@ -855,11 +867,6 @@ where
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
let view = cx.view().clone();
|
let view = cx.view().clone();
|
||||||
let horizontal_scroll_handle = self.horizontal_scroll_handle.clone();
|
let horizontal_scroll_handle = self.horizontal_scroll_handle.clone();
|
||||||
let fixed_cols_count = self
|
|
||||||
.col_groups
|
|
||||||
.iter()
|
|
||||||
.filter(|col| col.fixed.is_some())
|
|
||||||
.count();
|
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.w_full()
|
.w_full()
|
||||||
|
|
@ -868,7 +875,7 @@ where
|
||||||
.border_b_1()
|
.border_b_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.text_color(cx.theme().table_head_foreground)
|
.text_color(cx.theme().table_head_foreground)
|
||||||
.when(fixed_cols_count > 0, |this| {
|
.when(left_cols_count > 0, |this| {
|
||||||
let view = view.clone();
|
let view = view.clone();
|
||||||
// Render left fixed columns
|
// Render left fixed columns
|
||||||
this.child(
|
this.child(
|
||||||
|
|
@ -898,55 +905,38 @@ where
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.child(
|
.child(
|
||||||
// Render other normal columns
|
// Columns
|
||||||
uniform_list(view.clone(), "table-head-uniform-list", 1, {
|
h_flex()
|
||||||
let horizontal_scroll_handle = horizontal_scroll_handle.clone();
|
.id("table-head")
|
||||||
let view = view.clone();
|
.size_full()
|
||||||
move |table, _, cx| {
|
.overflow_scroll()
|
||||||
let view = view.clone();
|
.relative()
|
||||||
|
.track_scroll(&horizontal_scroll_handle)
|
||||||
// Columns
|
.bg(cx.theme().table_head)
|
||||||
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("table-head")
|
|
||||||
.h_full()
|
|
||||||
.w_full()
|
|
||||||
.overflow_scroll()
|
|
||||||
.relative()
|
.relative()
|
||||||
.track_scroll(&horizontal_scroll_handle)
|
.children(
|
||||||
.bg(cx.theme().table_head)
|
self.col_groups
|
||||||
.child(
|
.iter()
|
||||||
h_flex()
|
.filter(|col| col.fixed == None)
|
||||||
.relative()
|
.enumerate()
|
||||||
.children(
|
.map(|(col_ix, _)| {
|
||||||
table
|
self.render_th(left_cols_count + col_ix, cx)
|
||||||
.col_groups
|
}),
|
||||||
.iter()
|
|
||||||
.filter(|col| col.fixed == None)
|
|
||||||
.enumerate()
|
|
||||||
.map(|(col_ix, _)| {
|
|
||||||
table.render_th(left_cols_count + col_ix, cx)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.child(table.delegate.render_last_empty_col(cx))
|
|
||||||
.child(
|
|
||||||
canvas(
|
|
||||||
move |bounds, cx| {
|
|
||||||
view.update(cx, |r, _| {
|
|
||||||
r.head_content_bounds = bounds
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|_, _, _| {},
|
|
||||||
)
|
|
||||||
.absolute()
|
|
||||||
.size_full(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.map(|this| vec![this])
|
.child(self.delegate.render_last_empty_col(cx))
|
||||||
}
|
.child(
|
||||||
})
|
canvas(
|
||||||
.h(self.size.table_row_height())
|
move |bounds, cx| {
|
||||||
.h_full()
|
view.update(cx, |r, _| r.head_content_bounds = bounds)
|
||||||
.flex_1(),
|
},
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.absolute()
|
||||||
|
.size_full(),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1111,6 +1101,7 @@ where
|
||||||
let vertical_scroll_handle = self.vertical_scroll_handle.clone();
|
let vertical_scroll_handle = self.vertical_scroll_handle.clone();
|
||||||
let horizontal_scroll_handle = self.horizontal_scroll_handle.clone();
|
let horizontal_scroll_handle = self.horizontal_scroll_handle.clone();
|
||||||
let cols_count: usize = self.delegate.cols_count(cx);
|
let cols_count: usize = self.delegate.cols_count(cx);
|
||||||
|
let left_cols_count = self.fixed_cols.left;
|
||||||
let rows_count = self.delegate.rows_count(cx);
|
let rows_count = self.delegate.rows_count(cx);
|
||||||
|
|
||||||
let row_height = self
|
let row_height = self
|
||||||
|
|
@ -1140,12 +1131,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let left_cols_count = self
|
|
||||||
.col_groups
|
|
||||||
.iter()
|
|
||||||
.filter(|col| col.fixed == Some(ColFixed::Left))
|
|
||||||
.count();
|
|
||||||
|
|
||||||
let inner_table = v_flex()
|
let inner_table = v_flex()
|
||||||
.key_context("Table")
|
.key_context("Table")
|
||||||
.id("table")
|
.id("table")
|
||||||
|
|
@ -1197,7 +1182,7 @@ where
|
||||||
)
|
)
|
||||||
.flex_grow()
|
.flex_grow()
|
||||||
.size_full()
|
.size_full()
|
||||||
.with_sizing_behavior(gpui::ListSizingBehavior::Auto)
|
.with_sizing_behavior(ListSizingBehavior::Auto)
|
||||||
.track_scroll(vertical_scroll_handle)
|
.track_scroll(vertical_scroll_handle)
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue