From 96cc6d5ce554e2c0a0cd0ca876b1397270b7338e Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 3 Aug 2022 16:47:41 -0700 Subject: [PATCH] Added icons to context menu --- crates/context_menu/src/context_menu.rs | 84 +++++++++++++++++------ crates/editor/src/mouse_context_menu.rs | 9 +-- crates/project_panel/src/project_panel.rs | 18 ++--- crates/theme/src/theme.rs | 2 + crates/workspace/src/pane.rs | 22 +++--- styles/src/styleTree/contextMenu.ts | 2 + 6 files changed, 93 insertions(+), 44 deletions(-) diff --git a/crates/context_menu/src/context_menu.rs b/crates/context_menu/src/context_menu.rs index 53f6bfe587..e66388ecd1 100644 --- a/crates/context_menu/src/context_menu.rs +++ b/crates/context_menu/src/context_menu.rs @@ -26,15 +26,17 @@ pub enum ContextMenuItem { Item { label: String, action: Box, + icon: Option, }, Separator, } impl ContextMenuItem { - pub fn item(label: impl ToString, action: impl 'static + Action) -> Self { + pub fn item(label: impl ToString, icon: Option<&str>, action: impl 'static + Action) -> Self { Self::Item { label: label.to_string(), action: Box::new(action), + icon: icon.map(|item| item.to_string()), } } @@ -254,14 +256,31 @@ impl ContextMenu { Flex::column() .with_children(self.items.iter().enumerate().map(|(ix, item)| { match item { - ContextMenuItem::Item { label, .. } => { + ContextMenuItem::Item { label, icon, .. } => { let style = style .item .style_for(Default::default(), Some(ix) == self.selected_index); - Label::new(label.to_string(), style.label.clone()) - .contained() - .with_style(style.container) - .boxed() + let mut line = Flex::row(); + if let Some(_) = icon { + line.add_child( + Empty::new() + .constrained() + .with_width(style.icon_width) + .boxed(), + ); + } + line.add_child( + Label::new(label.to_string(), style.label.clone()) + .contained() + .with_style(style.container) + .with_margin_left(if icon.is_some() { + style.icon_spacing + } else { + 0. + }) + .boxed(), + ); + line.boxed() } ContextMenuItem::Separator => Empty::new() .collapsed() @@ -314,27 +333,50 @@ impl ContextMenu { Flex::column() .with_children(self.items.iter().enumerate().map(|(ix, item)| { match item { - ContextMenuItem::Item { label, action } => { + ContextMenuItem::Item { + label, + action, + icon, + } => { let action = action.boxed_clone(); MouseEventHandler::new::(ix, cx, |state, _| { let style = style.item.style_for(state, Some(ix) == self.selected_index); - Flex::row() - .with_child( - Label::new(label.to_string(), style.label.clone()).boxed(), + + let mut line = Flex::row(); + if let Some(icon_file) = icon { + line.add_child( + Svg::new(format!("icons/{}", icon_file)) + .with_color(style.label.color) + .constrained() + .with_width(style.icon_width) + .aligned() + .boxed(), ) - .with_child({ - KeystrokeLabel::new( - action.boxed_clone(), - style.keystroke.container, - style.keystroke.text.clone(), - ) - .flex_float() - .boxed() - }) - .contained() - .with_style(style.container) + } + + line.with_child( + Label::new(label.to_string(), style.label.clone()) + .contained() + .with_margin_left(if icon.is_some() { + style.icon_spacing + } else { + 0. + }) + .boxed(), + ) + .with_child({ + KeystrokeLabel::new( + action.boxed_clone(), + style.keystroke.container, + style.keystroke.text.clone(), + ) + .flex_float() .boxed() + }) + .contained() + .with_style(style.container) + .boxed() }) .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, cx| { diff --git a/crates/editor/src/mouse_context_menu.rs b/crates/editor/src/mouse_context_menu.rs index 513a9ed99c..d96deb359d 100644 --- a/crates/editor/src/mouse_context_menu.rs +++ b/crates/editor/src/mouse_context_menu.rs @@ -48,12 +48,13 @@ pub fn deploy_context_menu( menu.show( position, vec![ - ContextMenuItem::item("Rename Symbol", Rename), - ContextMenuItem::item("Go To Definition", GoToDefinition), - ContextMenuItem::item("Go To Type Definition", GoToTypeDefinition), - ContextMenuItem::item("Find All References", FindAllReferences), + ContextMenuItem::item("Rename Symbol", None, Rename), + ContextMenuItem::item("Go To Definition", None, GoToDefinition), + ContextMenuItem::item("Go To Type Definition", None, GoToTypeDefinition), + ContextMenuItem::item("Find All References", None, FindAllReferences), ContextMenuItem::item( "Code Actions", + None, ToggleCodeActions { deployed_from_indicator: false, }, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 0a32a8427b..2b5a607bed 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -269,30 +269,32 @@ impl ProjectPanel { if !project.is_remote() { menu_entries.push(ContextMenuItem::item( "Add Folder to Project", + None, workspace::AddFolderToProject, )); if is_root { menu_entries.push(ContextMenuItem::item( "Remove from Project", + None, workspace::RemoveWorktreeFromProject(worktree_id), )); } } - menu_entries.push(ContextMenuItem::item("New File", AddFile)); - menu_entries.push(ContextMenuItem::item("New Folder", AddDirectory)); + menu_entries.push(ContextMenuItem::item("New File", None, AddFile)); + menu_entries.push(ContextMenuItem::item("New Folder", None, AddDirectory)); menu_entries.push(ContextMenuItem::Separator); - menu_entries.push(ContextMenuItem::item("Copy", Copy)); - menu_entries.push(ContextMenuItem::item("Copy Path", CopyPath)); - menu_entries.push(ContextMenuItem::item("Cut", Cut)); + menu_entries.push(ContextMenuItem::item("Copy", None, Copy)); + menu_entries.push(ContextMenuItem::item("Copy Path", None, CopyPath)); + menu_entries.push(ContextMenuItem::item("Cut", None, Cut)); if let Some(clipboard_entry) = self.clipboard_entry { if clipboard_entry.worktree_id() == worktree.id() { - menu_entries.push(ContextMenuItem::item("Paste", Paste)); + menu_entries.push(ContextMenuItem::item("Paste", None, Paste)); } } menu_entries.push(ContextMenuItem::Separator); - menu_entries.push(ContextMenuItem::item("Rename", Rename)); + menu_entries.push(ContextMenuItem::item("Rename", None, Rename)); if !is_root { - menu_entries.push(ContextMenuItem::item("Delete", Delete)); + menu_entries.push(ContextMenuItem::item("Delete", None, Delete)); } } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 349a505a08..1aaeed2d78 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -267,6 +267,8 @@ pub struct ContextMenuItem { pub container: ContainerStyle, pub label: TextStyle, pub keystroke: ContainedText, + pub icon_width: f32, + pub icon_spacing: f32, } #[derive(Debug, Deserialize, Default)] diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 386b151e24..3abd05da26 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -147,7 +147,7 @@ pub struct Pane { autoscroll: bool, nav_history: Rc>, toolbar: ViewHandle, - split_menu: ViewHandle, + context_menu: ViewHandle, } pub struct ItemNavHistory { @@ -203,7 +203,7 @@ impl Pane { pane: handle.clone(), })), toolbar: cx.add_view(|_| Toolbar::new(handle)), - split_menu, + context_menu: split_menu, } } @@ -837,14 +837,14 @@ impl Pane { } fn deploy_split_menu(&mut self, action: &DeploySplitMenu, cx: &mut ViewContext) { - self.split_menu.update(cx, |menu, cx| { + self.context_menu.update(cx, |menu, cx| { menu.show( action.position, vec![ - ContextMenuItem::item("Split Right", SplitRight), - ContextMenuItem::item("Split Left", SplitLeft), - ContextMenuItem::item("Split Up", SplitUp), - ContextMenuItem::item("Split Down", SplitDown), + ContextMenuItem::item("Split Right", None, SplitRight), + ContextMenuItem::item("Split Left", None, SplitLeft), + ContextMenuItem::item("Split Up", None, SplitUp), + ContextMenuItem::item("Split Down", None, SplitDown), ], cx, ); @@ -852,12 +852,12 @@ impl Pane { } fn deploy_new_menu(&mut self, action: &DeployNewMenu, cx: &mut ViewContext) { - self.split_menu.update(cx, |menu, cx| { + self.context_menu.update(cx, |menu, cx| { menu.show( action.position, vec![ - ContextMenuItem::item("New File", NewFile), - ContextMenuItem::item("New Terminal", NewTerminal), + ContextMenuItem::item("New File", Some("circle_info_12.svg"), NewFile), + ContextMenuItem::item("New Terminal", Some("terminal_12.svg"), NewTerminal), ], cx, ); @@ -1204,7 +1204,7 @@ impl View for Pane { }) .boxed(), ) - .with_child(ChildView::new(&self.split_menu).boxed()) + .with_child(ChildView::new(&self.context_menu).boxed()) .named("pane") } diff --git a/styles/src/styleTree/contextMenu.ts b/styles/src/styleTree/contextMenu.ts index 0244641ec7..6236c2bc60 100644 --- a/styles/src/styleTree/contextMenu.ts +++ b/styles/src/styleTree/contextMenu.ts @@ -16,6 +16,8 @@ export default function contextMenu(theme: Theme) { border: border(theme, "primary"), keystrokeMargin: 30, item: { + iconSpacing: 8, + iconWidth: 14, padding: { left: 4, right: 4, top: 2, bottom: 2 }, cornerRadius: 6, label: text(theme, "sans", "primary", { size: "sm" }),