Merge pull request #1467 from zed-industries/new-button

Add discoverable 'New' button
This commit is contained in:
Mikayla Maki 2022-08-04 12:02:57 -07:00 committed by GitHub
commit 5a372cecaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 18 deletions

View file

@ -31,7 +31,7 @@
"cmd-n": "workspace::NewFile",
"cmd-shift-n": "workspace::NewWindow",
"cmd-o": "workspace::Open",
"ctrl-`": "terminal::Deploy"
"ctrl-`": "workspace::NewTerminal"
}
},
{
@ -300,7 +300,7 @@
8
],
"cmd-b": "workspace::ToggleLeftSidebar",
"cmd-shift-f": "project_search::Deploy",
"cmd-shift-f": "workspace::NewSearch",
"cmd-k cmd-t": "theme_selector::Toggle",
"cmd-k cmd-s": "zed::OpenKeymap",
"cmd-t": "project_symbols::Toggle",

View file

@ -22,6 +22,7 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ContextMenu::cancel);
}
//
pub enum ContextMenuItem {
Item {
label: String,
@ -258,6 +259,7 @@ impl ContextMenu {
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)
@ -319,9 +321,12 @@ impl ContextMenu {
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(),
Label::new(label.to_string(), style.label.clone())
.contained()
.boxed(),
)
.with_child({
KeystrokeLabel::new(

View file

@ -24,7 +24,7 @@ use workspace::{
Item, ItemHandle, ItemNavHistory, Pane, ToolbarItemLocation, ToolbarItemView, Workspace,
};
actions!(project_search, [Deploy, SearchInNew, ToggleFocus]);
actions!(project_search, [SearchInNew, ToggleFocus]);
#[derive(Default)]
struct ActiveSearches(HashMap<WeakModelHandle<Project>, WeakViewHandle<ProjectSearchView>>);
@ -431,7 +431,11 @@ impl ProjectSearchView {
// Re-activate the most recently activated search or the most recent if it has been closed.
// If no search exists in the workspace, create a new one.
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
fn deploy(
workspace: &mut Workspace,
_: &workspace::NewSearch,
cx: &mut ViewContext<Workspace>,
) {
// Clean up entries for dropped projects
cx.update_global(|state: &mut ActiveSearches, cx| {
state.0.retain(|project, _| project.is_upgradable(cx))

View file

@ -5,17 +5,17 @@ use gpui::{
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, View, ViewContext,
ViewHandle,
};
use workspace::{Item, Workspace};
use crate::TerminalSize;
use project::{LocalWorktree, Project, ProjectPath};
use settings::{Settings, WorkingDirectory};
use smallvec::SmallVec;
use std::path::{Path, PathBuf};
use workspace::{Item, Workspace};
use crate::connected_el::TerminalEl;
actions!(terminal, [Deploy, DeployModal]);
actions!(terminal, [DeployModal]);
//Make terminal view an enum, that can give you views for the error and non-error states
//Take away all the result unwrapping in the current TerminalView by making it 'infallible'
@ -59,7 +59,11 @@ impl Entity for ErrorView {
impl TerminalView {
///Create a new Terminal in the current working directory or the user's home directory
pub fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
pub fn deploy(
workspace: &mut Workspace,
_: &workspace::NewTerminal,
cx: &mut ViewContext<Workspace>,
) {
let strategy = cx
.global::<Settings>()
.terminal_overrides

View file

@ -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)]

View file

@ -1,5 +1,5 @@
use super::{ItemHandle, SplitDirection};
use crate::{toolbar::Toolbar, Item, WeakItemHandle, Workspace};
use crate::{toolbar::Toolbar, Item, NewFile, NewSearch, NewTerminal, WeakItemHandle, Workspace};
use anyhow::Result;
use collections::{HashMap, HashSet, VecDeque};
use context_menu::{ContextMenu, ContextMenuItem};
@ -65,8 +65,13 @@ pub struct DeploySplitMenu {
position: Vector2F,
}
#[derive(Clone, PartialEq)]
pub struct DeployNewMenu {
position: Vector2F,
}
impl_actions!(pane, [GoBack, GoForward, ActivateItem]);
impl_internal_actions!(pane, [CloseItem, DeploySplitMenu]);
impl_internal_actions!(pane, [CloseItem, DeploySplitMenu, DeployNewMenu]);
const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
@ -98,6 +103,7 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(|pane: &mut Pane, _: &SplitRight, cx| pane.split(SplitDirection::Right, cx));
cx.add_action(|pane: &mut Pane, _: &SplitDown, cx| pane.split(SplitDirection::Down, cx));
cx.add_action(Pane::deploy_split_menu);
cx.add_action(Pane::deploy_new_menu);
cx.add_action(|workspace: &mut Workspace, _: &ReopenClosedItem, cx| {
Pane::reopen_closed_item(workspace, cx).detach();
});
@ -141,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 {
@ -182,7 +188,7 @@ pub struct NavigationEntry {
impl Pane {
pub fn new(cx: &mut ViewContext<Self>) -> Self {
let handle = cx.weak_handle();
let split_menu = cx.add_view(|cx| ContextMenu::new(cx));
let context_menu = cx.add_view(|cx| ContextMenu::new(cx));
Self {
items: Vec::new(),
is_active: true,
@ -197,7 +203,7 @@ impl Pane {
pane: handle.clone(),
})),
toolbar: cx.add_view(|_| Toolbar::new(handle)),
split_menu,
context_menu,
}
}
@ -831,7 +837,7 @@ 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![
@ -845,6 +851,20 @@ impl Pane {
});
}
fn deploy_new_menu(&mut self, action: &DeployNewMenu, cx: &mut ViewContext<Self>) {
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 Search", NewSearch),
],
cx,
);
});
}
pub fn toolbar(&self) -> &ViewHandle<Toolbar> {
&self.toolbar
}
@ -1083,10 +1103,40 @@ impl View for Pane {
.with_child(self.render_tabs(cx).flex(1., true).named("tabs"));
if self.is_active {
tab_row.add_child(
tab_row.add_children([
MouseEventHandler::new::<SplitIcon, _, _>(
0,
cx,
|mouse_state, cx| {
let theme =
&cx.global::<Settings>().theme.workspace.tab_bar;
let style =
theme.pane_button.style_for(mouse_state, false);
Svg::new("icons/plus_12.svg")
.with_color(style.color)
.constrained()
.with_width(style.icon_width)
.aligned()
.contained()
.with_style(style.container)
.constrained()
.with_width(style.button_width)
.with_height(style.button_width)
.aligned()
.boxed()
},
)
.with_cursor_style(CursorStyle::PointingHand)
.on_down(
MouseButton::Left,
|MouseButtonEvent { position, .. }, cx| {
cx.dispatch_action(DeployNewMenu { position });
},
)
.boxed(),
MouseEventHandler::new::<SplitIcon, _, _>(
1,
cx,
|mouse_state, cx| {
let theme =
&cx.global::<Settings>().theme.workspace.tab_bar;
@ -1114,7 +1164,7 @@ impl View for Pane {
},
)
.boxed(),
)
])
}
tab_row
@ -1155,7 +1205,7 @@ impl View for Pane {
})
.boxed(),
)
.with_child(ChildView::new(&self.split_menu).boxed())
.with_child(ChildView::new(&self.context_menu).boxed())
.named("pane")
}

View file

@ -96,6 +96,8 @@ actions!(
FollowNextCollaborator,
ToggleLeftSidebar,
ToggleRightSidebar,
NewTerminal,
NewSearch
]
);

View file

@ -136,7 +136,7 @@ pub fn menus() -> Vec<Menu<'static>> {
},
MenuItem::Action {
name: "Find In Project",
action: Box::new(search::project_search::Deploy),
action: Box::new(workspace::NewSearch),
},
MenuItem::Separator,
MenuItem::Action {

View file

@ -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" }),