diff --git a/gpui/src/elements/mouse_event_handler.rs b/gpui/src/elements/mouse_event_handler.rs index 89f7ba87e63d722a33afdd827ec52942ebb903e8..aed9779f81a21b2e7794ba93ac51612f0ade865c 100644 --- a/gpui/src/elements/mouse_event_handler.rs +++ b/gpui/src/elements/mouse_event_handler.rs @@ -8,6 +8,7 @@ use serde_json::json; pub struct MouseEventHandler { state: ValueHandle, child: ElementBox, + click_handler: Option>, } #[derive(Clone, Copy, Debug, Default)] @@ -28,8 +29,14 @@ impl MouseEventHandler { Self { state: state_handle, child, + click_handler: None, } } + + pub fn on_click(mut self, handler: impl FnMut(&mut EventContext) + 'static) -> Self { + self.click_handler = Some(Box::new(handler)); + self + } } impl Element for MouseEventHandler { @@ -70,6 +77,8 @@ impl Element for MouseEventHandler { _: &mut Self::PaintState, ctx: &mut EventContext, ) -> bool { + let click_handler = self.click_handler.as_mut(); + let handled_in_child = self.child.dispatch_event(event, ctx); self.state.update(ctx.app, |state| match event { @@ -92,10 +101,15 @@ impl Element for MouseEventHandler { handled_in_child } } - Event::LeftMouseUp { .. } => { + Event::LeftMouseUp { position, .. } => { if !handled_in_child && state.clicked { state.clicked = false; ctx.notify(); + if let Some(handler) = click_handler { + if bounds.contains_point(*position) { + handler(ctx); + } + } true } else { handled_in_child diff --git a/zed/src/workspace/pane.rs b/zed/src/workspace/pane.rs index 9b5fae6ad963ead5aac0e9ccf98bb2522aaad79b..f17b439d013c07868cab0c75f6ba1d30afb1a755 100644 --- a/zed/src/workspace/pane.rs +++ b/zed/src/workspace/pane.rs @@ -25,6 +25,12 @@ pub fn init(app: &mut MutableAppContext) { app.add_action("pane:close_active_item", |pane: &mut Pane, _: &(), ctx| { pane.close_active_item(ctx); }); + app.add_action( + "pane:close_item", + |pane: &mut Pane, item_id: &usize, ctx| { + pane.close_item(*item_id, ctx); + }, + ); app.add_action("pane:split_up", |pane: &mut Pane, _: &(), ctx| { pane.split(SplitDirection::Up, ctx); }); @@ -155,15 +161,17 @@ impl Pane { pub fn close_active_item(&mut self, ctx: &mut ViewContext) { if !self.items.is_empty() { - self.items.remove(self.active_item); - if self.active_item >= self.items.len() { - self.active_item = self.items.len().saturating_sub(1); - } - ctx.notify(); + self.close_item(self.items[self.active_item].id(), ctx) } + } + + pub fn close_item(&mut self, item_id: usize, ctx: &mut ViewContext) { + self.items.retain(|item| item.id() != item_id); + self.active_item = cmp::min(self.active_item, self.items.len().saturating_sub(1)); if self.items.is_empty() { ctx.emit(Event::Remove); } + ctx.notify(); } fn focus_active_item(&mut self, ctx: &mut ViewContext) { @@ -316,6 +324,7 @@ impl Pane { icon.boxed() } }) + .on_click(move |ctx| ctx.dispatch_action("pane:close_item", item_id)) .named("close-tab-icon") } else { let diameter = 8.;