diff --git a/crates/story/src/table_story.rs b/crates/story/src/table_story.rs index 26659bdc..96f8c691 100644 --- a/crates/story/src/table_story.rs +++ b/crates/story/src/table_story.rs @@ -189,6 +189,7 @@ struct StockTableDelegate { loading: bool, lazy_load: bool, full_loading: bool, + clicked_row: Option, eof: bool, visible_rows: Range, visible_cols: Range, @@ -202,6 +203,7 @@ impl StockTableDelegate { size: Size::default(), stocks: random_stocks(size), lazy_load: false, + clicked_row: None, columns: vec![ Column::new("id", "ID") .width(60.) @@ -354,7 +356,12 @@ impl TableDelegate for StockTableDelegate { &self.columns[col_ix] } - fn render_th(&self, col_ix: usize, _: &mut Window, _: &mut App) -> impl IntoElement { + fn render_th( + &mut self, + col_ix: usize, + _: &mut Window, + _: &mut Context>, + ) -> impl IntoElement { let col = self.columns.get(col_ix).unwrap(); div() @@ -368,11 +375,11 @@ impl TableDelegate for StockTableDelegate { } fn context_menu( - &self, + &mut self, row_ix: usize, menu: PopupMenu, _window: &mut Window, - _cx: &mut App, + _: &mut Context>, ) -> PopupMenu { menu.menu( format!("Selected Row: {}", row_ix), @@ -385,13 +392,23 @@ impl TableDelegate for StockTableDelegate { .menu("Size XSmall", Box::new(ChangeSize(Size::XSmall))) } - fn render_tr(&self, row_ix: usize, _: &mut Window, _: &mut App) -> Stateful
{ - div().id(row_ix).on_click(|ev: &ClickEvent, _, _| { - println!( - "You have clicked row with secondary: {}", - ev.modifiers().secondary() - ) - }) + fn render_tr( + &mut self, + row_ix: usize, + _: &mut Window, + cx: &mut Context>, + ) -> Stateful
{ + div() + .id(row_ix) + .on_click(cx.listener(move |table, ev: &ClickEvent, _window, cx| { + println!( + "You have clicked row with secondary: {}", + ev.modifiers().secondary() + ); + + table.delegate_mut().clicked_row = Some(row_ix); + cx.notify(); + })) } /// NOTE: Performance metrics @@ -403,11 +420,11 @@ impl TableDelegate for StockTableDelegate { /// /// If we improve the td rendering, we can reduce the time to render the full table cells. fn render_td( - &self, + &mut self, row_ix: usize, col_ix: usize, _: &mut Window, - cx: &mut App, + cx: &mut Context>, ) -> impl IntoElement { let stock = self.stocks.get(row_ix).unwrap(); let col = self.columns.get(col_ix).unwrap(); diff --git a/crates/ui/src/table/delegate.rs b/crates/ui/src/table/delegate.rs index e0b129e0..14518669 100644 --- a/crates/ui/src/table/delegate.rs +++ b/crates/ui/src/table/delegate.rs @@ -1,15 +1,14 @@ use std::ops::Range; use gpui::{ - div, App, Context, Div, InteractiveElement as _, IntoElement, ParentElement as _, Stateful, - Styled as _, Window, + App, Context, Div, InteractiveElement as _, IntoElement, ParentElement as _, Stateful, + Styled as _, Window, div, }; use crate::{ - h_flex, + ActiveTheme as _, Icon, IconName, Size, h_flex, menu::PopupMenu, - table::{loading::Loading, Column, ColumnSort, TableState}, - ActiveTheme as _, Icon, IconName, Size, + table::{Column, ColumnSort, TableState, loading::Loading}, }; /// A delegate trait for providing data and rendering for a table. @@ -37,35 +36,45 @@ pub trait TableDelegate: Sized + 'static { } /// Render the header cell at the given column index, default to the column name. - fn render_th(&self, col_ix: usize, window: &mut Window, cx: &mut App) -> impl IntoElement { + fn render_th( + &mut self, + col_ix: usize, + window: &mut Window, + cx: &mut Context>, + ) -> impl IntoElement { div() .size_full() .child(self.column(col_ix, cx).name.clone()) } /// Render the row at the given row and column. - fn render_tr(&self, row_ix: usize, window: &mut Window, cx: &mut App) -> Stateful
{ + fn render_tr( + &mut self, + row_ix: usize, + window: &mut Window, + cx: &mut Context>, + ) -> Stateful
{ h_flex().id(("row", row_ix)) } /// Render the context menu for the row at the given row index. fn context_menu( - &self, + &mut self, row_ix: usize, menu: PopupMenu, window: &mut Window, - cx: &mut App, + cx: &mut Context>, ) -> PopupMenu { menu } /// Render cell at the given row and column. fn render_td( - &self, + &mut self, row_ix: usize, col_ix: usize, window: &mut Window, - cx: &mut App, + cx: &mut Context>, ) -> impl IntoElement; /// Move the column at the given `col_ix` to insert before the column at the given `to_ix`. @@ -79,7 +88,11 @@ pub trait TableDelegate: Sized + 'static { } /// Return a Element to show when table is empty. - fn render_empty(&self, window: &mut Window, cx: &mut App) -> impl IntoElement { + fn render_empty( + &mut self, + window: &mut Window, + cx: &mut Context>, + ) -> impl IntoElement { h_flex() .size_full() .justify_center() @@ -96,7 +109,12 @@ pub trait TableDelegate: Sized + 'static { /// Return a Element to show when table is loading, default is built-in Skeleton loading view. /// /// The size is the size of the Table. - fn render_loading(&self, size: Size, window: &mut Window, cx: &mut App) -> impl IntoElement { + fn render_loading( + &mut self, + size: Size, + window: &mut Window, + cx: &mut Context>, + ) -> impl IntoElement { Loading::new().size(size) } @@ -125,7 +143,11 @@ pub trait TableDelegate: Sized + 'static { fn load_more(&mut self, window: &mut Window, cx: &mut Context>) {} /// Render the last empty column, default to empty. - fn render_last_empty_col(&self, window: &mut Window, cx: &mut App) -> impl IntoElement { + fn render_last_empty_col( + &mut self, + window: &mut Window, + cx: &mut Context>, + ) -> impl IntoElement { h_flex().w_3().h_full().flex_shrink_0() } diff --git a/crates/ui/src/table/state.rs b/crates/ui/src/table/state.rs index eb4343f5..047c64bf 100644 --- a/crates/ui/src/table/state.rs +++ b/crates/ui/src/table/state.rs @@ -788,7 +788,7 @@ where /// The children must be one by one items. /// Because the horizontal scroll handle will use the child_item_bounds to /// calculate the item position for itself's `scroll_to_item` method. - fn render_th(&self, col_ix: usize, window: &mut Window, cx: &mut Context) -> Div { + fn render_th(&mut self, col_ix: usize, window: &mut Window, cx: &mut Context) -> Div { let entity_id = cx.entity_id(); let col_group = self.col_groups.get(col_ix).expect("BUG: invalid col index"); @@ -896,7 +896,8 @@ where .bg(cx.theme().table_head) .children( self.col_groups - .iter() + .clone() + .into_iter() .filter(|col| col.column.fixed == Some(ColumnFixed::Left)) .enumerate() .map(|(col_ix, _)| self.render_th(col_ix, window, cx)), @@ -939,7 +940,8 @@ where .relative() .children( self.col_groups - .iter() + .clone() + .into_iter() .skip(left_columns_count) .enumerate() .map(|(col_ix, _)| { @@ -1302,7 +1304,7 @@ where move |this, window: &mut Window, cx: &mut Context| { if let Some(row_ix) = view.read(cx).right_clicked_row { view.update(cx, |menu, cx| { - menu.delegate().context_menu(row_ix, this, window, cx) + menu.delegate_mut().context_menu(row_ix, this, window, cx) }) } else { this