mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 18:41:56 +03:00
Add blank pane experience
This commit is contained in:
parent
dad66eb3fb
commit
152755b043
@ -198,6 +198,7 @@ impl TestServer {
|
|||||||
build_window_options: |_, _, _| Default::default(),
|
build_window_options: |_, _, _| Default::default(),
|
||||||
initialize_workspace: |_, _, _| unimplemented!(),
|
initialize_workspace: |_, _, _| unimplemented!(),
|
||||||
dock_default_item_factory: |_, _| unimplemented!(),
|
dock_default_item_factory: |_, _| unimplemented!(),
|
||||||
|
background_actions: || unimplemented!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Project::init(&client);
|
Project::init(&client);
|
||||||
@ -434,15 +435,7 @@ impl TestClient {
|
|||||||
cx: &mut TestAppContext,
|
cx: &mut TestAppContext,
|
||||||
) -> ViewHandle<Workspace> {
|
) -> ViewHandle<Workspace> {
|
||||||
let (_, root_view) = cx.add_window(|_| EmptyView);
|
let (_, root_view) = cx.add_window(|_| EmptyView);
|
||||||
cx.add_view(&root_view, |cx| {
|
cx.add_view(&root_view, |cx| Workspace::test_new(project.clone(), cx))
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_new_root_dir(&mut self) -> PathBuf {
|
fn create_new_root_dir(&mut self) -> PathBuf {
|
||||||
|
@ -1449,15 +1449,7 @@ async fn test_host_disconnect(
|
|||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||||
|
|
||||||
let (_, workspace_b) = cx_b.add_window(|cx| {
|
let (_, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project_b.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
|
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
|
||||||
@ -4706,15 +4698,7 @@ async fn test_collaborating_with_code_actions(
|
|||||||
|
|
||||||
// Join the project as client B.
|
// Join the project as client B.
|
||||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
let (_window_b, workspace_b) = cx_b.add_window(|cx| {
|
let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project_b.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
|
workspace.open_path((worktree_id, "main.rs"), None, true, cx)
|
||||||
@ -4937,15 +4921,7 @@ async fn test_collaborating_with_renames(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let (_window_b, workspace_b) = cx_b.add_window(|cx| {
|
let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::test_new(project_b.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project_b.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
workspace.open_path((worktree_id, "one.rs"), None, true, cx)
|
workspace.open_path((worktree_id, "one.rs"), None, true, cx)
|
||||||
|
@ -86,6 +86,7 @@ fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut Mutable
|
|||||||
0,
|
0,
|
||||||
project,
|
project,
|
||||||
app_state.dock_default_item_factory,
|
app_state.dock_default_item_factory,
|
||||||
|
app_state.background_actions,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
|
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
|
||||||
|
@ -352,9 +352,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let editor = cx.add_view(&workspace, |cx| {
|
let editor = cx.add_view(&workspace, |cx| {
|
||||||
let mut editor = Editor::single_line(None, cx);
|
let mut editor = Editor::single_line(None, cx);
|
||||||
editor.set_text("abc", cx);
|
editor.set_text("abc", cx);
|
||||||
|
@ -805,15 +805,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/test".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create some diagnostics
|
// Create some diagnostics
|
||||||
project.update(cx, |project, cx| {
|
project.update(cx, |project, cx| {
|
||||||
|
@ -484,7 +484,9 @@ fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
|
|||||||
cx.set_global(Settings::test(cx));
|
cx.set_global(Settings::test(cx));
|
||||||
cx.set_global(DragAndDrop::<Workspace>::default());
|
cx.set_global(DragAndDrop::<Workspace>::default());
|
||||||
use workspace::item::Item;
|
use workspace::item::Item;
|
||||||
let (_, pane) = cx.add_window(Default::default(), |cx| Pane::new(None, cx));
|
let (_, pane) = cx.add_window(Default::default(), |cx| {
|
||||||
|
Pane::new(None, || unimplemented!(), cx)
|
||||||
|
});
|
||||||
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
|
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
|
||||||
|
|
||||||
cx.add_view(&pane, |cx| {
|
cx.add_view(&pane, |cx| {
|
||||||
@ -2354,10 +2356,10 @@ async fn test_clipboard(cx: &mut gpui::TestAppContext) {
|
|||||||
e.handle_input(") ", cx);
|
e.handle_input(") ", cx);
|
||||||
});
|
});
|
||||||
cx.assert_editor_state(indoc! {"
|
cx.assert_editor_state(indoc! {"
|
||||||
( one✅
|
( one✅
|
||||||
three
|
three
|
||||||
five ) ˇtwo one✅ four three six five ( one✅
|
five ) ˇtwo one✅ four three six five ( one✅
|
||||||
three
|
three
|
||||||
five ) ˇ"});
|
five ) ˇ"});
|
||||||
|
|
||||||
// Cut with three selections, one of which is full-line.
|
// Cut with three selections, one of which is full-line.
|
||||||
@ -5562,7 +5564,7 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
|
|||||||
Settings::test_async(cx);
|
Settings::test_async(cx);
|
||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
|
let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
|
||||||
let (_, pane) = cx.add_window(|cx| Pane::new(None, cx));
|
let (_, pane) = cx.add_window(|cx| Pane::new(None, || unimplemented!(), cx));
|
||||||
|
|
||||||
let leader = pane.update(cx, |_, cx| {
|
let leader = pane.update(cx, |_, cx| {
|
||||||
let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
|
let multibuffer = cx.add_model(|_| MultiBuffer::new(0));
|
||||||
@ -5831,11 +5833,11 @@ async fn go_to_hunk(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppCon
|
|||||||
cx.assert_editor_state(
|
cx.assert_editor_state(
|
||||||
&r#"
|
&r#"
|
||||||
ˇuse some::modified;
|
ˇuse some::modified;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("hello there");
|
println!("hello there");
|
||||||
|
|
||||||
println!("around the");
|
println!("around the");
|
||||||
println!("world");
|
println!("world");
|
||||||
}
|
}
|
||||||
|
@ -65,15 +65,7 @@ impl<'a> EditorLspTestContext<'a> {
|
|||||||
.insert_tree("/root", json!({ "dir": { file_name.clone(): "" }}))
|
.insert_tree("/root", json!({ "dir": { file_name.clone(): "" }}))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
project
|
project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| {
|
||||||
project.find_or_create_local_worktree("/root", true, cx)
|
project.find_or_create_local_worktree("/root", true, cx)
|
||||||
@ -134,7 +126,7 @@ impl<'a> EditorLspTestContext<'a> {
|
|||||||
(let_chain)
|
(let_chain)
|
||||||
(await_expression)
|
(await_expression)
|
||||||
] @indent
|
] @indent
|
||||||
|
|
||||||
(_ "[" "]" @end) @indent
|
(_ "[" "]" @end) @indent
|
||||||
(_ "<" ">" @end) @indent
|
(_ "<" ">" @end) @indent
|
||||||
(_ "{" "}" @end) @indent
|
(_ "{" "}" @end) @indent
|
||||||
|
@ -329,9 +329,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
cx.dispatch_action(window_id, Toggle);
|
cx.dispatch_action(window_id, Toggle);
|
||||||
|
|
||||||
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
||||||
@ -385,9 +383,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let (_, finder) =
|
let (_, finder) =
|
||||||
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
||||||
|
|
||||||
@ -461,9 +457,7 @@ mod tests {
|
|||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let (_, finder) =
|
let (_, finder) =
|
||||||
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
||||||
finder
|
finder
|
||||||
@ -487,9 +481,7 @@ mod tests {
|
|||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let (_, finder) =
|
let (_, finder) =
|
||||||
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
||||||
|
|
||||||
@ -541,9 +533,7 @@ mod tests {
|
|||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
let (_, finder) =
|
let (_, finder) =
|
||||||
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
||||||
@ -585,9 +575,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
// When workspace has an active item, sort items which are closer to that item
|
// When workspace has an active item, sort items which are closer to that item
|
||||||
// first when they have the same name. In this case, b.txt is closer to dir2's a.txt
|
// first when they have the same name. In this case, b.txt is closer to dir2's a.txt
|
||||||
@ -624,9 +612,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let (_, finder) =
|
let (_, finder) =
|
||||||
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
cx.add_window(|cx| FileFinder::new(workspace.read(cx).project().clone(), None, cx));
|
||||||
finder
|
finder
|
||||||
|
@ -6,15 +6,14 @@ use gpui::{
|
|||||||
actions,
|
actions,
|
||||||
anyhow::{anyhow, Result},
|
anyhow::{anyhow, Result},
|
||||||
elements::{
|
elements::{
|
||||||
AnchorCorner, ChildView, ConstrainedBox, Container, ContainerStyle, Empty, Flex,
|
AnchorCorner, ChildView, ConstrainedBox, ContainerStyle, Empty, Flex, Label,
|
||||||
KeystrokeLabel, Label, MouseEventHandler, ParentElement, ScrollTarget, Stack, Svg,
|
MouseEventHandler, ParentElement, ScrollTarget, Stack, Svg, UniformList, UniformListState,
|
||||||
UniformList, UniformListState,
|
|
||||||
},
|
},
|
||||||
geometry::vector::Vector2F,
|
geometry::vector::Vector2F,
|
||||||
impl_internal_actions,
|
impl_internal_actions,
|
||||||
keymap_matcher::KeymapContext,
|
keymap_matcher::KeymapContext,
|
||||||
platform::CursorStyle,
|
platform::CursorStyle,
|
||||||
Action, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MouseButton,
|
AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MouseButton,
|
||||||
MutableAppContext, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle,
|
MutableAppContext, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use menu::{Confirm, SelectNext, SelectPrev};
|
use menu::{Confirm, SelectNext, SelectPrev};
|
||||||
@ -28,7 +27,7 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use theme::{ContainedText, ProjectPanelEntry};
|
use theme::ProjectPanelEntry;
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
@ -1315,7 +1314,6 @@ impl View for ProjectPanel {
|
|||||||
.with_child(ChildView::new(&self.context_menu, cx).boxed())
|
.with_child(ChildView::new(&self.context_menu, cx).boxed())
|
||||||
.boxed()
|
.boxed()
|
||||||
} else {
|
} else {
|
||||||
let parent_view_id = cx.handle().id();
|
|
||||||
Flex::column()
|
Flex::column()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<Self>::new(2, cx, {
|
MouseEventHandler::<Self>::new(2, cx, {
|
||||||
@ -1327,12 +1325,11 @@ impl View for ProjectPanel {
|
|||||||
let context_menu_item =
|
let context_menu_item =
|
||||||
context_menu_item_style.style_for(state, true).clone();
|
context_menu_item_style.style_for(state, true).clone();
|
||||||
|
|
||||||
keystroke_label(
|
theme::ui::keystroke_label(
|
||||||
parent_view_id,
|
|
||||||
"Open a project",
|
"Open a project",
|
||||||
&button_style,
|
&button_style,
|
||||||
context_menu_item.keystroke,
|
&context_menu_item.keystroke,
|
||||||
workspace::Open,
|
Box::new(workspace::Open),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
@ -1357,38 +1354,6 @@ impl View for ProjectPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keystroke_label<A>(
|
|
||||||
view_id: usize,
|
|
||||||
label_text: &'static str,
|
|
||||||
label_style: &ContainedText,
|
|
||||||
keystroke_style: ContainedText,
|
|
||||||
action: A,
|
|
||||||
cx: &mut RenderContext<ProjectPanel>,
|
|
||||||
) -> Container
|
|
||||||
where
|
|
||||||
A: Action,
|
|
||||||
{
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
Label::new(label_text, label_style.text.clone())
|
|
||||||
.contained()
|
|
||||||
.boxed(),
|
|
||||||
)
|
|
||||||
.with_child({
|
|
||||||
KeystrokeLabel::new(
|
|
||||||
cx.window_id(),
|
|
||||||
view_id,
|
|
||||||
Box::new(action),
|
|
||||||
keystroke_style.container,
|
|
||||||
keystroke_style.text.clone(),
|
|
||||||
)
|
|
||||||
.flex_float()
|
|
||||||
.boxed()
|
|
||||||
})
|
|
||||||
.contained()
|
|
||||||
.with_style(label_style.container)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entity for ProjectPanel {
|
impl Entity for ProjectPanel {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
}
|
}
|
||||||
@ -1474,15 +1439,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
|
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
visible_entries_as_strings(&panel, 0..50, cx),
|
visible_entries_as_strings(&panel, 0..50, cx),
|
||||||
@ -1574,15 +1531,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
|
let panel = workspace.update(cx, |_, cx| ProjectPanel::new(project, cx));
|
||||||
|
|
||||||
select_path(&panel, "root1", cx);
|
select_path(&panel, "root1", cx);
|
||||||
|
@ -970,15 +970,7 @@ mod tests {
|
|||||||
let params = cx.update(AppState::test);
|
let params = cx.update(AppState::test);
|
||||||
|
|
||||||
let project = Project::test(params.fs.clone(), [], cx).await;
|
let project = Project::test(params.fs.clone(), [], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
(project, workspace)
|
(project, workspace)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ use gpui::{
|
|||||||
use serde::{de::DeserializeOwned, Deserialize};
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
use ui::{CheckboxStyle, IconStyle};
|
||||||
|
|
||||||
|
pub mod ui;
|
||||||
|
|
||||||
pub use theme_registry::*;
|
pub use theme_registry::*;
|
||||||
|
|
||||||
@ -50,6 +53,7 @@ pub struct ThemeMeta {
|
|||||||
#[derive(Deserialize, Default)]
|
#[derive(Deserialize, Default)]
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
pub background: Color,
|
pub background: Color,
|
||||||
|
pub blank_pane: BlankPaneStyle,
|
||||||
pub titlebar: Titlebar,
|
pub titlebar: Titlebar,
|
||||||
pub tab_bar: TabBar,
|
pub tab_bar: TabBar,
|
||||||
pub pane_divider: Border,
|
pub pane_divider: Border,
|
||||||
@ -69,6 +73,14 @@ pub struct Workspace {
|
|||||||
pub drop_target_overlay_color: Color,
|
pub drop_target_overlay_color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
pub struct BlankPaneStyle {
|
||||||
|
pub logo: IconStyle,
|
||||||
|
pub keyboard_hints: ContainerStyle,
|
||||||
|
pub keyboard_hint: Interactive<ContainedText>,
|
||||||
|
pub keyboard_hint_width: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
pub struct Titlebar {
|
pub struct Titlebar {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@ -858,46 +870,18 @@ pub struct WelcomeStyle {
|
|||||||
pub logo: IconStyle,
|
pub logo: IconStyle,
|
||||||
pub logo_subheading: ContainedText,
|
pub logo_subheading: ContainedText,
|
||||||
pub checkbox: CheckboxStyle,
|
pub checkbox: CheckboxStyle,
|
||||||
|
pub checkbox_container: ContainerStyle,
|
||||||
pub button: Interactive<ContainedText>,
|
pub button: Interactive<ContainedText>,
|
||||||
pub button_group: ContainerStyle,
|
pub button_group: ContainerStyle,
|
||||||
pub heading_group: ContainerStyle,
|
pub heading_group: ContainerStyle,
|
||||||
pub checkbox_group: ContainerStyle,
|
pub checkbox_group: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
|
||||||
pub struct IconStyle {
|
|
||||||
pub color: Color,
|
|
||||||
pub icon: String,
|
|
||||||
pub dimensions: Dimensions,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
|
||||||
pub struct Dimensions {
|
|
||||||
pub width: f32,
|
|
||||||
pub height: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
|
||||||
pub struct CheckboxStyle {
|
|
||||||
pub check_icon: String,
|
|
||||||
pub check_icon_color: Color,
|
|
||||||
pub label: ContainedText,
|
|
||||||
pub container: ContainerStyle,
|
|
||||||
pub width: f32,
|
|
||||||
pub height: f32,
|
|
||||||
pub default: ContainerStyle,
|
|
||||||
pub checked: ContainerStyle,
|
|
||||||
pub hovered: ContainerStyle,
|
|
||||||
pub hovered_and_checked: ContainerStyle,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
pub struct ColorScheme {
|
pub struct ColorScheme {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub is_light: bool,
|
pub is_light: bool,
|
||||||
|
|
||||||
pub ramps: RampSet,
|
pub ramps: RampSet,
|
||||||
|
|
||||||
pub lowest: Layer,
|
pub lowest: Layer,
|
||||||
pub middle: Layer,
|
pub middle: Layer,
|
||||||
pub highest: Layer,
|
pub highest: Layer,
|
||||||
|
119
crates/theme/src/ui.rs
Normal file
119
crates/theme/src/ui.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
use gpui::{
|
||||||
|
color::Color,
|
||||||
|
elements::{
|
||||||
|
ConstrainedBox, Container, ContainerStyle, Empty, Flex, KeystrokeLabel, Label,
|
||||||
|
MouseEventHandler, ParentElement, Svg,
|
||||||
|
},
|
||||||
|
Action, Element, EventContext, RenderContext, View,
|
||||||
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use crate::ContainedText;
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
pub struct CheckboxStyle {
|
||||||
|
pub icon: IconStyle,
|
||||||
|
pub label: ContainedText,
|
||||||
|
pub default: ContainerStyle,
|
||||||
|
pub checked: ContainerStyle,
|
||||||
|
pub hovered: ContainerStyle,
|
||||||
|
pub hovered_and_checked: ContainerStyle,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn checkbox<T: 'static, V: View>(
|
||||||
|
label: &'static str,
|
||||||
|
style: &CheckboxStyle,
|
||||||
|
checked: bool,
|
||||||
|
cx: &mut RenderContext<V>,
|
||||||
|
change: fn(checked: bool, cx: &mut EventContext) -> (),
|
||||||
|
) -> MouseEventHandler<T> {
|
||||||
|
MouseEventHandler::<T>::new(0, cx, |state, _| {
|
||||||
|
let indicator = if checked {
|
||||||
|
icon(&style.icon)
|
||||||
|
} else {
|
||||||
|
Empty::new()
|
||||||
|
.constrained()
|
||||||
|
.with_width(style.icon.dimensions.width)
|
||||||
|
.with_height(style.icon.dimensions.height)
|
||||||
|
};
|
||||||
|
|
||||||
|
Flex::row()
|
||||||
|
.with_children([
|
||||||
|
indicator
|
||||||
|
.contained()
|
||||||
|
.with_style(if checked {
|
||||||
|
if state.hovered() {
|
||||||
|
style.hovered_and_checked
|
||||||
|
} else {
|
||||||
|
style.checked
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if state.hovered() {
|
||||||
|
style.hovered
|
||||||
|
} else {
|
||||||
|
style.default
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.boxed(),
|
||||||
|
Label::new(label, style.label.text.clone())
|
||||||
|
.contained()
|
||||||
|
.with_style(style.label.container)
|
||||||
|
.boxed(),
|
||||||
|
])
|
||||||
|
.align_children_center()
|
||||||
|
.boxed()
|
||||||
|
})
|
||||||
|
.on_click(gpui::MouseButton::Left, move |_, cx| change(!checked, cx))
|
||||||
|
.with_cursor_style(gpui::CursorStyle::PointingHand)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
pub struct IconStyle {
|
||||||
|
pub color: Color,
|
||||||
|
pub icon: String,
|
||||||
|
pub dimensions: Dimensions,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
pub struct Dimensions {
|
||||||
|
pub width: f32,
|
||||||
|
pub height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn icon(style: &IconStyle) -> ConstrainedBox {
|
||||||
|
Svg::new(style.icon.clone())
|
||||||
|
.with_color(style.color)
|
||||||
|
.constrained()
|
||||||
|
.with_width(style.dimensions.width)
|
||||||
|
.with_height(style.dimensions.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn keystroke_label<V: View>(
|
||||||
|
label_text: &'static str,
|
||||||
|
label_style: &ContainedText,
|
||||||
|
keystroke_style: &ContainedText,
|
||||||
|
action: Box<dyn Action>,
|
||||||
|
cx: &mut RenderContext<V>,
|
||||||
|
) -> Container {
|
||||||
|
// FIXME: Put the theme in it's own global so we can
|
||||||
|
// query the keystroke style on our own
|
||||||
|
Flex::row()
|
||||||
|
.with_child(
|
||||||
|
Label::new(label_text, label_style.text.clone())
|
||||||
|
.contained()
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_child({
|
||||||
|
KeystrokeLabel::new(
|
||||||
|
cx.window_id(),
|
||||||
|
cx.handle().id(),
|
||||||
|
action,
|
||||||
|
keystroke_style.container,
|
||||||
|
keystroke_style.text.clone(),
|
||||||
|
)
|
||||||
|
.flex_float()
|
||||||
|
.boxed()
|
||||||
|
})
|
||||||
|
.contained()
|
||||||
|
.with_style(label_style.container)
|
||||||
|
}
|
@ -4,12 +4,12 @@ use std::{borrow::Cow, sync::Arc};
|
|||||||
|
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
elements::{Empty, Flex, Label, MouseEventHandler, ParentElement, Svg},
|
elements::{Flex, Label, MouseEventHandler, ParentElement},
|
||||||
Action, Element, ElementBox, Entity, MouseButton, MutableAppContext, RenderContext,
|
Action, Element, ElementBox, Entity, MouseButton, MutableAppContext, RenderContext,
|
||||||
Subscription, View, ViewContext,
|
Subscription, View, ViewContext,
|
||||||
};
|
};
|
||||||
use settings::{settings_file::SettingsFile, Settings, SettingsFileContent};
|
use settings::{settings_file::SettingsFile, Settings};
|
||||||
use theme::CheckboxStyle;
|
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::Item, open_new, sidebar::SidebarSide, AppState, PaneBackdrop, Welcome, Workspace,
|
item::Item, open_new, sidebar::SidebarSide, AppState, PaneBackdrop, Welcome, Workspace,
|
||||||
WorkspaceId,
|
WorkspaceId,
|
||||||
@ -77,11 +77,7 @@ impl View for WelcomePage {
|
|||||||
.with_children([
|
.with_children([
|
||||||
Flex::column()
|
Flex::column()
|
||||||
.with_children([
|
.with_children([
|
||||||
Svg::new(theme.welcome.logo.icon.clone())
|
theme::ui::icon(&theme.welcome.logo)
|
||||||
.with_color(theme.welcome.logo.color)
|
|
||||||
.constrained()
|
|
||||||
.with_width(theme.welcome.logo.dimensions.width)
|
|
||||||
.with_height(theme.welcome.logo.dimensions.height)
|
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.aligned()
|
.aligned()
|
||||||
@ -128,20 +124,34 @@ impl View for WelcomePage {
|
|||||||
.boxed(),
|
.boxed(),
|
||||||
Flex::column()
|
Flex::column()
|
||||||
.with_children([
|
.with_children([
|
||||||
self.render_settings_checkbox::<Metrics>(
|
theme::ui::checkbox::<Metrics, Self>(
|
||||||
"Do you want to send telemetry?",
|
"Do you want to send telemetry?",
|
||||||
&theme.welcome.checkbox,
|
&theme.welcome.checkbox,
|
||||||
metrics,
|
metrics,
|
||||||
cx,
|
cx,
|
||||||
|content, checked| content.telemetry.set_metrics(checked),
|
|checked, cx| {
|
||||||
),
|
SettingsFile::update(cx, move |file| {
|
||||||
self.render_settings_checkbox::<Diagnostics>(
|
file.telemetry.set_metrics(checked)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.welcome.checkbox_container)
|
||||||
|
.boxed(),
|
||||||
|
theme::ui::checkbox::<Diagnostics, Self>(
|
||||||
"Send crash reports",
|
"Send crash reports",
|
||||||
&theme.welcome.checkbox,
|
&theme.welcome.checkbox,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
cx,
|
cx,
|
||||||
|content, checked| content.telemetry.set_diagnostics(checked),
|
|checked, cx| {
|
||||||
),
|
SettingsFile::update(cx, move |file| {
|
||||||
|
file.telemetry.set_diagnostics(checked)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.welcome.checkbox_container)
|
||||||
|
.boxed(),
|
||||||
])
|
])
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.welcome.checkbox_group)
|
.with_style(theme.welcome.checkbox_group)
|
||||||
@ -204,59 +214,59 @@ impl WelcomePage {
|
|||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_settings_checkbox<T: 'static>(
|
// fn render_settings_checkbox<T: 'static>(
|
||||||
&self,
|
// &self,
|
||||||
label: &'static str,
|
// label: &'static str,
|
||||||
style: &CheckboxStyle,
|
// style: &CheckboxStyle,
|
||||||
checked: bool,
|
// checked: bool,
|
||||||
cx: &mut RenderContext<Self>,
|
// cx: &mut RenderContext<Self>,
|
||||||
set_value: fn(&mut SettingsFileContent, checked: bool) -> (),
|
// set_value: fn(&mut SettingsFileContent, checked: bool) -> (),
|
||||||
) -> ElementBox {
|
// ) -> ElementBox {
|
||||||
MouseEventHandler::<T>::new(0, cx, |state, _| {
|
// MouseEventHandler::<T>::new(0, cx, |state, _| {
|
||||||
let indicator = if checked {
|
// let indicator = if checked {
|
||||||
Svg::new(style.check_icon.clone())
|
// Svg::new(style.check_icon.clone())
|
||||||
.with_color(style.check_icon_color)
|
// .with_color(style.check_icon_color)
|
||||||
.constrained()
|
// .constrained()
|
||||||
} else {
|
// } else {
|
||||||
Empty::new().constrained()
|
// Empty::new().constrained()
|
||||||
};
|
// };
|
||||||
|
|
||||||
Flex::row()
|
// Flex::row()
|
||||||
.with_children([
|
// .with_children([
|
||||||
indicator
|
// indicator
|
||||||
.with_width(style.width)
|
// .with_width(style.width)
|
||||||
.with_height(style.height)
|
// .with_height(style.height)
|
||||||
.contained()
|
// .contained()
|
||||||
.with_style(if checked {
|
// .with_style(if checked {
|
||||||
if state.hovered() {
|
// if state.hovered() {
|
||||||
style.hovered_and_checked
|
// style.hovered_and_checked
|
||||||
} else {
|
// } else {
|
||||||
style.checked
|
// style.checked
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
if state.hovered() {
|
// if state.hovered() {
|
||||||
style.hovered
|
// style.hovered
|
||||||
} else {
|
// } else {
|
||||||
style.default
|
// style.default
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.boxed(),
|
// .boxed(),
|
||||||
Label::new(label, style.label.text.clone())
|
// Label::new(label, style.label.text.clone())
|
||||||
.contained()
|
// .contained()
|
||||||
.with_style(style.label.container)
|
// .with_style(style.label.container)
|
||||||
.boxed(),
|
// .boxed(),
|
||||||
])
|
// ])
|
||||||
.align_children_center()
|
// .align_children_center()
|
||||||
.boxed()
|
// .boxed()
|
||||||
})
|
// })
|
||||||
.on_click(gpui::MouseButton::Left, move |_, cx| {
|
// .on_click(gpui::MouseButton::Left, move |_, cx| {
|
||||||
SettingsFile::update(cx, move |content| set_value(content, !checked))
|
// SettingsFile::update(cx, move |content| set_value(content, !checked))
|
||||||
})
|
// })
|
||||||
.with_cursor_style(gpui::CursorStyle::PointingHand)
|
// .with_cursor_style(gpui::CursorStyle::PointingHand)
|
||||||
.contained()
|
// .contained()
|
||||||
.with_style(style.container)
|
// .with_style(style.container)
|
||||||
.boxed()
|
// .boxed()
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item for WelcomePage {
|
impl Item for WelcomePage {
|
||||||
|
@ -13,7 +13,7 @@ use gpui::{
|
|||||||
use settings::{DockAnchor, Settings};
|
use settings::{DockAnchor, Settings};
|
||||||
use theme::Theme;
|
use theme::Theme;
|
||||||
|
|
||||||
use crate::{sidebar::SidebarSide, ItemHandle, Pane, Workspace};
|
use crate::{sidebar::SidebarSide, BackgroundActions, ItemHandle, Pane, Workspace};
|
||||||
pub use toggle_dock_button::ToggleDockButton;
|
pub use toggle_dock_button::ToggleDockButton;
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Deserialize)]
|
#[derive(PartialEq, Clone, Deserialize)]
|
||||||
@ -182,11 +182,12 @@ pub struct Dock {
|
|||||||
impl Dock {
|
impl Dock {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
default_item_factory: DockDefaultItemFactory,
|
default_item_factory: DockDefaultItemFactory,
|
||||||
|
background_actions: BackgroundActions,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let position = DockPosition::Hidden(cx.global::<Settings>().default_dock_anchor);
|
let position = DockPosition::Hidden(cx.global::<Settings>().default_dock_anchor);
|
||||||
|
|
||||||
let pane = cx.add_view(|cx| Pane::new(Some(position.anchor()), cx));
|
let pane = cx.add_view(|cx| Pane::new(Some(position.anchor()), background_actions, cx));
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.set_active(false, cx);
|
pane.set_active(false, cx);
|
||||||
});
|
});
|
||||||
@ -492,6 +493,7 @@ mod tests {
|
|||||||
0,
|
0,
|
||||||
project.clone(),
|
project.clone(),
|
||||||
default_item_factory,
|
default_item_factory,
|
||||||
|
|| unimplemented!(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -620,7 +622,14 @@ mod tests {
|
|||||||
cx.update(|cx| init(cx));
|
cx.update(|cx| init(cx));
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| {
|
||||||
Workspace::new(Default::default(), 0, project, default_item_factory, cx)
|
Workspace::new(
|
||||||
|
Default::default(),
|
||||||
|
0,
|
||||||
|
project,
|
||||||
|
default_item_factory,
|
||||||
|
|| unimplemented!(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
|
@ -110,6 +110,8 @@ impl_internal_actions!(
|
|||||||
|
|
||||||
const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
|
const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
|
||||||
|
|
||||||
|
pub type BackgroundActions = fn() -> &'static [(&'static str, &'static dyn Action)];
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(|pane: &mut Pane, action: &ActivateItem, cx| {
|
cx.add_action(|pane: &mut Pane, action: &ActivateItem, cx| {
|
||||||
pane.activate_item(action.0, true, true, cx);
|
pane.activate_item(action.0, true, true, cx);
|
||||||
@ -215,6 +217,7 @@ pub struct Pane {
|
|||||||
toolbar: ViewHandle<Toolbar>,
|
toolbar: ViewHandle<Toolbar>,
|
||||||
tab_bar_context_menu: ViewHandle<ContextMenu>,
|
tab_bar_context_menu: ViewHandle<ContextMenu>,
|
||||||
docked: Option<DockAnchor>,
|
docked: Option<DockAnchor>,
|
||||||
|
background_actions: BackgroundActions,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ItemNavHistory {
|
pub struct ItemNavHistory {
|
||||||
@ -271,7 +274,11 @@ enum ItemType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Pane {
|
impl Pane {
|
||||||
pub fn new(docked: Option<DockAnchor>, cx: &mut ViewContext<Self>) -> Self {
|
pub fn new(
|
||||||
|
docked: Option<DockAnchor>,
|
||||||
|
background_actions: BackgroundActions,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Self {
|
||||||
let handle = cx.weak_handle();
|
let handle = cx.weak_handle();
|
||||||
let context_menu = cx.add_view(ContextMenu::new);
|
let context_menu = cx.add_view(ContextMenu::new);
|
||||||
Self {
|
Self {
|
||||||
@ -292,6 +299,7 @@ impl Pane {
|
|||||||
toolbar: cx.add_view(|_| Toolbar::new(handle)),
|
toolbar: cx.add_view(|_| Toolbar::new(handle)),
|
||||||
tab_bar_context_menu: context_menu,
|
tab_bar_context_menu: context_menu,
|
||||||
docked,
|
docked,
|
||||||
|
background_actions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1415,6 +1423,64 @@ impl Pane {
|
|||||||
.flex(1., false)
|
.flex(1., false)
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_blank_pane(&mut self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
|
let background = theme.workspace.background;
|
||||||
|
let keystroke_style = &theme.context_menu.item;
|
||||||
|
let theme = &theme.workspace.blank_pane;
|
||||||
|
Stack::new()
|
||||||
|
.with_children([
|
||||||
|
Empty::new()
|
||||||
|
.contained()
|
||||||
|
.with_background_color(background)
|
||||||
|
.boxed(),
|
||||||
|
Flex::column()
|
||||||
|
.align_children_center()
|
||||||
|
.with_children([
|
||||||
|
theme::ui::icon(&theme.logo).aligned().boxed(),
|
||||||
|
Flex::column()
|
||||||
|
.with_children({
|
||||||
|
enum KeyboardHint {}
|
||||||
|
let keyboard_hint = &theme.keyboard_hint;
|
||||||
|
(self.background_actions)().into_iter().enumerate().map(
|
||||||
|
move |(idx, (text, action))| {
|
||||||
|
let hint_action = action.boxed_clone();
|
||||||
|
MouseEventHandler::<KeyboardHint>::new(
|
||||||
|
idx,
|
||||||
|
cx,
|
||||||
|
move |state, cx| {
|
||||||
|
theme::ui::keystroke_label(
|
||||||
|
text,
|
||||||
|
&keyboard_hint.style_for(state, false),
|
||||||
|
&keystroke_style
|
||||||
|
.style_for(state, false)
|
||||||
|
.keystroke,
|
||||||
|
hint_action,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.boxed()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.on_click(MouseButton::Left, move |_, cx| {
|
||||||
|
cx.dispatch_any_action(action.boxed_clone())
|
||||||
|
})
|
||||||
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
.boxed()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.keyboard_hints)
|
||||||
|
.constrained()
|
||||||
|
.with_max_width(theme.keyboard_hint_width)
|
||||||
|
.aligned()
|
||||||
|
.boxed(),
|
||||||
|
])
|
||||||
|
.aligned()
|
||||||
|
.boxed(),
|
||||||
|
])
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for Pane {
|
impl Entity for Pane {
|
||||||
@ -1508,11 +1574,8 @@ impl View for Pane {
|
|||||||
enum EmptyPane {}
|
enum EmptyPane {}
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
|
|
||||||
dragged_item_receiver::<EmptyPane, _>(0, 0, false, None, cx, |_, _| {
|
dragged_item_receiver::<EmptyPane, _>(0, 0, false, None, cx, |_, cx| {
|
||||||
Empty::new()
|
self.render_blank_pane(&theme, cx)
|
||||||
.contained()
|
|
||||||
.with_background_color(theme.workspace.background)
|
|
||||||
.boxed()
|
|
||||||
})
|
})
|
||||||
.on_down(MouseButton::Left, |_, cx| {
|
.on_down(MouseButton::Left, |_, cx| {
|
||||||
cx.focus_parent_view();
|
cx.focus_parent_view();
|
||||||
@ -1809,9 +1872,7 @@ mod tests {
|
|||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
|
||||||
let project = Project::test(fs, None, cx).await;
|
let project = Project::test(fs, None, cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||||
|
|
||||||
// 1. Add with a destination index
|
// 1. Add with a destination index
|
||||||
@ -1899,9 +1960,7 @@ mod tests {
|
|||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
|
||||||
let project = Project::test(fs, None, cx).await;
|
let project = Project::test(fs, None, cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||||
|
|
||||||
// 1. Add with a destination index
|
// 1. Add with a destination index
|
||||||
@ -1977,9 +2036,7 @@ mod tests {
|
|||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
|
||||||
let project = Project::test(fs, None, cx).await;
|
let project = Project::test(fs, None, cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||||
|
|
||||||
// singleton view
|
// singleton view
|
||||||
@ -2088,8 +2145,7 @@ mod tests {
|
|||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
|
||||||
let project = Project::test(fs, None, cx).await;
|
let project = Project::test(fs, None, cx).await;
|
||||||
let (_, workspace) =
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
cx.add_window(|cx| Workspace::new(None, 0, project, |_, _| unimplemented!(), cx));
|
|
||||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||||
|
|
||||||
add_labled_item(&workspace, &pane, "A", cx);
|
add_labled_item(&workspace, &pane, "A", cx);
|
||||||
|
@ -432,6 +432,7 @@ pub struct AppState {
|
|||||||
fn(Option<WindowBounds>, Option<uuid::Uuid>, &dyn Platform) -> WindowOptions<'static>,
|
fn(Option<WindowBounds>, Option<uuid::Uuid>, &dyn Platform) -> WindowOptions<'static>,
|
||||||
pub initialize_workspace: fn(&mut Workspace, &Arc<AppState>, &mut ViewContext<Workspace>),
|
pub initialize_workspace: fn(&mut Workspace, &Arc<AppState>, &mut ViewContext<Workspace>),
|
||||||
pub dock_default_item_factory: DockDefaultItemFactory,
|
pub dock_default_item_factory: DockDefaultItemFactory,
|
||||||
|
pub background_actions: BackgroundActions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@ -455,6 +456,7 @@ impl AppState {
|
|||||||
initialize_workspace: |_, _, _| {},
|
initialize_workspace: |_, _, _| {},
|
||||||
build_window_options: |_, _, _| Default::default(),
|
build_window_options: |_, _, _| Default::default(),
|
||||||
dock_default_item_factory: |_, _| unimplemented!(),
|
dock_default_item_factory: |_, _| unimplemented!(),
|
||||||
|
background_actions: || unimplemented!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,6 +544,7 @@ pub struct Workspace {
|
|||||||
active_call: Option<(ModelHandle<ActiveCall>, Vec<gpui::Subscription>)>,
|
active_call: Option<(ModelHandle<ActiveCall>, Vec<gpui::Subscription>)>,
|
||||||
leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
|
leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
|
||||||
database_id: WorkspaceId,
|
database_id: WorkspaceId,
|
||||||
|
background_actions: BackgroundActions,
|
||||||
_window_subscriptions: [Subscription; 3],
|
_window_subscriptions: [Subscription; 3],
|
||||||
_apply_leader_updates: Task<Result<()>>,
|
_apply_leader_updates: Task<Result<()>>,
|
||||||
_observe_current_user: Task<()>,
|
_observe_current_user: Task<()>,
|
||||||
@ -572,6 +575,7 @@ impl Workspace {
|
|||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
dock_default_factory: DockDefaultItemFactory,
|
dock_default_factory: DockDefaultItemFactory,
|
||||||
|
background_actions: BackgroundActions,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
cx.observe(&project, |_, _, cx| cx.notify()).detach();
|
cx.observe(&project, |_, _, cx| cx.notify()).detach();
|
||||||
@ -602,7 +606,7 @@ impl Workspace {
|
|||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let center_pane = cx.add_view(|cx| Pane::new(None, cx));
|
let center_pane = cx.add_view(|cx| Pane::new(None, background_actions, cx));
|
||||||
let pane_id = center_pane.id();
|
let pane_id = center_pane.id();
|
||||||
cx.subscribe(¢er_pane, move |this, _, event, cx| {
|
cx.subscribe(¢er_pane, move |this, _, event, cx| {
|
||||||
this.handle_pane_event(pane_id, event, cx)
|
this.handle_pane_event(pane_id, event, cx)
|
||||||
@ -610,7 +614,7 @@ impl Workspace {
|
|||||||
.detach();
|
.detach();
|
||||||
cx.focus(¢er_pane);
|
cx.focus(¢er_pane);
|
||||||
cx.emit(Event::PaneAdded(center_pane.clone()));
|
cx.emit(Event::PaneAdded(center_pane.clone()));
|
||||||
let dock = Dock::new(dock_default_factory, cx);
|
let dock = Dock::new(dock_default_factory, background_actions, cx);
|
||||||
let dock_pane = dock.pane().clone();
|
let dock_pane = dock.pane().clone();
|
||||||
|
|
||||||
let fs = project.read(cx).fs().clone();
|
let fs = project.read(cx).fs().clone();
|
||||||
@ -730,6 +734,7 @@ impl Workspace {
|
|||||||
window_edited: false,
|
window_edited: false,
|
||||||
active_call,
|
active_call,
|
||||||
database_id: workspace_id,
|
database_id: workspace_id,
|
||||||
|
background_actions,
|
||||||
_observe_current_user,
|
_observe_current_user,
|
||||||
_apply_leader_updates,
|
_apply_leader_updates,
|
||||||
leader_updates_tx,
|
leader_updates_tx,
|
||||||
@ -818,6 +823,7 @@ impl Workspace {
|
|||||||
workspace_id,
|
workspace_id,
|
||||||
project_handle,
|
project_handle,
|
||||||
app_state.dock_default_item_factory,
|
app_state.dock_default_item_factory,
|
||||||
|
app_state.background_actions,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
|
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
|
||||||
@ -1432,7 +1438,7 @@ impl Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_pane(&mut self, cx: &mut ViewContext<Self>) -> ViewHandle<Pane> {
|
fn add_pane(&mut self, cx: &mut ViewContext<Self>) -> ViewHandle<Pane> {
|
||||||
let pane = cx.add_view(|cx| Pane::new(None, cx));
|
let pane = cx.add_view(|cx| Pane::new(None, self.background_actions, cx));
|
||||||
let pane_id = pane.id();
|
let pane_id = pane.id();
|
||||||
cx.subscribe(&pane, move |this, _, event, cx| {
|
cx.subscribe(&pane, move |this, _, event, cx| {
|
||||||
this.handle_pane_event(pane_id, event, cx)
|
this.handle_pane_event(pane_id, event, cx)
|
||||||
@ -2648,6 +2654,11 @@ impl Workspace {
|
|||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
pub fn test_new(project: ModelHandle<Project>, cx: &mut ViewContext<Self>) -> Self {
|
||||||
|
Self::new(None, 0, project, |_, _| None, || &[], cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAppContext) {
|
fn notify_if_database_failed(workspace: &ViewHandle<Workspace>, cx: &mut AsyncAppContext) {
|
||||||
@ -2988,17 +2999,10 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use fs::FakeFs;
|
use fs::FakeFs;
|
||||||
use gpui::{executor::Deterministic, TestAppContext, ViewContext};
|
use gpui::{executor::Deterministic, TestAppContext};
|
||||||
use project::{Project, ProjectEntryId};
|
use project::{Project, ProjectEntryId};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
pub fn default_item_factory(
|
|
||||||
_workspace: &mut Workspace,
|
|
||||||
_cx: &mut ViewContext<Workspace>,
|
|
||||||
) -> Option<Box<dyn ItemHandle>> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_tab_disambiguation(cx: &mut TestAppContext) {
|
async fn test_tab_disambiguation(cx: &mut TestAppContext) {
|
||||||
cx.foreground().forbid_parking();
|
cx.foreground().forbid_parking();
|
||||||
@ -3011,7 +3015,8 @@ mod tests {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
0,
|
0,
|
||||||
project.clone(),
|
project.clone(),
|
||||||
default_item_factory,
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -3083,7 +3088,8 @@ mod tests {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
0,
|
0,
|
||||||
project.clone(),
|
project.clone(),
|
||||||
default_item_factory,
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -3183,7 +3189,8 @@ mod tests {
|
|||||||
Default::default(),
|
Default::default(),
|
||||||
0,
|
0,
|
||||||
project.clone(),
|
project.clone(),
|
||||||
default_item_factory,
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -3222,7 +3229,14 @@ mod tests {
|
|||||||
|
|
||||||
let project = Project::test(fs, None, cx).await;
|
let project = Project::test(fs, None, cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| {
|
||||||
Workspace::new(Default::default(), 0, project, default_item_factory, cx)
|
Workspace::new(
|
||||||
|
Default::default(),
|
||||||
|
0,
|
||||||
|
project,
|
||||||
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let item1 = cx.add_view(&workspace, |cx| {
|
let item1 = cx.add_view(&workspace, |cx| {
|
||||||
@ -3331,7 +3345,14 @@ mod tests {
|
|||||||
|
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| {
|
||||||
Workspace::new(Default::default(), 0, project, default_item_factory, cx)
|
Workspace::new(
|
||||||
|
Default::default(),
|
||||||
|
0,
|
||||||
|
project,
|
||||||
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create several workspace items with single project entries, and two
|
// Create several workspace items with single project entries, and two
|
||||||
@ -3440,7 +3461,14 @@ mod tests {
|
|||||||
|
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| {
|
||||||
Workspace::new(Default::default(), 0, project, default_item_factory, cx)
|
Workspace::new(
|
||||||
|
Default::default(),
|
||||||
|
0,
|
||||||
|
project,
|
||||||
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let item = cx.add_view(&workspace, |cx| {
|
let item = cx.add_view(&workspace, |cx| {
|
||||||
@ -3559,7 +3587,14 @@ mod tests {
|
|||||||
|
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| {
|
||||||
Workspace::new(Default::default(), 0, project, default_item_factory, cx)
|
Workspace::new(
|
||||||
|
Default::default(),
|
||||||
|
0,
|
||||||
|
project,
|
||||||
|
|_, _| unimplemented!(),
|
||||||
|
|| unimplemented!(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let item = cx.add_view(&workspace, |cx| {
|
let item = cx.add_view(&workspace, |cx| {
|
||||||
|
@ -18,7 +18,7 @@ use futures::{
|
|||||||
channel::{mpsc, oneshot},
|
channel::{mpsc, oneshot},
|
||||||
FutureExt, SinkExt, StreamExt,
|
FutureExt, SinkExt, StreamExt,
|
||||||
};
|
};
|
||||||
use gpui::{App, AssetSource, AsyncAppContext, MutableAppContext, Task, ViewContext};
|
use gpui::{Action, App, AssetSource, AsyncAppContext, MutableAppContext, Task, ViewContext};
|
||||||
use isahc::{config::Configurable, Request};
|
use isahc::{config::Configurable, Request};
|
||||||
use language::LanguageRegistry;
|
use language::LanguageRegistry;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
@ -45,9 +45,10 @@ use theme::ThemeRegistry;
|
|||||||
use util::StaffMode;
|
use util::StaffMode;
|
||||||
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
|
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
self, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile, OpenPaths, Workspace,
|
self, dock::FocusDock, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile,
|
||||||
|
OpenPaths, Workspace,
|
||||||
};
|
};
|
||||||
use zed::{self, build_window_options, initialize_workspace, languages, menus};
|
use zed::{self, build_window_options, initialize_workspace, languages, menus, OpenSettings};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let http = http::client();
|
let http = http::client();
|
||||||
@ -186,6 +187,7 @@ fn main() {
|
|||||||
build_window_options,
|
build_window_options,
|
||||||
initialize_workspace,
|
initialize_workspace,
|
||||||
dock_default_item_factory,
|
dock_default_item_factory,
|
||||||
|
background_actions,
|
||||||
});
|
});
|
||||||
auto_update::init(http, client::ZED_SERVER_URL.clone(), cx);
|
auto_update::init(http, client::ZED_SERVER_URL.clone(), cx);
|
||||||
|
|
||||||
@ -703,3 +705,13 @@ pub fn dock_default_item_factory(
|
|||||||
|
|
||||||
Some(Box::new(terminal_view))
|
Some(Box::new(terminal_view))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn background_actions() -> &'static [(&'static str, &'static dyn Action)] {
|
||||||
|
&[
|
||||||
|
("Go to file", &file_finder::Toggle),
|
||||||
|
("Open the command palette", &command_palette::Toggle),
|
||||||
|
("Focus the dock", &FocusDock),
|
||||||
|
("Open recent projects", &recent_projects::OpenRecent),
|
||||||
|
("Change your settings", &OpenSettings),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@ -889,9 +889,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||||
let file1 = entries[0].clone();
|
let file1 = entries[0].clone();
|
||||||
@ -1010,9 +1008,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/dir1".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Open a file within an existing worktree.
|
// Open a file within an existing worktree.
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
@ -1171,9 +1167,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Open a file within an existing worktree.
|
// Open a file within an existing worktree.
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
@ -1215,9 +1209,7 @@ mod tests {
|
|||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
|
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
|
||||||
|
|
||||||
// Create a new untitled buffer
|
// Create a new untitled buffer
|
||||||
@ -1306,9 +1298,7 @@ mod tests {
|
|||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
||||||
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a new untitled buffer
|
// Create a new untitled buffer
|
||||||
cx.dispatch_action(window_id, NewFile);
|
cx.dispatch_action(window_id, NewFile);
|
||||||
@ -1361,9 +1351,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (window_id, workspace) = cx.add_window(|cx| {
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(Default::default(), 0, project, |_, _| unimplemented!(), cx)
|
|
||||||
});
|
|
||||||
|
|
||||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||||
let file1 = entries[0].clone();
|
let file1 = entries[0].clone();
|
||||||
@ -1437,15 +1425,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||||
let file1 = entries[0].clone();
|
let file1 = entries[0].clone();
|
||||||
@ -1709,15 +1689,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||||
let (_, workspace) = cx.add_window(|cx| {
|
let (_, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
Workspace::new(
|
|
||||||
Default::default(),
|
|
||||||
0,
|
|
||||||
project.clone(),
|
|
||||||
|_, _| unimplemented!(),
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||||
|
|
||||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||||
|
@ -26,14 +26,19 @@ export default function contextMenu(colorScheme: ColorScheme) {
|
|||||||
hover: {
|
hover: {
|
||||||
background: background(layer, "hovered"),
|
background: background(layer, "hovered"),
|
||||||
label: text(layer, "sans", "hovered", { size: "sm" }),
|
label: text(layer, "sans", "hovered", { size: "sm" }),
|
||||||
|
keystroke: {
|
||||||
|
...text(layer, "sans", "hovered", {
|
||||||
|
size: "sm",
|
||||||
|
weight: "bold",
|
||||||
|
}),
|
||||||
|
padding: { left: 3, right: 3 },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
active: {
|
active: {
|
||||||
background: background(layer, "active"),
|
background: background(layer, "active"),
|
||||||
label: text(layer, "sans", "active", { size: "sm" }),
|
|
||||||
},
|
},
|
||||||
activeHover: {
|
activeHover: {
|
||||||
background: background(layer, "active"),
|
background: background(layer, "active"),
|
||||||
label: text(layer, "sans", "active", { size: "sm" }),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
separator: {
|
separator: {
|
||||||
|
@ -86,20 +86,24 @@ export default function welcome(colorScheme: ColorScheme) {
|
|||||||
border: border(layer, "active"),
|
border: border(layer, "active"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
checkboxContainer: {
|
||||||
|
margin: {
|
||||||
|
top: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
checkbox: {
|
checkbox: {
|
||||||
label: {
|
label: {
|
||||||
...text(layer, "sans", interactive_text_size),
|
...text(layer, "sans", interactive_text_size),
|
||||||
// Also supports margin, container, border, etc.
|
// Also supports margin, container, border, etc.
|
||||||
},
|
},
|
||||||
container: {
|
icon: {
|
||||||
margin: {
|
color: foreground(layer, "on"),
|
||||||
top: 4,
|
icon: "icons/check_12.svg",
|
||||||
},
|
dimensions: {
|
||||||
|
width: 12,
|
||||||
|
height: 12,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
width: 12,
|
|
||||||
height: 12,
|
|
||||||
checkIcon: "icons/check_12.svg",
|
|
||||||
checkIconColor: foreground(layer, "on"),
|
|
||||||
default: {
|
default: {
|
||||||
...checkboxBase,
|
...checkboxBase,
|
||||||
background: background(layer, "default"),
|
background: background(layer, "default"),
|
||||||
|
@ -41,6 +41,34 @@ export default function workspace(colorScheme: ColorScheme) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
background: background(layer),
|
background: background(layer),
|
||||||
|
blankPane: {
|
||||||
|
logo: {
|
||||||
|
color: background(layer, "on"),
|
||||||
|
icon: "icons/logo_96.svg",
|
||||||
|
dimensions: {
|
||||||
|
width: 240,
|
||||||
|
height: 240,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyboardHints: {
|
||||||
|
margin: {
|
||||||
|
top: 32
|
||||||
|
},
|
||||||
|
padding: {
|
||||||
|
bottom: -8.
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyboardHint: {
|
||||||
|
...text(colorScheme.lowest, "sans", "variant", { size: "sm" }),
|
||||||
|
margin: {
|
||||||
|
bottom: 8
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
...text(colorScheme.lowest, "sans", "hovered", { size: "sm" }),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyboardHintWidth: 240,
|
||||||
|
},
|
||||||
joiningProjectAvatar: {
|
joiningProjectAvatar: {
|
||||||
cornerRadius: 40,
|
cornerRadius: 40,
|
||||||
width: 80,
|
width: 80,
|
||||||
|
Loading…
Reference in New Issue
Block a user