WIP
This commit is contained in:
parent
3c938a7377
commit
afcc0d621b
13 changed files with 300 additions and 262 deletions
|
@ -64,7 +64,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
|
|||
Editor::for_buffer(buffer.clone(), None, cx)
|
||||
}
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let editor2 = cx
|
||||
.add_window({
|
||||
let events = events.clone();
|
||||
|
@ -81,7 +81,7 @@ fn test_edit_events(cx: &mut TestAppContext) {
|
|||
Editor::for_buffer(buffer.clone(), None, cx)
|
||||
}
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
|
||||
|
||||
// Mutating editor 1 will emit an `Edited` event only for that editor.
|
||||
|
@ -179,7 +179,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) {
|
|||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx
|
||||
.add_window(|cx| build_editor(buffer.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.start_transaction_at(now, cx);
|
||||
|
@ -354,7 +354,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\nddddddd\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
editor.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
|
||||
});
|
||||
|
@ -423,7 +423,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
|
||||
|
@ -471,7 +471,7 @@ fn test_clone(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple(&text, cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone()));
|
||||
|
@ -489,7 +489,7 @@ fn test_clone(cx: &mut TestAppContext) {
|
|||
.update(cx, |editor, cx| {
|
||||
cx.add_window(Default::default(), |cx| editor.clone(cx))
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
let snapshot = editor.update(cx, |e, cx| e.snapshot(cx));
|
||||
let cloned_snapshot = cloned_editor.update(cx, |e, cx| e.snapshot(cx));
|
||||
|
@ -639,7 +639,7 @@ fn test_cancel(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
|
||||
|
@ -704,7 +704,7 @@ fn test_fold_action(cx: &mut TestAppContext) {
|
|||
);
|
||||
build_editor(buffer.clone(), cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
|
@ -774,7 +774,7 @@ fn test_move_cursor(cx: &mut TestAppContext) {
|
|||
let buffer = cx.update(|cx| MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx));
|
||||
let view = cx
|
||||
.add_window(|cx| build_editor(buffer.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
|
@ -854,7 +854,7 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
assert_eq!('ⓐ'.len_utf8(), 3);
|
||||
assert_eq!('α'.len_utf8(), 2);
|
||||
|
@ -961,7 +961,7 @@ fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]);
|
||||
|
@ -1013,7 +1013,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\n def", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
|
@ -1178,7 +1178,7 @@ fn test_prev_next_word_boundary(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
|
@ -1233,7 +1233,7 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) {
|
|||
MultiBuffer::build_simple("use one::{\n two::three::four::five\n};", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.set_wrap_width(Some(140.), cx);
|
||||
|
@ -1568,7 +1568,7 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("one two three four", cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
|
@ -1606,7 +1606,7 @@ fn test_newline(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("aaaa\n bbbb\n", cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
|
@ -1651,7 +1651,7 @@ fn test_newline_with_old_selections(cx: &mut TestAppContext) {
|
|||
});
|
||||
editor
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
// Edit the buffer directly, deleting ranges surrounding the editor's selections
|
||||
|
@ -1863,7 +1863,7 @@ fn test_insert_with_old_selections(cx: &mut TestAppContext) {
|
|||
editor.change_selections(None, cx, |s| s.select_ranges([3..4, 11..12, 19..20]));
|
||||
editor
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
// Edit the buffer directly, deleting ranges surrounding the editor's selections
|
||||
|
@ -2375,7 +2375,7 @@ fn test_delete_line(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
|
@ -2400,7 +2400,7 @@ fn test_delete_line(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)])
|
||||
|
@ -2704,7 +2704,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
|
@ -2732,7 +2732,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
|
@ -2761,7 +2761,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.fold_ranges(
|
||||
vec![
|
||||
|
@ -2862,7 +2862,7 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
editor.update(cx, |editor, cx| {
|
||||
let snapshot = editor.buffer.read(cx).snapshot(cx);
|
||||
editor.insert_blocks(
|
||||
|
@ -3182,7 +3182,7 @@ fn test_select_all(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.select_all(&SelectAll, cx);
|
||||
assert_eq!(
|
||||
|
@ -3201,7 +3201,7 @@ fn test_select_line(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
s.select_display_ranges([
|
||||
|
@ -3250,7 +3250,7 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.fold_ranges(
|
||||
vec![
|
||||
|
@ -3323,7 +3323,7 @@ fn test_add_selection_above_below(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
|
||||
build_editor(buffer, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.change_selections(None, cx, |s| {
|
||||
|
@ -3608,7 +3608,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let view = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
|
||||
.await;
|
||||
|
||||
|
@ -3771,7 +3771,7 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
editor
|
||||
.condition(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx))
|
||||
.await;
|
||||
|
@ -4334,7 +4334,7 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let view = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
|
||||
.await;
|
||||
|
||||
|
@ -4482,7 +4482,7 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
editor
|
||||
.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
|
||||
.await;
|
||||
|
@ -4572,7 +4572,7 @@ async fn test_snippets(cx: &mut gpui::TestAppContext) {
|
|||
);
|
||||
|
||||
let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap();
|
||||
|
@ -4702,7 +4702,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) {
|
|||
let fake_server = fake_servers.next().await.unwrap();
|
||||
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
|
||||
assert!(cx.read(|cx| editor.is_dirty(cx)));
|
||||
|
||||
|
@ -4814,7 +4814,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) {
|
|||
let fake_server = fake_servers.next().await.unwrap();
|
||||
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
|
||||
assert!(cx.read(|cx| editor.is_dirty(cx)));
|
||||
|
||||
|
@ -4928,7 +4928,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) {
|
|||
let fake_server = fake_servers.next().await.unwrap();
|
||||
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx));
|
||||
|
||||
let format = editor.update(cx, |editor, cx| {
|
||||
|
@ -5706,7 +5706,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
|
|||
multibuffer
|
||||
});
|
||||
|
||||
let view = cx.add_window(|cx| build_editor(multibuffer, cx)).detach(cx);
|
||||
let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
assert_eq!(view.text(cx), "aaaa\nbbbb");
|
||||
view.change_selections(None, cx, |s| {
|
||||
|
@ -5776,7 +5776,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
|
|||
multibuffer
|
||||
});
|
||||
|
||||
let view = cx.add_window(|cx| build_editor(multibuffer, cx)).detach(cx);
|
||||
let view = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
let (expected_text, selection_ranges) = marked_text_ranges(
|
||||
indoc! {"
|
||||
|
@ -5869,7 +5869,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
|
|||
);
|
||||
editor
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
// Refreshing selections is a no-op when excerpts haven't changed.
|
||||
editor.update(cx, |editor, cx| {
|
||||
|
@ -5950,7 +5950,7 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
|
|||
);
|
||||
editor
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
multibuffer.update(cx, |multibuffer, cx| {
|
||||
multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx);
|
||||
|
@ -6013,7 +6013,7 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) {
|
|||
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx).with_language(language, cx));
|
||||
let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
|
||||
let view = cx.add_window(|cx| build_editor(buffer, cx)).detach(cx);
|
||||
let view = cx.add_window(|cx| build_editor(buffer, cx)).root(cx);
|
||||
view.condition(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx))
|
||||
.await;
|
||||
|
||||
|
@ -6054,7 +6054,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) {
|
|||
let buffer = MultiBuffer::build_simple(&sample_text(16, 8, 'a'), cx);
|
||||
build_editor(buffer.clone(), cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
struct Type1;
|
||||
|
@ -6145,7 +6145,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
|
|||
});
|
||||
let leader = cx
|
||||
.add_window(|cx| build_editor(buffer.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let follower = cx
|
||||
.update(|cx| {
|
||||
cx.add_window(
|
||||
|
@ -6156,7 +6156,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
|
|||
|cx| build_editor(buffer.clone(), cx),
|
||||
)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
let is_still_following = Rc::new(RefCell::new(true));
|
||||
let follower_edit_event_count = Rc::new(RefCell::new(0));
|
||||
|
@ -6289,7 +6289,7 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
|
|||
let project = Project::test(fs, ["/file.rs".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||
|
||||
let leader = pane.update(cx, |_, cx| {
|
||||
|
@ -7033,7 +7033,7 @@ async fn test_copilot_multibuffer(
|
|||
);
|
||||
multibuffer
|
||||
});
|
||||
let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
|
||||
|
||||
handle_copilot_completion_request(
|
||||
&copilot_lsp,
|
||||
|
@ -7163,7 +7163,7 @@ async fn test_copilot_disabled_globs(
|
|||
);
|
||||
multibuffer
|
||||
});
|
||||
let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).detach(cx);
|
||||
let editor = cx.add_window(|cx| build_editor(multibuffer, cx)).root(cx);
|
||||
|
||||
let mut copilot_requests = copilot_lsp
|
||||
.handle_request::<copilot::request::GetCompletions, _, _>(move |_params, _cx| async move {
|
||||
|
@ -7244,7 +7244,7 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) {
|
|||
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
|
|
@ -3007,7 +3007,7 @@ mod tests {
|
|||
let buffer = MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx);
|
||||
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
|
||||
|
||||
let layouts = editor.update(cx, |editor, cx| {
|
||||
|
@ -3028,7 +3028,7 @@ mod tests {
|
|||
let buffer = MultiBuffer::build_simple("", cx);
|
||||
Editor::new(EditorMode::Full, buffer, None, None, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.set_placeholder_text("hello", cx);
|
||||
|
@ -3240,7 +3240,7 @@ mod tests {
|
|||
let buffer = MultiBuffer::build_simple(&input_text, cx);
|
||||
Editor::new(editor_mode, buffer, None, None, cx)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
let mut element = EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx)));
|
||||
let (_, layout_state) = editor.update(cx, |editor, cx| {
|
||||
|
|
|
@ -1138,7 +1138,7 @@ mod tests {
|
|||
let project = Project::test(fs, ["/a".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -1840,7 +1840,7 @@ mod tests {
|
|||
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -1995,7 +1995,7 @@ mod tests {
|
|||
});
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -2083,7 +2083,7 @@ mod tests {
|
|||
cx.foreground().run_until_parked();
|
||||
let editor = cx
|
||||
.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let editor_edited = Arc::new(AtomicBool::new(false));
|
||||
let fake_server = fake_servers.next().await.unwrap();
|
||||
let closure_editor_edited = Arc::clone(&editor_edited);
|
||||
|
@ -2337,7 +2337,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
|||
});
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
@ -2384,7 +2384,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
|||
cx.foreground().run_until_parked();
|
||||
let editor = cx
|
||||
.add_window(|cx| Editor::for_multibuffer(multibuffer, Some(project.clone()), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let editor_edited = Arc::new(AtomicBool::new(false));
|
||||
let fake_server = fake_servers.next().await.unwrap();
|
||||
let closure_editor_edited = Arc::clone(&editor_edited);
|
||||
|
@ -2574,7 +2574,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
|||
project.update(cx, |project, _| project.languages().add(Arc::new(language)));
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = workspace.update(cx, |workspace, cx| {
|
||||
workspace.project().read_with(cx, |project, cx| {
|
||||
project.worktrees(cx).next().unwrap().read(cx).id()
|
||||
|
|
|
@ -842,7 +842,7 @@ mod tests {
|
|||
let project = Project::test(app_state.fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let finder = cx
|
||||
.add_window(|cx| {
|
||||
Picker::new(
|
||||
|
@ -856,7 +856,7 @@ mod tests {
|
|||
cx,
|
||||
)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
let query = test_path_like("hi");
|
||||
finder
|
||||
|
@ -940,7 +940,7 @@ mod tests {
|
|||
.await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let finder = cx
|
||||
.add_window(|cx| {
|
||||
Picker::new(
|
||||
|
@ -954,7 +954,7 @@ mod tests {
|
|||
cx,
|
||||
)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
finder
|
||||
.update(cx, |f, cx| {
|
||||
f.delegate_mut().spawn_search(test_path_like("hi"), cx)
|
||||
|
@ -980,7 +980,7 @@ mod tests {
|
|||
.await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let finder = cx
|
||||
.add_window(|cx| {
|
||||
Picker::new(
|
||||
|
@ -994,7 +994,7 @@ mod tests {
|
|||
cx,
|
||||
)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
// Even though there is only one worktree, that worktree's filename
|
||||
// is included in the matching, because the worktree is a single file.
|
||||
|
@ -1051,7 +1051,7 @@ mod tests {
|
|||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let worktree_id = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1);
|
||||
|
@ -1078,7 +1078,7 @@ mod tests {
|
|||
cx,
|
||||
)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
finder
|
||||
.update(cx, |f, cx| {
|
||||
|
@ -1117,7 +1117,7 @@ mod tests {
|
|||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let finder = cx
|
||||
.add_window(|cx| {
|
||||
Picker::new(
|
||||
|
@ -1131,7 +1131,7 @@ mod tests {
|
|||
cx,
|
||||
)
|
||||
})
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
finder
|
||||
.update(cx, |f, cx| {
|
||||
f.delegate_mut().spawn_search(test_path_like("dir"), cx)
|
||||
|
|
|
@ -130,12 +130,12 @@ pub trait BorrowAppContext {
|
|||
}
|
||||
|
||||
pub trait BorrowWindowContext {
|
||||
type Return<T>;
|
||||
type Result<T>;
|
||||
|
||||
fn read_with<T, F>(&self, window_id: usize, f: F) -> Self::Return<T>
|
||||
fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&WindowContext) -> T;
|
||||
fn update<T, F>(&mut self, window_id: usize, f: F) -> Self::Return<T>
|
||||
fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&mut WindowContext) -> T;
|
||||
}
|
||||
|
@ -458,6 +458,26 @@ impl BorrowAppContext for AsyncAppContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl BorrowWindowContext for AsyncAppContext {
|
||||
type Result<T> = Option<T>;
|
||||
|
||||
fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&WindowContext) -> T,
|
||||
{
|
||||
self.0.borrow().read_with(|cx| cx.read_window(window_id, f))
|
||||
}
|
||||
|
||||
fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&mut WindowContext) -> T,
|
||||
{
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.update(|cx| cx.update_window(window_id, f))
|
||||
}
|
||||
}
|
||||
|
||||
type ActionCallback = dyn FnMut(&mut dyn AnyView, &dyn Action, &mut WindowContext, usize);
|
||||
type GlobalActionCallback = dyn FnMut(&dyn Action, &mut AppContext);
|
||||
|
||||
|
@ -2162,6 +2182,24 @@ impl BorrowAppContext for AppContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl BorrowWindowContext for AppContext {
|
||||
type Result<T> = Option<T>;
|
||||
|
||||
fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&WindowContext) -> T,
|
||||
{
|
||||
AppContext::read_window(self, window_id, f)
|
||||
}
|
||||
|
||||
fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&mut WindowContext) -> T,
|
||||
{
|
||||
AppContext::update_window(self, window_id, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParentId {
|
||||
View(usize),
|
||||
|
@ -3360,14 +3398,18 @@ impl<V> BorrowAppContext for ViewContext<'_, '_, V> {
|
|||
}
|
||||
|
||||
impl<V> BorrowWindowContext for ViewContext<'_, '_, V> {
|
||||
type Return<T> = T;
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_with(&*self.window_context, window_id, f)
|
||||
fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_window_with(&*self.window_context, window_id, f)
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::update(&mut *self.window_context, window_id, f)
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
f: F,
|
||||
) -> T {
|
||||
BorrowWindowContext::update_window(&mut *self.window_context, window_id, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3467,14 +3509,18 @@ impl<V: View> BorrowAppContext for LayoutContext<'_, '_, '_, V> {
|
|||
}
|
||||
|
||||
impl<V: View> BorrowWindowContext for LayoutContext<'_, '_, '_, V> {
|
||||
type Return<T> = T;
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_with(&*self.view_context, window_id, f)
|
||||
fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_window_with(&*self.view_context, window_id, f)
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::update(&mut *self.view_context, window_id, f)
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
f: F,
|
||||
) -> T {
|
||||
BorrowWindowContext::update_window(&mut *self.view_context, window_id, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3521,14 +3567,18 @@ impl<V: View> BorrowAppContext for EventContext<'_, '_, '_, V> {
|
|||
}
|
||||
|
||||
impl<V: View> BorrowWindowContext for EventContext<'_, '_, '_, V> {
|
||||
type Return<T> = T;
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_with(&*self.view_context, window_id, f)
|
||||
fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_window_with(&*self.view_context, window_id, f)
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::update(&mut *self.view_context, window_id, f)
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
f: F,
|
||||
) -> T {
|
||||
BorrowWindowContext::update_window(&mut *self.view_context, window_id, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3830,32 +3880,16 @@ impl<V: View> WindowHandle<V> {
|
|||
self.any_handle.id()
|
||||
}
|
||||
|
||||
pub fn root(&self, cx: &impl BorrowAppContext) -> ViewHandle<V> {
|
||||
pub fn root<C: BorrowWindowContext>(&self, cx: &C) -> C::Result<ViewHandle<V>> {
|
||||
self.read_with(cx, |cx| cx.root_view().clone().downcast().unwrap())
|
||||
}
|
||||
|
||||
/// Keep this window open until it's explicitly closed.
|
||||
//
|
||||
// TODO: Implement window dropping behavior when we don't call this.
|
||||
pub fn detach(mut self, cx: &impl BorrowAppContext) -> ViewHandle<V> {
|
||||
let root = self.root(cx);
|
||||
let ref_counts = self.any_handle.ref_counts.take();
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
ref_counts
|
||||
.unwrap()
|
||||
.lock()
|
||||
.leak_detector
|
||||
.lock()
|
||||
.handle_dropped(self.id(), self.any_handle.handle_id);
|
||||
root
|
||||
}
|
||||
|
||||
pub fn read_with<C, F, R>(&self, cx: &C, read: F) -> R
|
||||
pub fn read_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowAppContext,
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&WindowContext) -> R,
|
||||
{
|
||||
cx.read_with(|cx| cx.read_window(self.id(), read).unwrap())
|
||||
cx.read_window_with(self.id(), |cx| read(cx))
|
||||
}
|
||||
|
||||
pub fn update<C, F, R>(&self, cx: &mut C, update: F) -> R
|
||||
|
@ -3891,9 +3925,9 @@ impl<V: View> WindowHandle<V> {
|
|||
root_view.read(cx)
|
||||
}
|
||||
|
||||
pub fn read_root_with<C, F, R>(&self, cx: &C, read: F) -> R
|
||||
pub fn read_root_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowAppContext,
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&V, &ViewContext<V>) -> R,
|
||||
{
|
||||
self.read_with(cx, |cx| {
|
||||
|
@ -4021,25 +4055,25 @@ impl<T: View> ViewHandle<T> {
|
|||
cx.read_view(self)
|
||||
}
|
||||
|
||||
pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> C::Return<S>
|
||||
pub fn read_with<C, F, S>(&self, cx: &C, read: F) -> C::Result<S>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&T, &ViewContext<T>) -> S,
|
||||
{
|
||||
cx.read_with(self.window_id, |cx| {
|
||||
cx.read_window_with(self.window_id, |cx| {
|
||||
let cx = ViewContext::immutable(cx, self.view_id);
|
||||
read(cx.read_view(self), &cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> C::Return<S>
|
||||
pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> C::Result<S>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
|
||||
{
|
||||
let mut update = Some(update);
|
||||
|
||||
cx.update(self.window_id, |cx| {
|
||||
cx.update_window(self.window_id, |cx| {
|
||||
cx.update_view(self, &mut |view, cx| {
|
||||
let update = update.take().unwrap();
|
||||
update(view, cx)
|
||||
|
@ -5005,7 +5039,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[crate::test(self)]
|
||||
fn test_entity_release_hooks(cx: &mut AppContext) {
|
||||
fn test_entity_release_hooks(cx: &mut TestAppContext) {
|
||||
struct Model {
|
||||
released: Rc<Cell<bool>>,
|
||||
}
|
||||
|
@ -5048,7 +5082,7 @@ mod tests {
|
|||
let model = cx.add_model(|_| Model {
|
||||
released: model_released.clone(),
|
||||
});
|
||||
let window = cx.add_window(Default::default(), |_| View {
|
||||
let window = cx.add_window(|_| View {
|
||||
released: view_released.clone(),
|
||||
});
|
||||
let view = window.root(cx);
|
||||
|
@ -5056,16 +5090,18 @@ mod tests {
|
|||
assert!(!model_released.get());
|
||||
assert!(!view_released.get());
|
||||
|
||||
cx.observe_release(&model, {
|
||||
let model_release_observed = model_release_observed.clone();
|
||||
move |_, _| model_release_observed.set(true)
|
||||
})
|
||||
.detach();
|
||||
cx.observe_release(&view, {
|
||||
let view_release_observed = view_release_observed.clone();
|
||||
move |_, _| view_release_observed.set(true)
|
||||
})
|
||||
.detach();
|
||||
cx.update(|cx| {
|
||||
cx.observe_release(&model, {
|
||||
let model_release_observed = model_release_observed.clone();
|
||||
move |_, _| model_release_observed.set(true)
|
||||
})
|
||||
.detach();
|
||||
cx.observe_release(&view, {
|
||||
let view_release_observed = view_release_observed.clone();
|
||||
move |_, _| view_release_observed.set(true)
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
|
||||
cx.update(move |_| {
|
||||
drop(model);
|
||||
|
@ -5795,7 +5831,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[crate::test(self)]
|
||||
fn test_dispatch_action(cx: &mut AppContext) {
|
||||
fn test_dispatch_action(cx: &mut TestAppContext) {
|
||||
struct ViewA {
|
||||
id: usize,
|
||||
child: Option<AnyViewHandle>,
|
||||
|
@ -5846,68 +5882,70 @@ mod tests {
|
|||
impl_actions!(test, [Action]);
|
||||
|
||||
let actions = Rc::new(RefCell::new(Vec::new()));
|
||||
|
||||
cx.add_global_action({
|
||||
let actions = actions.clone();
|
||||
move |_: &Action, _: &mut AppContext| {
|
||||
actions.borrow_mut().push("global".to_string());
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewA, action: &Action, cx| {
|
||||
assert_eq!(action.0, "bar");
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} a", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewA, _: &Action, cx| {
|
||||
if view.id != 1 {
|
||||
cx.add_view(|cx| {
|
||||
cx.propagate_action(); // Still works on a nested ViewContext
|
||||
ViewB { id: 5, child: None }
|
||||
});
|
||||
}
|
||||
actions.borrow_mut().push(format!("{} b", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewB, _: &Action, cx| {
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} c", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewB, _: &Action, cx| {
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} d", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.capture_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewA, _: &Action, cx| {
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} capture", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
let observed_actions = Rc::new(RefCell::new(Vec::new()));
|
||||
cx.observe_actions({
|
||||
let observed_actions = observed_actions.clone();
|
||||
move |action_id, _| observed_actions.borrow_mut().push(action_id)
|
||||
})
|
||||
.detach();
|
||||
|
||||
let window = cx.add_window(Default::default(), |_| ViewA { id: 1, child: None });
|
||||
cx.update(|cx| {
|
||||
cx.add_global_action({
|
||||
let actions = actions.clone();
|
||||
move |_: &Action, _: &mut AppContext| {
|
||||
actions.borrow_mut().push("global".to_string());
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewA, action: &Action, cx| {
|
||||
assert_eq!(action.0, "bar");
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} a", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewA, _: &Action, cx| {
|
||||
if view.id != 1 {
|
||||
cx.add_view(|cx| {
|
||||
cx.propagate_action(); // Still works on a nested ViewContext
|
||||
ViewB { id: 5, child: None }
|
||||
});
|
||||
}
|
||||
actions.borrow_mut().push(format!("{} b", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewB, _: &Action, cx| {
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} c", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.add_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewB, _: &Action, cx| {
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} d", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.capture_action({
|
||||
let actions = actions.clone();
|
||||
move |view: &mut ViewA, _: &Action, cx| {
|
||||
cx.propagate_action();
|
||||
actions.borrow_mut().push(format!("{} capture", view.id));
|
||||
}
|
||||
});
|
||||
|
||||
cx.observe_actions({
|
||||
let observed_actions = observed_actions.clone();
|
||||
move |action_id, _| observed_actions.borrow_mut().push(action_id)
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
|
||||
let window = cx.add_window(|_| ViewA { id: 1, child: None });
|
||||
let view_1 = window.root(cx);
|
||||
let view_2 = window.update(cx, |cx| {
|
||||
let child = cx.add_view(|_| ViewB { id: 2, child: None });
|
||||
|
@ -5956,7 +5994,7 @@ mod tests {
|
|||
|
||||
// Remove view_1, which doesn't propagate the action
|
||||
|
||||
let window = cx.add_window(Default::default(), |_| ViewB { id: 2, child: None });
|
||||
let window = cx.add_window(|_| ViewB { id: 2, child: None });
|
||||
let view_2 = window.root(cx);
|
||||
let view_3 = window.update(cx, |cx| {
|
||||
let child = cx.add_view(|_| ViewA { id: 3, child: None });
|
||||
|
@ -6457,7 +6495,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[crate::test(self)]
|
||||
fn test_refresh_windows(cx: &mut AppContext) {
|
||||
fn test_refresh_windows(cx: &mut TestAppContext) {
|
||||
struct View(usize);
|
||||
|
||||
impl super::Entity for View {
|
||||
|
@ -6474,7 +6512,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
let window = cx.add_window(Default::default(), |_| View(0));
|
||||
let window = cx.add_window(|_| View(0));
|
||||
let root_view = window.root(cx);
|
||||
window.update(cx, |cx| {
|
||||
assert_eq!(
|
||||
|
|
|
@ -406,16 +406,20 @@ impl BorrowAppContext for TestAppContext {
|
|||
}
|
||||
|
||||
impl BorrowWindowContext for TestAppContext {
|
||||
type Return<T> = T;
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
self.cx
|
||||
.borrow()
|
||||
.read_window(window_id, f)
|
||||
.expect("window was closed")
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
f: F,
|
||||
) -> T {
|
||||
self.cx
|
||||
.borrow_mut()
|
||||
.update_window(window_id, f)
|
||||
|
|
|
@ -142,9 +142,9 @@ impl BorrowAppContext for WindowContext<'_> {
|
|||
}
|
||||
|
||||
impl BorrowWindowContext for WindowContext<'_> {
|
||||
type Return<T> = T;
|
||||
type Result<T> = T;
|
||||
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
fn read_window_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
if self.window_id == window_id {
|
||||
f(self)
|
||||
} else {
|
||||
|
@ -152,7 +152,11 @@ impl BorrowWindowContext for WindowContext<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
f: F,
|
||||
) -> T {
|
||||
if self.window_id == window_id {
|
||||
f(self)
|
||||
} else {
|
||||
|
|
|
@ -63,7 +63,7 @@ async fn test_lsp_logs(cx: &mut TestAppContext) {
|
|||
|
||||
let log_view = cx
|
||||
.add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
language_server.notify::<lsp::notification::LogMessage>(lsp::LogMessageParams {
|
||||
message: "hello from the server".into(),
|
||||
|
|
|
@ -1782,7 +1782,7 @@ mod tests {
|
|||
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
assert_eq!(
|
||||
visible_entries_as_strings(&panel, 0..50, cx),
|
||||
|
@ -2327,7 +2327,7 @@ mod tests {
|
|||
let project = Project::test(fs.clone(), ["/root1".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
panel.update(cx, |panel, cx| {
|
||||
|
@ -2641,7 +2641,7 @@ mod tests {
|
|||
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
let new_search_events_count = Arc::new(AtomicUsize::new(0));
|
||||
|
@ -2730,7 +2730,7 @@ mod tests {
|
|||
let project = Project::test(fs.clone(), ["/project_root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
panel.update(cx, |panel, cx| {
|
||||
|
|
|
@ -1449,7 +1449,7 @@ pub mod tests {
|
|||
let search = cx.add_model(|cx| ProjectSearch::new(project, cx));
|
||||
let search_view = cx
|
||||
.add_window(|cx| ProjectSearchView::new(search.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
search_view.update(cx, |search_view, cx| {
|
||||
search_view
|
||||
|
@ -1754,7 +1754,7 @@ pub mod tests {
|
|||
});
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
let active_item = cx.read(|cx| {
|
||||
workspace
|
||||
|
|
|
@ -1072,7 +1072,7 @@ mod tests {
|
|||
let project = Project::test(params.fs.clone(), [], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
(project, workspace)
|
||||
}
|
||||
|
|
|
@ -793,68 +793,60 @@ impl Workspace {
|
|||
DB.next_id().await.unwrap_or(0)
|
||||
};
|
||||
|
||||
let window = requesting_window_id
|
||||
.and_then(|window_id| {
|
||||
cx.update(|cx| {
|
||||
cx.replace_root_view(window_id, |cx| {
|
||||
Workspace::new(
|
||||
workspace_id,
|
||||
project_handle.clone(),
|
||||
app_state.clone(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
let window = requesting_window_id.and_then(|window_id| {
|
||||
cx.update(|cx| {
|
||||
cx.replace_root_view(window_id, |cx| {
|
||||
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
|
||||
})
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let window_bounds_override = window_bounds_env_override(&cx);
|
||||
let (bounds, display) = if let Some(bounds) = window_bounds_override {
|
||||
(Some(bounds), None)
|
||||
} else {
|
||||
serialized_workspace
|
||||
.as_ref()
|
||||
.and_then(|serialized_workspace| {
|
||||
let display = serialized_workspace.display?;
|
||||
let mut bounds = serialized_workspace.bounds?;
|
||||
});
|
||||
let window = window.unwrap_or_else(|| {
|
||||
let window_bounds_override = window_bounds_env_override(&cx);
|
||||
let (bounds, display) = if let Some(bounds) = window_bounds_override {
|
||||
(Some(bounds), None)
|
||||
} else {
|
||||
serialized_workspace
|
||||
.as_ref()
|
||||
.and_then(|serialized_workspace| {
|
||||
let display = serialized_workspace.display?;
|
||||
let mut bounds = serialized_workspace.bounds?;
|
||||
|
||||
// Stored bounds are relative to the containing display.
|
||||
// So convert back to global coordinates if that screen still exists
|
||||
if let WindowBounds::Fixed(mut window_bounds) = bounds {
|
||||
if let Some(screen) = cx.platform().screen_by_id(display) {
|
||||
let screen_bounds = screen.bounds();
|
||||
window_bounds.set_origin_x(
|
||||
window_bounds.origin_x() + screen_bounds.origin_x(),
|
||||
);
|
||||
window_bounds.set_origin_y(
|
||||
window_bounds.origin_y() + screen_bounds.origin_y(),
|
||||
);
|
||||
bounds = WindowBounds::Fixed(window_bounds);
|
||||
} else {
|
||||
// Screen no longer exists. Return none here.
|
||||
return None;
|
||||
}
|
||||
// Stored bounds are relative to the containing display.
|
||||
// So convert back to global coordinates if that screen still exists
|
||||
if let WindowBounds::Fixed(mut window_bounds) = bounds {
|
||||
if let Some(screen) = cx.platform().screen_by_id(display) {
|
||||
let screen_bounds = screen.bounds();
|
||||
window_bounds.set_origin_x(
|
||||
window_bounds.origin_x() + screen_bounds.origin_x(),
|
||||
);
|
||||
window_bounds.set_origin_y(
|
||||
window_bounds.origin_y() + screen_bounds.origin_y(),
|
||||
);
|
||||
bounds = WindowBounds::Fixed(window_bounds);
|
||||
} else {
|
||||
// Screen no longer exists. Return none here.
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Some((bounds, display))
|
||||
})
|
||||
.unzip()
|
||||
};
|
||||
Some((bounds, display))
|
||||
})
|
||||
.unzip()
|
||||
};
|
||||
|
||||
// Use the serialized workspace to construct the new window
|
||||
cx.add_window(
|
||||
(app_state.build_window_options)(bounds, display, cx.platform().as_ref()),
|
||||
|cx| {
|
||||
Workspace::new(
|
||||
workspace_id,
|
||||
project_handle.clone(),
|
||||
app_state.clone(),
|
||||
cx,
|
||||
)
|
||||
},
|
||||
)
|
||||
});
|
||||
// Use the serialized workspace to construct the new window
|
||||
cx.add_window(
|
||||
(app_state.build_window_options)(bounds, display, cx.platform().as_ref()),
|
||||
|cx| {
|
||||
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
// We haven't yielded the main thread since obtaining the window handle,
|
||||
// so the window exists.
|
||||
let workspace = window.root(&cx).unwrap();
|
||||
|
||||
let workspace = window.root(&cx);
|
||||
(app_state.initialize_workspace)(
|
||||
workspace.downgrade(),
|
||||
serialized_workspace.is_some(),
|
||||
|
@ -3985,7 +3977,7 @@ pub fn join_remote_project(
|
|||
),
|
||||
|cx| Workspace::new(0, project, app_state.clone(), cx),
|
||||
);
|
||||
let workspace = window.root(&cx);
|
||||
let workspace = window.root(&cx).unwrap();
|
||||
(app_state.initialize_workspace)(
|
||||
workspace.downgrade(),
|
||||
false,
|
||||
|
|
|
@ -985,7 +985,7 @@ mod tests {
|
|||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
let file1 = entries[0].clone();
|
||||
|
@ -1566,7 +1566,7 @@ mod tests {
|
|||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project.clone(), cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
|
@ -1845,7 +1845,7 @@ mod tests {
|
|||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.detach(cx);
|
||||
.root(cx);
|
||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue