Detailed changes
@@ -26,15 +26,17 @@ pub enum ContextMenuItem {
Item {
label: String,
action: Box<dyn Action>,
+ icon: Option<String>,
},
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::<MenuItem, _, _>(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| {
@@ -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,
},
@@ -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));
}
}
@@ -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)]
@@ -147,7 +147,7 @@ pub struct Pane {
autoscroll: bool,
nav_history: Rc<RefCell<NavHistory>>,
toolbar: ViewHandle<Toolbar>,
- split_menu: ViewHandle<ContextMenu>,
+ context_menu: ViewHandle<ContextMenu>,
}
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>) {
- 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>) {
- 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")
}
@@ -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" }),