table: Binding popup menu on the table not on row for avoid render it on each rows. (#528)

- Add `TableEvent::DoubleClickedRow` to emit double clicked row event to
table.
This commit is contained in:
Jason Lee 2025-01-03 18:10:07 +08:00 committed by GitHub
parent 5be03543dd
commit 99e51288e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 26 deletions

View file

@ -24,7 +24,10 @@ use ui::{
#[derive(Clone, PartialEq, Eq, Deserialize)] #[derive(Clone, PartialEq, Eq, Deserialize)]
struct ChangeSize(Size); struct ChangeSize(Size);
impl_actions!(table_story, [ChangeSize]); #[derive(Clone, PartialEq, Eq, Deserialize)]
struct OpenDetail(usize);
impl_actions!(table_story, [ChangeSize, OpenDetail]);
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
struct Stock { struct Stock {
@ -349,11 +352,16 @@ impl TableDelegate for StockTableDelegate {
} }
} }
fn context_menu(&self, _: usize, menu: PopupMenu, _: &WindowContext) -> PopupMenu { fn context_menu(&self, row_ix: usize, menu: PopupMenu, _: &WindowContext) -> PopupMenu {
menu.menu("Size Large", Box::new(ChangeSize(Size::Large))) menu.menu(
.menu("Size Medium", Box::new(ChangeSize(Size::Medium))) format!("Selected Row: {}", row_ix),
.menu("Size Small", Box::new(ChangeSize(Size::Small))) Box::new(OpenDetail(row_ix)),
.menu("Size XSmall", Box::new(ChangeSize(Size::XSmall))) )
.separator()
.menu("Size Large", Box::new(ChangeSize(Size::Large)))
.menu("Size Medium", Box::new(ChangeSize(Size::Medium)))
.menu("Size Small", Box::new(ChangeSize(Size::Small)))
.menu("Size XSmall", Box::new(ChangeSize(Size::XSmall)))
} }
fn render_td( fn render_td(
@ -674,6 +682,7 @@ impl TableStory {
println!("Col widths changed: {:?}", col_widths) println!("Col widths changed: {:?}", col_widths)
} }
TableEvent::SelectCol(ix) => println!("Select col: {}", ix), TableEvent::SelectCol(ix) => println!("Select col: {}", ix),
TableEvent::DoubleClickedRow(ix) => println!("Double clicked row: {}", ix),
TableEvent::SelectRow(ix) => println!("Select row: {}", ix), TableEvent::SelectRow(ix) => println!("Select row: {}", ix),
TableEvent::MoveCol(origin_idx, target_idx) => { TableEvent::MoveCol(origin_idx, target_idx) => {
println!("Move col index: {} -> {}", origin_idx, target_idx); println!("Move col index: {} -> {}", origin_idx, target_idx);

View file

@ -13,8 +13,8 @@ use crate::{
use gpui::{ use gpui::{
actions, canvas, deferred, div, prelude::FluentBuilder, px, uniform_list, AppContext, Axis, actions, canvas, deferred, div, prelude::FluentBuilder, px, uniform_list, AppContext, Axis,
Bounds, Div, DragMoveEvent, Edges, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, Bounds, Div, DragMoveEvent, Edges, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
InteractiveElement, IntoElement, KeyBinding, ListSizingBehavior, MouseButton, ParentElement, InteractiveElement, IntoElement, KeyBinding, ListSizingBehavior, MouseButton, MouseDownEvent,
Pixels, Point, Render, ScrollHandle, ScrollStrategy, SharedString, Stateful, ParentElement, Pixels, Point, Render, ScrollHandle, ScrollStrategy, SharedString, Stateful,
StatefulInteractiveElement as _, Styled, UniformListScrollHandle, ViewContext, StatefulInteractiveElement as _, Styled, UniformListScrollHandle, ViewContext,
VisualContext as _, WindowContext, VisualContext as _, WindowContext,
}; };
@ -102,7 +102,10 @@ enum SelectionState {
#[derive(Clone)] #[derive(Clone)]
pub enum TableEvent { pub enum TableEvent {
/// Single click or move to selected row.
SelectRow(usize), SelectRow(usize),
/// Double click on the row.
DoubleClickedRow(usize),
SelectCol(usize), SelectCol(usize),
ColWidthsChanged(Vec<Pixels>), ColWidthsChanged(Vec<Pixels>),
MoveCol(usize, usize), MoveCol(usize, usize),
@ -407,16 +410,15 @@ where
cx.notify(); cx.notify();
} }
fn on_row_click( fn on_row_click(&mut self, ev: &MouseDownEvent, row_ix: usize, cx: &mut ViewContext<Self>) {
&mut self, if ev.button == MouseButton::Right {
mouse_button: MouseButton,
row_ix: usize,
cx: &mut ViewContext<Self>,
) {
if mouse_button == MouseButton::Right {
self.right_clicked_row = Some(row_ix); self.right_clicked_row = Some(row_ix);
} else { } else {
self.set_selected_row(row_ix, cx) self.set_selected_row(row_ix, cx);
if ev.click_count == 2 {
cx.emit(TableEvent::DoubleClickedRow(row_ix));
}
} }
} }
@ -987,12 +989,6 @@ where
if row_ix < rows_count { if row_ix < rows_count {
self.delegate self.delegate
.render_tr(row_ix, cx) .render_tr(row_ix, cx)
.context_menu({
let view = view.clone();
move |this, cx: &mut ViewContext<PopupMenu>| {
view.read(cx).delegate.context_menu(row_ix, this, cx)
}
})
.w_full() .w_full()
.h(self.size.table_row_height()) .h(self.size.table_row_height())
.border_b_1() .border_b_1()
@ -1084,14 +1080,14 @@ where
}) })
.on_mouse_down( .on_mouse_down(
MouseButton::Left, MouseButton::Left,
cx.listener(move |this, _, cx| { cx.listener(move |this, ev, cx| {
this.on_row_click(MouseButton::Left, row_ix, cx); this.on_row_click(ev, row_ix, cx);
}), }),
) )
.on_mouse_down( .on_mouse_down(
MouseButton::Right, MouseButton::Right,
cx.listener(move |this, _, cx| { cx.listener(move |this, ev, cx| {
this.on_row_click(MouseButton::Right, row_ix, cx); this.on_row_click(ev, row_ix, cx);
}), }),
) )
} else { } else {
@ -1184,6 +1180,16 @@ where
.size_full() .size_full()
.overflow_hidden() .overflow_hidden()
.child(self.render_table_head(left_cols_count, cx)) .child(self.render_table_head(left_cols_count, cx))
.context_menu({
let view = view.clone();
move |this, cx: &mut ViewContext<PopupMenu>| {
if let Some(row_ix) = view.read(cx).right_clicked_row {
view.read(cx).delegate.context_menu(row_ix, this, cx)
} else {
this
}
}
})
.map(|this| { .map(|this| {
if rows_count == 0 { if rows_count == 0 {
this.child(div().size_full().child(self.delegate.render_empty(cx))) this.child(div().size_full().child(self.delegate.render_empty(cx)))