diff --git a/crates/auto_update2/src/update_notification.rs b/crates/auto_update2/src/update_notification.rs index d15d82e112..4a2efcf807 100644 --- a/crates/auto_update2/src/update_notification.rs +++ b/crates/auto_update2/src/update_notification.rs @@ -51,6 +51,6 @@ impl UpdateNotification { } pub fn dismiss(&mut self, cx: &mut ViewContext) { - cx.emit(DismissEvent::Dismiss); + cx.emit(DismissEvent); } } diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index 31f2764b11..fee04ec40c 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -161,7 +161,7 @@ impl PickerDelegate for ContactFinderDelegate { fn dismissed(&mut self, cx: &mut ViewContext>) { //cx.emit(PickerEvent::Dismiss); self.parent - .update(cx, |_, cx| cx.emit(DismissEvent::Dismiss)) + .update(cx, |_, cx| cx.emit(DismissEvent)) .log_err(); } diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 75e98bfa25..f9b58b1d56 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -269,7 +269,7 @@ impl PickerDelegate for CommandPaletteDelegate { fn dismissed(&mut self, cx: &mut ViewContext>) { self.command_palette - .update(cx, |_, cx| cx.emit(DismissEvent::Dismiss)) + .update(cx, |_, cx| cx.emit(DismissEvent)) .log_err(); } diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 2f7b26dfb5..a24da580eb 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -687,9 +687,7 @@ impl PickerDelegate for FileFinderDelegate { .log_err(); } } - finder - .update(&mut cx, |_, cx| cx.emit(DismissEvent::Dismiss)) - .ok()?; + finder.update(&mut cx, |_, cx| cx.emit(DismissEvent)).ok()?; Some(()) }) @@ -700,7 +698,7 @@ impl PickerDelegate for FileFinderDelegate { fn dismissed(&mut self, cx: &mut ViewContext>) { self.file_finder - .update(cx, |_, cx| cx.emit(DismissEvent::Dismiss)) + .update(cx, |_, cx| cx.emit(DismissEvent)) .log_err(); } diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index c734281d22..5ad95c1f6e 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -90,7 +90,7 @@ impl GoToLine { ) { match event { // todo!() this isn't working... - editor::EditorEvent::Blurred => cx.emit(DismissEvent::Dismiss), + editor::EditorEvent::Blurred => cx.emit(DismissEvent), editor::EditorEvent::BufferEdited { .. } => self.highlight_current_line(cx), _ => {} } @@ -125,7 +125,7 @@ impl GoToLine { } fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { - cx.emit(DismissEvent::Dismiss); + cx.emit(DismissEvent); } fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { @@ -142,7 +142,7 @@ impl GoToLine { self.prev_scroll_position.take(); } - cx.emit(DismissEvent::Dismiss); + cx.emit(DismissEvent); } } diff --git a/crates/gpui2/src/app/async_context.rs b/crates/gpui2/src/app/async_context.rs index 11420bee69..92ccc118f1 100644 --- a/crates/gpui2/src/app/async_context.rs +++ b/crates/gpui2/src/app/async_context.rs @@ -325,8 +325,7 @@ impl VisualContext for AsyncWindowContext { where V: crate::ManagedView, { - self.window.update(self, |_, cx| { - view.update(cx, |_, cx| cx.emit(DismissEvent::Dismiss)) - }) + self.window + .update(self, |_, cx| view.update(cx, |_, cx| cx.emit(DismissEvent))) } } diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index 71bc8e3d81..9637720a67 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -611,7 +611,7 @@ impl<'a> VisualContext for VisualTestContext<'a> { { self.window .update(self.cx, |_, cx| { - view.update(cx, |_, cx| cx.emit(crate::DismissEvent::Dismiss)) + view.update(cx, |_, cx| cx.emit(crate::DismissEvent)) }) .unwrap() } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index b02005aa78..507c46d067 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -197,9 +197,7 @@ pub trait ManagedView: FocusableView + EventEmitter {} impl> ManagedView for M {} -pub enum DismissEvent { - Dismiss, -} +pub struct DismissEvent; // Holds the state for a specific window. pub struct Window { @@ -1482,13 +1480,15 @@ impl<'a> WindowContext<'a> { } } - pub fn constructor_for( + pub fn handler_for( &self, view: &View, - f: impl Fn(&mut V, &mut ViewContext) -> R + 'static, - ) -> impl Fn(&mut WindowContext) -> R + 'static { - let view = view.clone(); - move |cx: &mut WindowContext| view.update(cx, |view, cx| f(view, cx)) + f: impl Fn(&mut V, &mut ViewContext) + 'static, + ) -> impl Fn(&mut WindowContext) { + let view = view.downgrade(); + move |cx: &mut WindowContext| { + view.update(cx, |view, cx| f(view, cx)).ok(); + } } //========== ELEMENT RELATED FUNCTIONS =========== @@ -1699,7 +1699,7 @@ impl VisualContext for WindowContext<'_> { where V: ManagedView, { - self.update_view(view, |_, cx| cx.emit(DismissEvent::Dismiss)) + self.update_view(view, |_, cx| cx.emit(DismissEvent)) } } @@ -2386,7 +2386,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { where V: ManagedView, { - self.defer(|_, cx| cx.emit(DismissEvent::Dismiss)) + self.defer(|_, cx| cx.emit(DismissEvent)) } pub fn listener( diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 359c5a8e6b..e4846af76c 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -8,10 +8,11 @@ use file_associations::FileAssociations; use anyhow::{anyhow, Result}; use gpui::{ - actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext, - ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement, - Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, Stateful, Styled, - Task, UniformListScrollHandle, View, ViewContext, VisualContext as _, WeakView, WindowContext, + actions, div, overlay, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext, + ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, Focusable, FocusableView, + InteractiveElement, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, + PromptLevel, Render, Stateful, Styled, Subscription, Task, UniformListScrollHandle, View, + ViewContext, VisualContext as _, WeakView, WindowContext, }; use menu::{Confirm, SelectNext, SelectPrev}; use project::{ @@ -29,7 +30,7 @@ use std::{ sync::Arc, }; use theme::ActiveTheme as _; -use ui::{v_stack, IconElement, Label, ListItem}; +use ui::{v_stack, ContextMenu, IconElement, Label, ListItem}; use unicase::UniCase; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -49,6 +50,7 @@ pub struct ProjectPanel { last_worktree_root_id: Option, expanded_dir_ids: HashMap>, selection: Option, + context_menu: Option<(View, Point, Subscription)>, edit_state: Option, filename_editor: View, clipboard_entry: Option, @@ -231,6 +233,7 @@ impl ProjectPanel { expanded_dir_ids: Default::default(), selection: None, edit_state: None, + context_menu: None, filename_editor, clipboard_entry: None, // context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)), @@ -366,80 +369,93 @@ impl ProjectPanel { fn deploy_context_menu( &mut self, - _position: Point, - _entry_id: ProjectEntryId, - _cx: &mut ViewContext, + position: Point, + entry_id: ProjectEntryId, + cx: &mut ViewContext, ) { - // todo!() - // let project = self.project.read(cx); + let this = cx.view().clone(); + let project = self.project.read(cx); - // let worktree_id = if let Some(id) = project.worktree_id_for_entry(entry_id, cx) { - // id - // } else { - // return; - // }; + let worktree_id = if let Some(id) = project.worktree_id_for_entry(entry_id, cx) { + id + } else { + return; + }; - // self.selection = Some(Selection { - // worktree_id, - // entry_id, - // }); + self.selection = Some(Selection { + worktree_id, + entry_id, + }); - // let mut menu_entries = Vec::new(); - // if let Some((worktree, entry)) = self.selected_entry(cx) { - // let is_root = Some(entry) == worktree.root_entry(); - // if !project.is_remote() { - // menu_entries.push(ContextMenuItem::action( - // "Add Folder to Project", - // workspace::AddFolderToProject, - // )); - // if is_root { - // let project = self.project.clone(); - // menu_entries.push(ContextMenuItem::handler("Remove from Project", move |cx| { - // project.update(cx, |project, cx| project.remove_worktree(worktree_id, cx)); - // })); - // } - // } - // menu_entries.push(ContextMenuItem::action("New File", NewFile)); - // menu_entries.push(ContextMenuItem::action("New Folder", NewDirectory)); - // menu_entries.push(ContextMenuItem::Separator); - // menu_entries.push(ContextMenuItem::action("Cut", Cut)); - // menu_entries.push(ContextMenuItem::action("Copy", Copy)); - // if let Some(clipboard_entry) = self.clipboard_entry { - // if clipboard_entry.worktree_id() == worktree.id() { - // menu_entries.push(ContextMenuItem::action("Paste", Paste)); - // } - // } - // menu_entries.push(ContextMenuItem::Separator); - // menu_entries.push(ContextMenuItem::action("Copy Path", CopyPath)); - // menu_entries.push(ContextMenuItem::action( - // "Copy Relative Path", - // CopyRelativePath, - // )); + if let Some((worktree, entry)) = self.selected_entry(cx) { + let is_root = Some(entry) == worktree.root_entry(); + let is_dir = entry.is_dir(); + let worktree_id = worktree.id(); + let is_local = project.is_local(); - // if entry.is_dir() { - // menu_entries.push(ContextMenuItem::Separator); - // } - // menu_entries.push(ContextMenuItem::action("Reveal in Finder", RevealInFinder)); - // if entry.is_dir() { - // menu_entries.push(ContextMenuItem::action("Open in Terminal", OpenInTerminal)); - // menu_entries.push(ContextMenuItem::action( - // "Search Inside", - // NewSearchInDirectory, - // )); - // } + let context_menu = ContextMenu::build(cx, |mut menu, cx| { + if is_local { + menu = menu.action( + "Add Folder to Project", + Box::new(workspace::AddFolderToProject), + cx, + ); + if is_root { + menu = menu.entry( + "Remove from Project", + cx.handler_for(&this, move |this, cx| { + this.project.update(cx, |project, cx| { + project.remove_worktree(worktree_id, cx) + }); + }), + ); + } + } - // menu_entries.push(ContextMenuItem::Separator); - // menu_entries.push(ContextMenuItem::action("Rename", Rename)); - // if !is_root { - // menu_entries.push(ContextMenuItem::action("Delete", Delete)); - // } - // } + menu = menu + .action("New File", Box::new(NewFile), cx) + .action("New Folder", Box::new(NewDirectory), cx) + .separator() + .action("Cut", Box::new(Cut), cx) + .action("Copy", Box::new(Copy), cx); - // // self.context_menu.update(cx, |menu, cx| { - // // menu.show(position, AnchorCorner::TopLeft, menu_entries, cx); - // // }); + if let Some(clipboard_entry) = self.clipboard_entry { + if clipboard_entry.worktree_id() == worktree_id { + menu = menu.action("Paste", Box::new(Paste), cx); + } + } - // cx.notify(); + menu = menu + .separator() + .action("Copy Path", Box::new(CopyPath), cx) + .action("Copy Relative Path", Box::new(CopyRelativePath), cx) + .separator() + .action("Reveal in Finder", Box::new(RevealInFinder), cx); + + if is_dir { + menu = menu + .action("Open in Terminal", Box::new(OpenInTerminal), cx) + .action("Search Inside", Box::new(NewSearchInDirectory), cx) + } + + menu = menu.separator().action("Rename", Box::new(Rename), cx); + + if !is_root { + menu = menu.action("Delete", Box::new(Delete), cx); + } + + menu + }); + + cx.focus_view(&context_menu); + let subscription = cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| { + this.context_menu.take(); + cx.notify(); + }); + self.context_menu = Some((context_menu, position, subscription)); + } + + cx.notify(); } fn expand_selected_entry(&mut self, _: &ExpandSelectedEntry, cx: &mut ViewContext) { @@ -643,7 +659,6 @@ impl ProjectPanel { } fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { - dbg!("odd"); self.edit_state = None; self.update_visible_entries(None, cx); cx.focus(&self.focus_handle); @@ -1370,7 +1385,7 @@ impl ProjectPanel { }) .child( if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) { - div().w_full().child(editor.clone()) + div().h_full().w_full().child(editor.clone()) } else { div() .text_color(filename_text_color) @@ -1379,6 +1394,9 @@ impl ProjectPanel { .ml_1(), ) .on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| { + if event.down.button == MouseButton::Right { + return; + } if !show_editor { if kind.is_dir() { this.toggle_expanded(entry_id, cx); @@ -1415,6 +1433,7 @@ impl Render for ProjectPanel { div() .id("project-panel") .size_full() + .relative() .key_context("ProjectPanel") .on_action(cx.listener(Self::select_next)) .on_action(cx.listener(Self::select_prev)) @@ -1458,6 +1477,12 @@ impl Render for ProjectPanel { .size_full() .track_scroll(self.list.clone()), ) + .children(self.context_menu.as_ref().map(|(menu, position, _)| { + overlay() + .position(*position) + .anchor(gpui::AnchorCorner::BottomLeft) + .child(menu.clone()) + })) } else { v_stack() .id("empty-project_panel") diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index 9f3ed31388..b007d58c34 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -298,9 +298,12 @@ impl TerminalView { position: gpui::Point, cx: &mut ViewContext, ) { - self.context_menu = Some(ContextMenu::build(cx, |menu, _| { - menu.action("Clear", Box::new(Clear)) - .action("Close", Box::new(CloseActiveItem { save_intent: None })) + self.context_menu = Some(ContextMenu::build(cx, |menu, cx| { + menu.action("Clear", Box::new(Clear), cx).action( + "Close", + Box::new(CloseActiveItem { save_intent: None }), + cx, + ) })); dbg!(&position); // todo!() diff --git a/crates/theme_selector2/src/theme_selector.rs b/crates/theme_selector2/src/theme_selector.rs index ec38f7083c..7b0a0c3d3a 100644 --- a/crates/theme_selector2/src/theme_selector.rs +++ b/crates/theme_selector2/src/theme_selector.rs @@ -177,7 +177,7 @@ impl PickerDelegate for ThemeSelectorDelegate { self.view .update(cx, |_, cx| { - cx.emit(DismissEvent::Dismiss); + cx.emit(DismissEvent); }) .ok(); } diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 8cd519f629..3772fb1bd2 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -1,23 +1,28 @@ -use std::cell::RefCell; -use std::rc::Rc; - -use crate::{prelude::*, v_stack, Label, List}; -use crate::{ListItem, ListSeparator, ListSubHeader}; -use gpui::{ - overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, ClickEvent, DismissEvent, - DispatchPhase, Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId, - ManagedView, MouseButton, MouseDownEvent, Pixels, Point, Render, View, VisualContext, +use crate::{ + h_stack, prelude::*, v_stack, KeyBinding, Label, List, ListItem, ListSeparator, ListSubHeader, }; +use gpui::{ + overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, DismissEvent, DispatchPhase, + Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId, ManagedView, MouseButton, + MouseDownEvent, Pixels, Point, Render, View, VisualContext, +}; +use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev}; +use std::{cell::RefCell, rc::Rc}; pub enum ContextMenuItem { Separator, Header(SharedString), - Entry(SharedString, Rc), + Entry { + label: SharedString, + handler: Rc, + key_binding: Option, + }, } pub struct ContextMenu { items: Vec, focus_handle: FocusHandle, + selected_index: Option, } impl FocusableView for ContextMenu { @@ -39,6 +44,7 @@ impl ContextMenu { Self { items: Default::default(), focus_handle: cx.focus_handle(), + selected_index: None, }, cx, ) @@ -58,27 +64,90 @@ impl ContextMenu { pub fn entry( mut self, label: impl Into, - on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static, + on_click: impl Fn(&mut WindowContext) + 'static, ) -> Self { - self.items - .push(ContextMenuItem::Entry(label.into(), Rc::new(on_click))); + self.items.push(ContextMenuItem::Entry { + label: label.into(), + handler: Rc::new(on_click), + key_binding: None, + }); self } - pub fn action(self, label: impl Into, action: Box) -> Self { - // todo: add the keybindings to the list entry - self.entry(label.into(), move |_, cx| { - cx.dispatch_action(action.boxed_clone()) - }) + pub fn action( + mut self, + label: impl Into, + action: Box, + cx: &mut WindowContext, + ) -> Self { + self.items.push(ContextMenuItem::Entry { + label: label.into(), + key_binding: KeyBinding::for_action(&*action, cx), + handler: Rc::new(move |cx| cx.dispatch_action(action.boxed_clone())), + }); + self } pub fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { - // todo!() - cx.emit(DismissEvent::Dismiss); + if let Some(ContextMenuItem::Entry { handler, .. }) = + self.selected_index.and_then(|ix| self.items.get(ix)) + { + (handler)(cx) + } + cx.emit(DismissEvent); } pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { - cx.emit(DismissEvent::Dismiss); + cx.emit(DismissEvent); + } + + fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext) { + self.selected_index = self.items.iter().position(|item| item.is_selectable()); + cx.notify(); + } + + fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext) { + for (ix, item) in self.items.iter().enumerate().rev() { + if item.is_selectable() { + self.selected_index = Some(ix); + cx.notify(); + break; + } + } + } + + fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext) { + if let Some(ix) = self.selected_index { + for (ix, item) in self.items.iter().enumerate().skip(ix + 1) { + if item.is_selectable() { + self.selected_index = Some(ix); + cx.notify(); + break; + } + } + } else { + self.select_first(&Default::default(), cx); + } + } + + pub fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext) { + if let Some(ix) = self.selected_index { + for (ix, item) in self.items.iter().enumerate().take(ix).rev() { + if item.is_selectable() { + self.selected_index = Some(ix); + cx.notify(); + break; + } + } + } else { + self.select_last(&Default::default(), cx); + } + } +} + +impl ContextMenuItem { + fn is_selectable(&self) -> bool { + matches!(self, Self::Entry { .. }) } } @@ -90,38 +159,51 @@ impl Render for ContextMenu { v_stack() .min_w(px(200.)) .track_focus(&self.focus_handle) - .on_mouse_down_out( - cx.listener(|this: &mut Self, _, cx| this.cancel(&Default::default(), cx)), - ) - // .on_action(ContextMenu::select_first) - // .on_action(ContextMenu::select_last) - // .on_action(ContextMenu::select_next) - // .on_action(ContextMenu::select_prev) + .on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&Default::default(), cx))) + .key_context("menu") + .on_action(cx.listener(ContextMenu::select_first)) + .on_action(cx.listener(ContextMenu::select_last)) + .on_action(cx.listener(ContextMenu::select_next)) + .on_action(cx.listener(ContextMenu::select_prev)) .on_action(cx.listener(ContextMenu::confirm)) .on_action(cx.listener(ContextMenu::cancel)) .flex_none() - // .bg(cx.theme().colors().elevated_surface_background) - // .border() - // .border_color(cx.theme().colors().border) .child( - List::new().children(self.items.iter().map(|item| match item { - ContextMenuItem::Separator => ListSeparator::new().into_any_element(), - ContextMenuItem::Header(header) => { - ListSubHeader::new(header.clone()).into_any_element() - } - ContextMenuItem::Entry(entry, callback) => { - let callback = callback.clone(); - let dismiss = cx.listener(|_, _, cx| cx.emit(DismissEvent::Dismiss)); + List::new().children(self.items.iter().enumerate().map( + |(ix, item)| match item { + ContextMenuItem::Separator => ListSeparator::new().into_any_element(), + ContextMenuItem::Header(header) => { + ListSubHeader::new(header.clone()).into_any_element() + } + ContextMenuItem::Entry { + label: entry, + handler: callback, + key_binding, + } => { + let callback = callback.clone(); + let dismiss = cx.listener(|_, _, cx| cx.emit(DismissEvent)); - ListItem::new(entry.clone()) - .child(Label::new(entry.clone())) - .on_click(move |event, cx| { - callback(event, cx); - dismiss(event, cx) - }) - .into_any_element() - } - })), + ListItem::new(entry.clone()) + .child( + h_stack() + .w_full() + .justify_between() + .child(Label::new(entry.clone())) + .children( + key_binding + .clone() + .map(|binding| div().ml_1().child(binding)), + ), + ) + .selected(Some(ix) == self.selected_index) + .on_click(move |event, cx| { + callback(cx); + dismiss(event, cx) + }) + .into_any_element() + } + }, + )), ), ) } @@ -177,6 +259,7 @@ pub struct MenuHandleState { child_element: Option, menu_element: Option, } + impl Element for MenuHandle { type State = MenuHandleState; @@ -264,11 +347,9 @@ impl Element for MenuHandle { let new_menu = (builder)(cx); let menu2 = menu.clone(); - cx.subscribe(&new_menu, move |_modal, e, cx| match e { - &DismissEvent::Dismiss => { - *menu2.borrow_mut() = None; - cx.notify(); - } + cx.subscribe(&new_menu, move |_modal, _: &DismissEvent, cx| { + *menu2.borrow_mut() = None; + cx.notify(); }) .detach(); cx.focus_view(&new_menu); diff --git a/crates/ui2/src/components/list.rs b/crates/ui2/src/components/list.rs index 6befc1eb81..5cd9c7f709 100644 --- a/crates/ui2/src/components/list.rs +++ b/crates/ui2/src/components/list.rs @@ -374,17 +374,15 @@ impl RenderOnce for List { type Rendered = Div; fn render(self, _cx: &mut WindowContext) -> Self::Rendered { - let list_content = match (self.children.is_empty(), self.toggle) { - (false, _) => div().children(self.children), - (true, Toggle::Toggled(false)) => div(), - (true, _) => div().child(Label::new(self.empty_message.clone()).color(Color::Muted)), - }; - v_stack() .w_full() .py_1() .children(self.header.map(|header| header)) - .child(list_content) + .map(|this| match (self.children.is_empty(), self.toggle) { + (false, _) => this.children(self.children), + (true, Toggle::Toggled(false)) => this, + (true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)), + }) } } diff --git a/crates/ui2/src/components/stories/context_menu.rs b/crates/ui2/src/components/stories/context_menu.rs index 9a8b7efbe6..d5fb94df4f 100644 --- a/crates/ui2/src/components/stories/context_menu.rs +++ b/crates/ui2/src/components/stories/context_menu.rs @@ -10,11 +10,11 @@ fn build_menu(cx: &mut WindowContext, header: impl Into) -> View { - this.dismiss_notification_internal(type_id, id, cx); - } + move |this, handle, event: &DismissEvent, cx| { + this.dismiss_notification_internal(type_id, id, cx); }, ) .detach(); @@ -260,7 +258,7 @@ pub mod simple_message_notification { } pub fn dismiss(&mut self, cx: &mut ViewContext) { - cx.emit(DismissEvent::Dismiss); + cx.emit(DismissEvent); } }