table: Add visible_rows_changed, visible_cols_changed method to table delegate. (#543)

Co-authored-by: Jason Lee <huacnlee@gmail.com>
This commit is contained in:
Ylin 2025-01-13 13:51:20 +08:00 committed by GitHub
parent 205a499bc9
commit eb10186463
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 121 additions and 1 deletions

View file

@ -1,4 +1,7 @@
use std::time::{self, Duration};
use std::{
ops::Range,
time::{self, Duration},
};
use fake::{Fake, Faker};
use gpui::{
@ -181,6 +184,8 @@ struct StockTableDelegate {
loading: bool,
fixed_cols: bool,
is_eof: bool,
visible_rows: Range<usize>,
visible_cols: Range<usize>,
}
impl StockTableDelegate {
@ -250,6 +255,8 @@ impl StockTableDelegate {
fixed_cols: false,
loading: false,
is_eof: false,
visible_cols: Range::default(),
visible_rows: Range::default(),
}
}
@ -490,6 +497,22 @@ impl TableDelegate for StockTableDelegate {
})
.detach();
}
fn visible_rows_changed(
&mut self,
visible_range: Range<usize>,
_: &mut ViewContext<Table<Self>>,
) {
self.visible_rows = visible_range;
}
fn visible_cols_changed(
&mut self,
visible_range: Range<usize>,
_: &mut ViewContext<Table<Self>>,
) {
self.visible_cols = visible_range;
}
}
pub struct TableStory {
@ -842,6 +865,8 @@ impl Render for TableStory {
this.child(h_flex().gap_1().child(Indicator::new()).child("Loading..."))
})
.child(format!("Total Rows: {}", rows_count))
.child(format!("Visible Rows: {:?}", delegate.visible_rows))
.child(format!("Visible Cols: {:?}", delegate.visible_cols))
.when(delegate.is_eof, |this| this.child("All data loaded.")),
),
)

View file

@ -116,6 +116,27 @@ struct FixedCols {
left: usize,
}
/// The visible range of the rows and columns.
#[derive(Debug, Default)]
pub struct VisibleRangeState {
/// The visible range of the rows.
rows: Range<usize>,
/// The visible range of the columns.
cols: Range<usize>,
}
impl VisibleRangeState {
/// Returns the visible range of the rows.
pub fn rows(&self) -> Range<usize> {
self.rows.clone()
}
/// Returns the visible range of the columns.
pub fn cols(&self) -> Range<usize> {
self.cols.clone()
}
}
pub struct Table<D: TableDelegate> {
focus_handle: FocusHandle,
delegate: D,
@ -148,6 +169,8 @@ pub struct Table<D: TableDelegate> {
border: bool,
/// The cell size of the table.
size: Size,
/// The visible range of the rows and columns.
visible_range: VisibleRangeState,
}
#[allow(unused)]
@ -280,6 +303,32 @@ pub trait TableDelegate: Sized + 'static {
fn render_last_empty_col(&mut self, cx: &mut ViewContext<Table<Self>>) -> Div {
h_flex().w_5().h_full().flex_shrink_0()
}
/// Called when the visible range of the rows changed.
///
/// NOTE: Make sure this method is fast, because it will be called frequently.
///
/// This can used to handle some data update, to only update the visible rows.
/// Please ensure that the data is updated in the background task.
fn visible_rows_changed(
&mut self,
visible_range: Range<usize>,
cx: &mut ViewContext<Table<Self>>,
) {
}
/// Called when the visible range of the columns changed.
///
/// NOTE: Make sure this method is fast, because it will be called frequently.
///
/// This can used to handle some data update, to only update the visible rows.
/// Please ensure that the data is updated in the background task.
fn visible_cols_changed(
&mut self,
visible_range: Range<usize>,
cx: &mut ViewContext<Table<Self>>,
) {
}
}
impl<D> Table<D>
@ -307,6 +356,7 @@ where
stripe: false,
border: true,
size: Size::default(),
visible_range: VisibleRangeState::default(),
};
this.prepare_col_groups(cx);
@ -436,6 +486,11 @@ where
cx.notify();
}
/// Returns the visible range of the rows and columns.
pub fn visible_range(&self) -> &VisibleRangeState {
&self.visible_range
}
fn on_row_click(&mut self, ev: &MouseDownEvent, row_ix: usize, cx: &mut ViewContext<Self>) {
if ev.button == MouseButton::Right {
self.right_clicked_row = Some(row_ix);
@ -630,6 +685,35 @@ where
}
}
fn update_visible_range_if_need(
&mut self,
visible_range: Range<usize>,
axis: Axis,
cx: &mut ViewContext<Self>,
) {
// Skip when visible range is only 1 item.
// The visual_list will use first item to measure.
if visible_range.len() <= 1 {
return;
}
if axis == Axis::Vertical {
if self.visible_range.rows == visible_range {
return;
}
self.delegate_mut()
.visible_rows_changed(visible_range.clone(), cx);
self.visible_range.rows = visible_range;
} else {
if self.visible_range.cols == visible_range {
return;
}
self.delegate_mut()
.visible_cols_changed(visible_range.clone(), cx);
self.visible_range.cols = visible_range;
}
}
/// Returns the size of the content area.
fn head_content_bounds(&self) -> gpui::Bounds<Pixels> {
let has_fixed_cols = self.fixed_head_cols_bounds.size.width > px(0.0);
@ -1054,6 +1138,12 @@ where
.child(
virtual_list(view, row_ix, Axis::Horizontal, col_sizes, {
move |table, visible_range: Range<usize>, _, cx| {
table.update_visible_range_if_need(
visible_range.clone(),
Axis::Horizontal,
cx,
);
visible_range
.map(|col_ix| {
let col_ix = col_ix + left_cols_count;
@ -1227,6 +1317,11 @@ where
{
move |table, visible_range, cx| {
table.load_more_if_need(visible_range.clone(), cx);
table.update_visible_range_if_need(
visible_range.clone(),
Axis::Vertical,
cx,
);
if visible_range.end > rows_count {
table.scroll_to_row(