mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 21:52:54 +03:00
WIP
This commit is contained in:
parent
dcf8b00656
commit
adc50469ff
39
Cargo.lock
generated
39
Cargo.lock
generated
@ -1649,6 +1649,12 @@ dependencies = [
|
||||
"theme",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
||||
|
||||
[[package]]
|
||||
name = "copilot"
|
||||
version = "0.1.0"
|
||||
@ -2133,6 +2139,19 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version 0.4.0",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dhat"
|
||||
version = "0.3.2"
|
||||
@ -3096,6 +3115,7 @@ dependencies = [
|
||||
"core-graphics",
|
||||
"core-text",
|
||||
"ctor",
|
||||
"derive_more",
|
||||
"dhat",
|
||||
"env_logger 0.9.3",
|
||||
"etagere",
|
||||
@ -5106,7 +5126,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
"rustc_version 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6276,7 +6296,16 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
|
||||
dependencies = [
|
||||
"semver",
|
||||
"semver 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver 1.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6716,6 +6745,12 @@ dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.10.2"
|
||||
|
@ -79,6 +79,7 @@ resolver = "2"
|
||||
anyhow = { version = "1.0.57" }
|
||||
async-trait = { version = "0.1" }
|
||||
ctor = { version = "0.1" }
|
||||
derive_more = { version = "0.99.17" }
|
||||
env_logger = { version = "0.9" }
|
||||
futures = { version = "0.3" }
|
||||
globset = { version = "0.4" }
|
||||
|
@ -3446,7 +3446,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
|
||||
let editor_a = window_a.add_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
|
||||
let mut editor_cx_a = EditorTestContext {
|
||||
cx: cx_a,
|
||||
window_id: window_a.window_id(),
|
||||
window_id: window_a.id(),
|
||||
editor: editor_a,
|
||||
};
|
||||
|
||||
@ -3459,7 +3459,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
|
||||
let editor_b = window_b.add_view(cx_b, |cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
|
||||
let mut editor_cx_b = EditorTestContext {
|
||||
cx: cx_b,
|
||||
window_id: window_b.window_id(),
|
||||
window_id: window_b.id(),
|
||||
editor: editor_b,
|
||||
};
|
||||
|
||||
|
@ -49,7 +49,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
|_| IncomingCallNotification::new(incoming_call.clone(), app_state.clone()),
|
||||
);
|
||||
|
||||
notification_windows.push(window.window_id());
|
||||
notification_windows.push(window.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
|
||||
notification_windows
|
||||
.entry(*project_id)
|
||||
.or_insert(Vec::new())
|
||||
.push(window.window_id());
|
||||
.push(window.id());
|
||||
}
|
||||
}
|
||||
room::Event::RemoteProjectUnshared { project_id } => {
|
||||
|
@ -297,7 +297,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), [], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let editor = cx.add_view(window_id, |cx| {
|
||||
let mut editor = Editor::single_line(None, cx);
|
||||
editor.set_text("abc", cx);
|
||||
|
@ -857,7 +857,7 @@ mod tests {
|
||||
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
// Create some diagnostics
|
||||
project.update(cx, |project, cx| {
|
||||
@ -1252,7 +1252,7 @@ mod tests {
|
||||
let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
let view = cx.add_view(window_id, |cx| {
|
||||
ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx)
|
||||
|
@ -525,7 +525,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
|
||||
cx.add_view(window_id, |cx| {
|
||||
let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx);
|
||||
|
@ -99,7 +99,7 @@ impl<'a> EditorLspTestContext<'a> {
|
||||
Self {
|
||||
cx: EditorTestContext {
|
||||
cx,
|
||||
window_id: window.window_id(),
|
||||
window_id: window.id(),
|
||||
editor,
|
||||
},
|
||||
lsp,
|
||||
|
@ -39,7 +39,7 @@ impl<'a> EditorTestContext<'a> {
|
||||
let editor = window.root(cx);
|
||||
Self {
|
||||
cx,
|
||||
window_id: window.window_id(),
|
||||
window_id: window.id(),
|
||||
editor,
|
||||
}
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
cx.dispatch_action(window.window_id(), Toggle);
|
||||
cx.dispatch_action(window.id(), Toggle);
|
||||
|
||||
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
||||
finder
|
||||
@ -632,8 +632,8 @@ mod tests {
|
||||
});
|
||||
|
||||
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
|
||||
cx.dispatch_action(window.window_id(), SelectNext);
|
||||
cx.dispatch_action(window.window_id(), Confirm);
|
||||
cx.dispatch_action(window.id(), SelectNext);
|
||||
cx.dispatch_action(window.id(), Confirm);
|
||||
active_pane
|
||||
.condition(cx, |pane, _| pane.active_item().is_some())
|
||||
.await;
|
||||
@ -674,7 +674,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
cx.dispatch_action(window.window_id(), Toggle);
|
||||
cx.dispatch_action(window.id(), Toggle);
|
||||
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
||||
|
||||
let file_query = &first_file_name[..3];
|
||||
@ -706,8 +706,8 @@ mod tests {
|
||||
});
|
||||
|
||||
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
|
||||
cx.dispatch_action(window.window_id(), SelectNext);
|
||||
cx.dispatch_action(window.window_id(), Confirm);
|
||||
cx.dispatch_action(window.id(), SelectNext);
|
||||
cx.dispatch_action(window.id(), Confirm);
|
||||
active_pane
|
||||
.condition(cx, |pane, _| pane.active_item().is_some())
|
||||
.await;
|
||||
@ -758,7 +758,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
cx.dispatch_action(window.window_id(), Toggle);
|
||||
cx.dispatch_action(window.id(), Toggle);
|
||||
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
||||
|
||||
let file_query = &first_file_name[..3];
|
||||
@ -790,8 +790,8 @@ mod tests {
|
||||
});
|
||||
|
||||
let active_pane = cx.read(|cx| workspace.read(cx).active_pane().clone());
|
||||
cx.dispatch_action(window.window_id(), SelectNext);
|
||||
cx.dispatch_action(window.window_id(), Confirm);
|
||||
cx.dispatch_action(window.id(), SelectNext);
|
||||
cx.dispatch_action(window.id(), Confirm);
|
||||
active_pane
|
||||
.condition(cx, |pane, _| pane.active_item().is_some())
|
||||
.await;
|
||||
@ -1168,7 +1168,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), ["/src".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let worktree_id = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1);
|
||||
@ -1376,7 +1376,7 @@ mod tests {
|
||||
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let worktree_id = cx.read(|cx| {
|
||||
let worktrees = workspace.read(cx).worktrees(cx).collect::<Vec<_>>();
|
||||
assert_eq!(worktrees.len(), 1,);
|
||||
|
@ -22,6 +22,7 @@ sqlez = { path = "../sqlez" }
|
||||
async-task = "4.0.3"
|
||||
backtrace = { version = "0.3", optional = true }
|
||||
ctor.workspace = true
|
||||
derive_more.workspace = true
|
||||
dhat = { version = "0.3", optional = true }
|
||||
env_logger = { version = "0.9", optional = true }
|
||||
etagere = "0.2"
|
||||
|
@ -23,6 +23,7 @@ use std::{
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use derive_more::Deref;
|
||||
use parking_lot::Mutex;
|
||||
use postage::oneshot;
|
||||
use smallvec::SmallVec;
|
||||
@ -132,11 +133,13 @@ pub trait BorrowAppContext {
|
||||
pub trait BorrowWindowContext {
|
||||
type Result<T>;
|
||||
|
||||
fn read_window_with<T, F>(&self, window_id: usize, f: F) -> Self::Result<T>
|
||||
fn read_window_with<H, T, F>(&self, window_handle: H, f: F) -> Self::Result<T>
|
||||
where
|
||||
H: Into<AnyWindowHandle>,
|
||||
F: FnOnce(&WindowContext) -> T;
|
||||
fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
|
||||
fn update_window<H, T, F>(&mut self, window_handle: H, f: F) -> Self::Result<T>
|
||||
where
|
||||
H: Into<AnyWindowHandle>,
|
||||
F: FnOnce(&mut WindowContext) -> T;
|
||||
}
|
||||
|
||||
@ -300,13 +303,13 @@ impl App {
|
||||
result
|
||||
}
|
||||
|
||||
fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
callback: F,
|
||||
) -> Option<T> {
|
||||
fn update_window<H, T, F>(&mut self, handle: H, callback: F) -> Option<T>
|
||||
where
|
||||
H: Into<AnyWindowHandle>,
|
||||
F: FnOnce(&mut WindowContext) -> T,
|
||||
{
|
||||
let mut state = self.0.borrow_mut();
|
||||
let result = state.update_window(window_id, callback);
|
||||
let result = state.update_window(handle, callback);
|
||||
state.pending_notifications.clear();
|
||||
result
|
||||
}
|
||||
@ -333,6 +336,10 @@ impl AsyncAppContext {
|
||||
self.0.borrow_mut().update(callback)
|
||||
}
|
||||
|
||||
pub fn windows(&self) -> Vec<AnyWindowHandle> {
|
||||
self.0.borrow().windows().collect()
|
||||
}
|
||||
|
||||
pub fn read_window<T, F: FnOnce(&WindowContext) -> T>(
|
||||
&self,
|
||||
window_id: usize,
|
||||
@ -343,10 +350,10 @@ impl AsyncAppContext {
|
||||
|
||||
pub fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
handle: AnyWindowHandle,
|
||||
callback: F,
|
||||
) -> Option<T> {
|
||||
self.0.borrow_mut().update_window(window_id, callback)
|
||||
self.0.borrow_mut().update_window(handle, callback)
|
||||
}
|
||||
|
||||
pub fn debug_elements(&self, window_id: usize) -> Option<json::Value> {
|
||||
@ -359,14 +366,14 @@ impl AsyncAppContext {
|
||||
|
||||
pub fn dispatch_action(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
window: impl Into<AnyWindowHandle>,
|
||||
view_id: usize,
|
||||
action: &dyn Action,
|
||||
) -> Result<()> {
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.update_window(window_id, |window| {
|
||||
window.dispatch_action(Some(view_id), action);
|
||||
.update_window(window, |cx| {
|
||||
cx.dispatch_action(Some(view_id), action);
|
||||
})
|
||||
.ok_or_else(|| anyhow!("window not found"))
|
||||
}
|
||||
@ -380,22 +387,6 @@ impl AsyncAppContext {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn has_window(&self, window_id: usize) -> bool {
|
||||
self.read(|cx| cx.windows.contains_key(&window_id))
|
||||
}
|
||||
|
||||
pub fn window_is_active(&self, window_id: usize) -> bool {
|
||||
self.read(|cx| cx.windows.get(&window_id).map_or(false, |w| w.is_active))
|
||||
}
|
||||
|
||||
pub fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> {
|
||||
self.read(|cx| cx.windows.get(&window_id).map(|w| w.root_view().clone()))
|
||||
}
|
||||
|
||||
pub fn window_ids(&self) -> Vec<usize> {
|
||||
self.read(|cx| cx.windows.keys().copied().collect())
|
||||
}
|
||||
|
||||
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
|
||||
where
|
||||
T: Entity,
|
||||
@ -501,7 +492,7 @@ pub struct AppContext {
|
||||
models: HashMap<usize, Box<dyn AnyModel>>,
|
||||
views: HashMap<(usize, usize), Box<dyn AnyView>>,
|
||||
views_metadata: HashMap<(usize, usize), ViewMetadata>,
|
||||
windows: HashMap<usize, Window>,
|
||||
windows: HashMap<AnyWindowHandle, Window>,
|
||||
globals: HashMap<TypeId, Box<dyn Any>>,
|
||||
element_states: HashMap<ElementStateId, Box<dyn Any>>,
|
||||
background: Arc<executor::Background>,
|
||||
@ -818,22 +809,6 @@ impl AppContext {
|
||||
Some(callback(&window_context))
|
||||
}
|
||||
|
||||
pub fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
callback: F,
|
||||
) -> Option<T> {
|
||||
self.update(|app_context| {
|
||||
let mut window = app_context.windows.remove(&window_id)?;
|
||||
let mut window_context = WindowContext::mutable(app_context, &mut window, window_id);
|
||||
let result = callback(&mut window_context);
|
||||
if !window_context.removed {
|
||||
app_context.windows.insert(window_id, window);
|
||||
}
|
||||
Some(result)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update_active_window<T, F: FnOnce(&mut WindowContext) -> T>(
|
||||
&mut self,
|
||||
callback: F,
|
||||
@ -1331,43 +1306,40 @@ impl AppContext {
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
self.update(|this| {
|
||||
let window_id = post_inc(&mut this.next_id);
|
||||
let window = WindowHandle::<V>::new(post_inc(&mut this.next_id));
|
||||
let platform_window =
|
||||
this.platform
|
||||
.open_window(window_id, window_options, this.foreground.clone());
|
||||
let window = this.build_window(window_id, platform_window, build_root_view);
|
||||
this.windows.insert(window_id, window);
|
||||
WindowHandle::new(window_id)
|
||||
.open_window(window, window_options, this.foreground.clone());
|
||||
let window = this.build_window(window, platform_window, build_root_view);
|
||||
this.windows.insert(window.into(), window);
|
||||
window
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_status_bar_item<V, F>(&mut self, build_root_view: F) -> (usize, ViewHandle<V>)
|
||||
pub fn add_status_bar_item<V, F>(&mut self, build_root_view: F) -> WindowHandle<V>
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
self.update(|this| {
|
||||
let window_id = post_inc(&mut this.next_id);
|
||||
let platform_window = this.platform.add_status_item(window_id);
|
||||
let window = this.build_window(window_id, platform_window, build_root_view);
|
||||
let root_view = window.root_view().clone().downcast::<V>().unwrap();
|
||||
let handle = WindowHandle::<V>::new(post_inc(&mut this.next_id));
|
||||
let platform_window = this.platform.add_status_item(handle.id());
|
||||
let window = this.build_window(handle, platform_window, build_root_view);
|
||||
|
||||
this.windows.insert(window_id, window);
|
||||
this.update_window(window_id, |cx| {
|
||||
root_view.update(cx, |view, cx| view.focus_in(cx.handle().into_any(), cx))
|
||||
});
|
||||
|
||||
(window_id, root_view)
|
||||
this.windows.insert(handle.into(), window);
|
||||
handle.update_root(this, |view, cx| view.focus_in(cx.handle().into_any(), cx));
|
||||
handle
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_window<V, F>(
|
||||
pub fn build_window<H, V, F>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
handle: H,
|
||||
mut platform_window: Box<dyn platform::Window>,
|
||||
build_root_view: F,
|
||||
) -> Window
|
||||
where
|
||||
H: Into<AnyWindowHandle>,
|
||||
V: View,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
@ -1375,7 +1347,7 @@ impl AppContext {
|
||||
let mut app = self.upgrade();
|
||||
|
||||
platform_window.on_event(Box::new(move |event| {
|
||||
app.update_window(window_id, |cx| {
|
||||
app.update_window(handle, |cx| {
|
||||
if let Event::KeyDown(KeyDownEvent { keystroke, .. }) = &event {
|
||||
if cx.dispatch_keystroke(keystroke) {
|
||||
return true;
|
||||
@ -1391,35 +1363,35 @@ impl AppContext {
|
||||
{
|
||||
let mut app = self.upgrade();
|
||||
platform_window.on_active_status_change(Box::new(move |is_active| {
|
||||
app.update(|cx| cx.window_changed_active_status(window_id, is_active))
|
||||
app.update(|cx| cx.window_changed_active_status(handle, is_active))
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
let mut app = self.upgrade();
|
||||
platform_window.on_resize(Box::new(move || {
|
||||
app.update(|cx| cx.window_was_resized(window_id))
|
||||
app.update(|cx| cx.window_was_resized(handle))
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
let mut app = self.upgrade();
|
||||
platform_window.on_moved(Box::new(move || {
|
||||
app.update(|cx| cx.window_was_moved(window_id))
|
||||
app.update(|cx| cx.window_was_moved(handle))
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
let mut app = self.upgrade();
|
||||
platform_window.on_fullscreen(Box::new(move |is_fullscreen| {
|
||||
app.update(|cx| cx.window_was_fullscreen_changed(window_id, is_fullscreen))
|
||||
app.update(|cx| cx.window_was_fullscreen_changed(handle, is_fullscreen))
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
let mut app = self.upgrade();
|
||||
platform_window.on_close(Box::new(move || {
|
||||
app.update(|cx| cx.update_window(window_id, |cx| cx.remove_window()));
|
||||
app.update(|cx| cx.update_window(handle, |cx| cx.remove_window()));
|
||||
}));
|
||||
}
|
||||
|
||||
@ -1431,27 +1403,20 @@ impl AppContext {
|
||||
|
||||
platform_window.set_input_handler(Box::new(WindowInputHandler {
|
||||
app: self.upgrade().0,
|
||||
window_id,
|
||||
window_id: handle,
|
||||
}));
|
||||
|
||||
let mut window = Window::new(window_id, platform_window, self, build_root_view);
|
||||
let mut cx = WindowContext::mutable(self, &mut window, window_id);
|
||||
let mut window = Window::new(handle, platform_window, self, build_root_view);
|
||||
let mut cx = WindowContext::mutable(self, &mut window, handle);
|
||||
cx.layout(false).expect("initial layout should not error");
|
||||
let scene = cx.paint().expect("initial paint should not error");
|
||||
window.platform_window.present_scene(scene);
|
||||
window
|
||||
}
|
||||
|
||||
pub(crate) fn replace_root_view<V, F>(
|
||||
&mut self,
|
||||
window_id: usize,
|
||||
build_root_view: F,
|
||||
) -> Option<WindowHandle<V>>
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
self.update_window(window_id, |cx| cx.replace_root_view(build_root_view))
|
||||
pub fn windows(&self) -> impl Iterator<Item = AnyWindowHandle> {
|
||||
todo!();
|
||||
None.into_iter()
|
||||
}
|
||||
|
||||
pub fn read_view<T: View>(&self, handle: &ViewHandle<T>) -> &T {
|
||||
@ -2192,11 +2157,20 @@ impl BorrowWindowContext for AppContext {
|
||||
AppContext::read_window(self, window_id, f)
|
||||
}
|
||||
|
||||
fn update_window<T, F>(&mut self, window_id: usize, f: F) -> Self::Result<T>
|
||||
fn update_window<T, F>(&mut self, window: usize, f: F) -> Self::Result<T>
|
||||
where
|
||||
F: FnOnce(&mut WindowContext) -> T,
|
||||
{
|
||||
AppContext::update_window(self, window_id, f)
|
||||
self.update(|app_context| {
|
||||
let mut window = app_context.windows.remove(&window_handle)?;
|
||||
let mut window_context =
|
||||
WindowContext::mutable(app_context, &mut window, window_handle);
|
||||
let result = callback(&mut window_context);
|
||||
if !window_context.removed {
|
||||
app_context.windows.insert(window_handle, window);
|
||||
}
|
||||
Some(result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -3862,44 +3836,28 @@ impl<T> Clone for WeakModelHandle<T> {
|
||||
|
||||
impl<T> Copy for WeakModelHandle<T> {}
|
||||
|
||||
#[derive(Deref, Copy, Clone)]
|
||||
pub struct WindowHandle<T> {
|
||||
window_id: usize,
|
||||
#[deref]
|
||||
any_handle: AnyWindowHandle,
|
||||
root_view_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl<V: View> WindowHandle<V> {
|
||||
fn new(window_id: usize) -> Self {
|
||||
WindowHandle {
|
||||
window_id,
|
||||
any_handle: AnyWindowHandle {
|
||||
window_id,
|
||||
root_view_type: TypeId::of::<V>(),
|
||||
},
|
||||
root_view_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_id(&self) -> usize {
|
||||
self.window_id
|
||||
}
|
||||
|
||||
pub fn root<C: BorrowWindowContext>(&self, cx: &C) -> C::Result<ViewHandle<V>> {
|
||||
self.read_with(cx, |cx| cx.root_view().clone().downcast().unwrap())
|
||||
}
|
||||
|
||||
pub fn read_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&WindowContext) -> R,
|
||||
{
|
||||
cx.read_window_with(self.window_id(), |cx| read(cx))
|
||||
}
|
||||
|
||||
pub fn update<C, F, R>(&self, cx: &mut C, update: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&mut WindowContext) -> R,
|
||||
{
|
||||
cx.update_window(self.window_id(), update)
|
||||
}
|
||||
|
||||
pub fn read_root_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
@ -3918,7 +3876,7 @@ impl<V: View> WindowHandle<V> {
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
{
|
||||
cx.update_window(self.window_id, |cx| {
|
||||
cx.update_window(*self, |cx| {
|
||||
cx.root_view()
|
||||
.clone()
|
||||
.downcast::<V>()
|
||||
@ -3927,6 +3885,53 @@ impl<V: View> WindowHandle<V> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn replace_root<C, F>(&self, cx: &mut C, build_root: F) -> C::Result<ViewHandle<V>>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
cx.update_window(self.into_any(), |cx| {
|
||||
let root_view = self.add_view(cx, |cx| build_root(cx));
|
||||
cx.window.root_view = Some(root_view.clone().into_any());
|
||||
cx.window.focused_view_id = Some(root_view.id());
|
||||
root_view
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Into<AnyWindowHandle> for WindowHandle<V> {
|
||||
fn into(self) -> AnyWindowHandle {
|
||||
self.any_handle
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct AnyWindowHandle {
|
||||
window_id: usize,
|
||||
root_view_type: TypeId,
|
||||
}
|
||||
|
||||
impl AnyWindowHandle {
|
||||
pub fn id(&self) -> usize {
|
||||
self.window_id
|
||||
}
|
||||
|
||||
pub fn read_with<C, F, R>(&self, cx: &C, read: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&WindowContext) -> R,
|
||||
{
|
||||
cx.read_window_with(self.window_id, |cx| read(cx))
|
||||
}
|
||||
|
||||
pub fn update<C, F, R>(&self, cx: &mut C, update: F) -> C::Result<R>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&mut WindowContext) -> R,
|
||||
{
|
||||
cx.update_window(self.window_id, update)
|
||||
}
|
||||
|
||||
pub fn add_view<C, U, F>(&self, cx: &mut C, build_view: F) -> C::Result<ViewHandle<U>>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
@ -3936,21 +3941,16 @@ impl<V: View> WindowHandle<V> {
|
||||
self.update(cx, |cx| cx.add_view(build_view))
|
||||
}
|
||||
|
||||
pub(crate) fn replace_root_view<C, F>(
|
||||
&self,
|
||||
cx: &mut C,
|
||||
build_root_view: F,
|
||||
) -> C::Result<ViewHandle<V>>
|
||||
where
|
||||
C: BorrowWindowContext,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
cx.update_window(self.window_id, |cx| {
|
||||
let root_view = self.add_view(cx, |cx| build_root_view(cx));
|
||||
cx.window.root_view = Some(root_view.clone().into_any());
|
||||
cx.window.focused_view_id = Some(root_view.id());
|
||||
root_view
|
||||
})
|
||||
pub fn root_is<V: View>(&self) -> bool {
|
||||
self.root_view_type == TypeId::of::<V>()
|
||||
}
|
||||
|
||||
pub fn is_active<C: BorrowWindowContext>(&self, cx: &C) -> C::Result<bool> {
|
||||
self.read_with(cx, |cx| cx.window.is_active)
|
||||
}
|
||||
|
||||
pub fn remove<C: BorrowWindowContext>(&self, cx: &mut C) -> C::Result<()> {
|
||||
self.update(cx, |cx| cx.remove_window())
|
||||
}
|
||||
}
|
||||
|
||||
@ -5390,7 +5390,7 @@ mod tests {
|
||||
TestView { events: Vec::new() }
|
||||
});
|
||||
|
||||
assert_eq!(window.read_root_with(cx, |view, _| assert_eq!(view.events, ["before notify"])));
|
||||
window.read_root_with(cx, |view, _| assert_eq!(view.events, ["before notify"]));
|
||||
}
|
||||
|
||||
#[crate::test(self)]
|
||||
@ -6227,7 +6227,7 @@ mod tests {
|
||||
|
||||
// Check that global actions do not have a binding, even if a binding does exist in another view
|
||||
assert_eq!(
|
||||
&available_actions(window.window_id(), view_1.id(), cx),
|
||||
&available_actions(window.id(), view_1.id(), cx),
|
||||
&[
|
||||
("test::Action1", vec![Keystroke::parse("a").unwrap()]),
|
||||
("test::GlobalAction", vec![])
|
||||
@ -6236,7 +6236,7 @@ mod tests {
|
||||
|
||||
// Check that view 1 actions and bindings are available even when called from view 2
|
||||
assert_eq!(
|
||||
&available_actions(window.window_id(), view_2.id(), cx),
|
||||
&available_actions(window.id(), view_2.id(), cx),
|
||||
&[
|
||||
("test::Action1", vec![Keystroke::parse("a").unwrap()]),
|
||||
("test::Action2", vec![Keystroke::parse("b").unwrap()]),
|
||||
@ -6299,7 +6299,7 @@ mod tests {
|
||||
]);
|
||||
});
|
||||
|
||||
let actions = cx.available_actions(window.window_id(), view.id());
|
||||
let actions = cx.available_actions(window.id(), view.id());
|
||||
assert_eq!(
|
||||
actions[0].1.as_any().downcast_ref::<ActionWithArg>(),
|
||||
Some(&ActionWithArg { arg: false })
|
||||
@ -6585,25 +6585,25 @@ mod tests {
|
||||
[("window 2", false), ("window 3", true)]
|
||||
);
|
||||
|
||||
cx.simulate_window_activation(Some(window_2.window_id()));
|
||||
cx.simulate_window_activation(Some(window_2.id()));
|
||||
assert_eq!(
|
||||
mem::take(&mut *events.borrow_mut()),
|
||||
[("window 3", false), ("window 2", true)]
|
||||
);
|
||||
|
||||
cx.simulate_window_activation(Some(window_1.window_id()));
|
||||
cx.simulate_window_activation(Some(window_1.id()));
|
||||
assert_eq!(
|
||||
mem::take(&mut *events.borrow_mut()),
|
||||
[("window 2", false), ("window 1", true)]
|
||||
);
|
||||
|
||||
cx.simulate_window_activation(Some(window_3.window_id()));
|
||||
cx.simulate_window_activation(Some(window_3.id()));
|
||||
assert_eq!(
|
||||
mem::take(&mut *events.borrow_mut()),
|
||||
[("window 1", false), ("window 3", true)]
|
||||
);
|
||||
|
||||
cx.simulate_window_activation(Some(window_3.window_id()));
|
||||
cx.simulate_window_activation(Some(window_3.id()));
|
||||
assert_eq!(mem::take(&mut *events.borrow_mut()), []);
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,9 @@ use crate::{
|
||||
keymap_matcher::{Binding, Keystroke},
|
||||
platform,
|
||||
platform::{Event, InputHandler, KeyDownEvent, Platform},
|
||||
Action, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache, Handle,
|
||||
ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakHandle,
|
||||
WindowContext, WindowHandle,
|
||||
Action, AnyWindowHandle, AppContext, BorrowAppContext, BorrowWindowContext, Entity, FontCache,
|
||||
Handle, ModelContext, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakHandle, WindowContext, WindowHandle,
|
||||
};
|
||||
use collections::BTreeMap;
|
||||
use futures::Future;
|
||||
@ -124,6 +124,13 @@ impl TestAppContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window<V: View>(&self, window_id: usize) -> Option<WindowHandle<V>> {
|
||||
self.cx
|
||||
.borrow()
|
||||
.read_window(window_id, |cx| cx.window())
|
||||
.flatten()
|
||||
}
|
||||
|
||||
pub fn read_window<T, F: FnOnce(&WindowContext) -> T>(
|
||||
&self,
|
||||
window_id: usize,
|
||||
@ -157,9 +164,9 @@ impl TestAppContext {
|
||||
.cx
|
||||
.borrow_mut()
|
||||
.add_window(Default::default(), build_root_view);
|
||||
self.simulate_window_activation(Some(window.window_id()));
|
||||
self.simulate_window_activation(Some(window.id()));
|
||||
|
||||
WindowHandle::new(window.window_id())
|
||||
WindowHandle::new(window.id())
|
||||
}
|
||||
|
||||
pub fn add_view<T, F>(&mut self, window_id: usize, build_view: F) -> ViewHandle<T>
|
||||
@ -191,10 +198,14 @@ impl TestAppContext {
|
||||
self.cx.borrow_mut().subscribe_global(callback)
|
||||
}
|
||||
|
||||
pub fn window_ids(&self) -> Vec<usize> {
|
||||
self.cx.borrow().windows.keys().copied().collect()
|
||||
pub fn windows(&self) -> impl Iterator<Item = AnyWindowHandle> {
|
||||
self.cx.borrow().windows()
|
||||
}
|
||||
|
||||
// pub fn window_ids(&self) -> Vec<usize> {
|
||||
// self.cx.borrow().windows.keys().copied().collect()
|
||||
// }
|
||||
|
||||
pub fn remove_all_windows(&mut self) {
|
||||
self.update(|cx| cx.windows.clear());
|
||||
}
|
||||
@ -311,15 +322,15 @@ impl TestAppContext {
|
||||
|
||||
pub fn simulate_window_activation(&self, to_activate: Option<usize>) {
|
||||
self.cx.borrow_mut().update(|cx| {
|
||||
let other_window_ids = cx
|
||||
let other_windows = cx
|
||||
.windows
|
||||
.keys()
|
||||
.filter(|window_id| Some(**window_id) != to_activate)
|
||||
.filter(|window| Some(window.id()) != to_activate)
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for window_id in other_window_ids {
|
||||
cx.window_changed_active_status(window_id, false)
|
||||
for window in other_windows {
|
||||
cx.window_changed_active_status(window.id(), false)
|
||||
}
|
||||
|
||||
if let Some(to_activate) = to_activate {
|
||||
|
@ -196,6 +196,16 @@ impl<'a> WindowContext<'a> {
|
||||
self.window_id
|
||||
}
|
||||
|
||||
pub fn window<V: View>(&self) -> Option<WindowHandle<V>> {
|
||||
self.window.root_view.as_ref().and_then(|root_view| {
|
||||
if root_view.is::<V>() {
|
||||
Some(WindowHandle::new(self.window_id))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn app_context(&mut self) -> &mut AppContext {
|
||||
&mut self.app_context
|
||||
}
|
||||
@ -1157,17 +1167,6 @@ impl<'a> WindowContext<'a> {
|
||||
self.window.platform_window.prompt(level, msg, answers)
|
||||
}
|
||||
|
||||
pub(crate) fn replace_root_view<V, F>(&mut self, build_root_view: F) -> WindowHandle<V>
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
{
|
||||
let root_view = self.add_view(|cx| build_root_view(cx));
|
||||
self.window.focused_view_id = Some(root_view.id());
|
||||
self.window.root_view = Some(root_view.into_any());
|
||||
WindowHandle::new(self.window_id)
|
||||
}
|
||||
|
||||
pub fn add_view<T, F>(&mut self, build_view: F) -> ViewHandle<T>
|
||||
where
|
||||
T: View,
|
||||
|
@ -1872,7 +1872,7 @@ mod tests {
|
||||
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
select_path(&panel, "root1", cx);
|
||||
@ -2225,7 +2225,7 @@ mod tests {
|
||||
let project = Project::test(fs.clone(), ["/root1".as_ref(), "/root2".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
select_path(&panel, "root1", cx);
|
||||
@ -2402,7 +2402,7 @@ mod tests {
|
||||
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
toggle_expand_dir(&panel, "src/test", cx);
|
||||
@ -2493,7 +2493,7 @@ mod tests {
|
||||
let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let panel = workspace.update(cx, |workspace, cx| ProjectPanel::new(workspace, cx));
|
||||
|
||||
select_path(&panel, "src/", cx);
|
||||
|
@ -328,7 +328,7 @@ mod tests {
|
||||
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
// Create the project symbols view.
|
||||
let symbols = cx.add_view(window_id, |cx| {
|
||||
|
@ -851,11 +851,11 @@ mod tests {
|
||||
});
|
||||
let window = cx.add_window(|_| EmptyView);
|
||||
|
||||
let editor = cx.add_view(window.window_id(), |cx| {
|
||||
let editor = cx.add_view(window.id(), |cx| {
|
||||
Editor::for_buffer(buffer.clone(), None, cx)
|
||||
});
|
||||
|
||||
let search_bar = cx.add_view(window.window_id(), |cx| {
|
||||
let search_bar = cx.add_view(window.id(), |cx| {
|
||||
let mut search_bar = BufferSearchBar::new(cx);
|
||||
search_bar.set_active_pane_item(Some(&editor), cx);
|
||||
search_bar.show(cx);
|
||||
@ -1232,7 +1232,7 @@ mod tests {
|
||||
);
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, buffer_text, cx));
|
||||
let window = cx.add_window(|_| EmptyView);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
let editor = cx.add_view(window_id, |cx| Editor::for_buffer(buffer.clone(), None, cx));
|
||||
|
||||
@ -1421,11 +1421,11 @@ mod tests {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, buffer_text, cx));
|
||||
let window = cx.add_window(|_| EmptyView);
|
||||
|
||||
let editor = cx.add_view(window.window_id(), |cx| {
|
||||
let editor = cx.add_view(window.id(), |cx| {
|
||||
Editor::for_buffer(buffer.clone(), None, cx)
|
||||
});
|
||||
|
||||
let search_bar = cx.add_view(window.window_id(), |cx| {
|
||||
let search_bar = cx.add_view(window.id(), |cx| {
|
||||
let mut search_bar = BufferSearchBar::new(cx);
|
||||
search_bar.set_active_pane_item(Some(&editor), cx);
|
||||
search_bar.show(cx);
|
||||
|
@ -1568,7 +1568,7 @@ pub mod tests {
|
||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
let active_item = cx.read(|cx| {
|
||||
workspace
|
||||
@ -1874,7 +1874,7 @@ pub mod tests {
|
||||
let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx)
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ use gpui::{
|
||||
},
|
||||
AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity,
|
||||
ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakViewHandle, WindowContext,
|
||||
WeakViewHandle, WindowContext, WindowHandle,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
@ -749,7 +749,7 @@ impl Workspace {
|
||||
fn new_local(
|
||||
abs_paths: Vec<PathBuf>,
|
||||
app_state: Arc<AppState>,
|
||||
requesting_window_id: Option<usize>,
|
||||
requesting_window: Option<WindowHandle<Workspace>>,
|
||||
cx: &mut AppContext,
|
||||
) -> Task<(
|
||||
WeakViewHandle<Workspace>,
|
||||
@ -793,55 +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 = 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?;
|
||||
let window = if let Some(window) = requesting_window {
|
||||
window.replace_root(&mut cx, |cx| {
|
||||
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
|
||||
});
|
||||
window
|
||||
} 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.
|
||||
@ -1227,14 +1232,14 @@ impl Workspace {
|
||||
|
||||
pub fn close_global(_: &CloseWindow, cx: &mut AppContext) {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let id = cx
|
||||
.window_ids()
|
||||
let window = cx
|
||||
.windows()
|
||||
.into_iter()
|
||||
.find(|&id| cx.window_is_active(id));
|
||||
if let Some(id) = id {
|
||||
.find(|window| window.is_active(&cx).unwrap_or(false));
|
||||
if let Some(window) = window {
|
||||
//This can only get called when the window's project connection has been lost
|
||||
//so we don't need to prompt the user for anything and instead just close the window
|
||||
cx.remove_window(id);
|
||||
window.remove(&mut cx);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
@ -1265,9 +1270,9 @@ impl Workspace {
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let workspace_count = cx
|
||||
.window_ids()
|
||||
.windows()
|
||||
.into_iter()
|
||||
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
|
||||
.filter(|window| window.root_is::<Workspace>())
|
||||
.count();
|
||||
|
||||
if let Some(active_call) = active_call {
|
||||
@ -1385,7 +1390,7 @@ impl Workspace {
|
||||
paths: Vec<PathBuf>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let window_id = cx.window_id();
|
||||
let window = cx.window::<Self>();
|
||||
let is_remote = self.project.read(cx).is_remote();
|
||||
let has_worktree = self.project.read(cx).worktrees(cx).next().is_some();
|
||||
let has_dirty_items = self.items(cx).any(|item| item.is_dirty(cx));
|
||||
@ -1397,15 +1402,15 @@ impl Workspace {
|
||||
let app_state = self.app_state.clone();
|
||||
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
let window_id_to_replace = if let Some(close_task) = close_task {
|
||||
let window_to_replace = if let Some(close_task) = close_task {
|
||||
if !close_task.await? {
|
||||
return Ok(());
|
||||
}
|
||||
Some(window_id)
|
||||
window
|
||||
} else {
|
||||
None
|
||||
};
|
||||
cx.update(|cx| open_paths(&paths, &app_state, window_id_to_replace, cx))
|
||||
cx.update(|cx| open_paths(&paths, &app_state, window_to_replace, cx))
|
||||
.await?;
|
||||
Ok(())
|
||||
})
|
||||
@ -3851,7 +3856,7 @@ pub async fn last_opened_workspace_paths() -> Option<WorkspaceLocation> {
|
||||
pub fn open_paths(
|
||||
abs_paths: &[PathBuf],
|
||||
app_state: &Arc<AppState>,
|
||||
requesting_window_id: Option<usize>,
|
||||
requesting_window: Option<WindowHandle<Workspace>>,
|
||||
cx: &mut AppContext,
|
||||
) -> Task<
|
||||
Result<(
|
||||
@ -3879,7 +3884,7 @@ pub fn open_paths(
|
||||
} else {
|
||||
Ok(cx
|
||||
.update(|cx| {
|
||||
Workspace::new_local(abs_paths, app_state.clone(), requesting_window_id, cx)
|
||||
Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
|
||||
})
|
||||
.await)
|
||||
}
|
||||
@ -4196,14 +4201,14 @@ mod tests {
|
||||
);
|
||||
});
|
||||
assert_eq!(
|
||||
cx.current_window_title(window.window_id()).as_deref(),
|
||||
cx.current_window_title(window.id()).as_deref(),
|
||||
Some("one.txt — root1")
|
||||
);
|
||||
|
||||
// Add a second item to a non-empty pane
|
||||
workspace.update(cx, |workspace, cx| workspace.add_item(Box::new(item2), cx));
|
||||
assert_eq!(
|
||||
cx.current_window_title(window.window_id()).as_deref(),
|
||||
cx.current_window_title(window.id()).as_deref(),
|
||||
Some("two.txt — root1")
|
||||
);
|
||||
project.read_with(cx, |project, cx| {
|
||||
@ -4222,7 +4227,7 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
cx.current_window_title(window.window_id()).as_deref(),
|
||||
cx.current_window_title(window.id()).as_deref(),
|
||||
Some("one.txt — root1")
|
||||
);
|
||||
project.read_with(cx, |project, cx| {
|
||||
@ -4242,14 +4247,14 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
cx.current_window_title(window.window_id()).as_deref(),
|
||||
cx.current_window_title(window.id()).as_deref(),
|
||||
Some("one.txt — root1, root2")
|
||||
);
|
||||
|
||||
// Remove a project folder
|
||||
project.update(cx, |project, cx| project.remove_worktree(worktree_id, cx));
|
||||
assert_eq!(
|
||||
cx.current_window_title(window.window_id()).as_deref(),
|
||||
cx.current_window_title(window.id()).as_deref(),
|
||||
Some("one.txt — root2")
|
||||
);
|
||||
}
|
||||
@ -4285,9 +4290,9 @@ mod tests {
|
||||
});
|
||||
let task = workspace.update(cx, |w, cx| w.prepare_to_close(false, cx));
|
||||
cx.foreground().run_until_parked();
|
||||
cx.simulate_prompt_answer(window.window_id(), 2 /* cancel */);
|
||||
cx.simulate_prompt_answer(window.id(), 2 /* cancel */);
|
||||
cx.foreground().run_until_parked();
|
||||
assert!(!cx.has_pending_prompt(window.window_id()));
|
||||
assert!(!cx.has_pending_prompt(window.id()));
|
||||
assert!(!task.await.unwrap());
|
||||
}
|
||||
|
||||
@ -4346,10 +4351,10 @@ mod tests {
|
||||
assert_eq!(pane.items_len(), 4);
|
||||
assert_eq!(pane.active_item().unwrap().id(), item1.id());
|
||||
});
|
||||
assert!(cx.has_pending_prompt(window.window_id()));
|
||||
assert!(cx.has_pending_prompt(window.id()));
|
||||
|
||||
// Confirm saving item 1.
|
||||
cx.simulate_prompt_answer(window.window_id(), 0);
|
||||
cx.simulate_prompt_answer(window.id(), 0);
|
||||
cx.foreground().run_until_parked();
|
||||
|
||||
// Item 1 is saved. There's a prompt to save item 3.
|
||||
@ -4360,10 +4365,10 @@ mod tests {
|
||||
assert_eq!(pane.items_len(), 3);
|
||||
assert_eq!(pane.active_item().unwrap().id(), item3.id());
|
||||
});
|
||||
assert!(cx.has_pending_prompt(window.window_id()));
|
||||
assert!(cx.has_pending_prompt(window.id()));
|
||||
|
||||
// Cancel saving item 3.
|
||||
cx.simulate_prompt_answer(window.window_id(), 1);
|
||||
cx.simulate_prompt_answer(window.id(), 1);
|
||||
cx.foreground().run_until_parked();
|
||||
|
||||
// Item 3 is reloaded. There's a prompt to save item 4.
|
||||
@ -4374,10 +4379,10 @@ mod tests {
|
||||
assert_eq!(pane.items_len(), 2);
|
||||
assert_eq!(pane.active_item().unwrap().id(), item4.id());
|
||||
});
|
||||
assert!(cx.has_pending_prompt(window.window_id()));
|
||||
assert!(cx.has_pending_prompt(window.id()));
|
||||
|
||||
// Confirm saving item 4.
|
||||
cx.simulate_prompt_answer(window.window_id(), 0);
|
||||
cx.simulate_prompt_answer(window.id(), 0);
|
||||
cx.foreground().run_until_parked();
|
||||
|
||||
// There's a prompt for a path for item 4.
|
||||
@ -4480,7 +4485,7 @@ mod tests {
|
||||
&[ProjectEntryId::from_proto(0)]
|
||||
);
|
||||
});
|
||||
cx.simulate_prompt_answer(window.window_id(), 0);
|
||||
cx.simulate_prompt_answer(window.id(), 0);
|
||||
|
||||
cx.foreground().run_until_parked();
|
||||
left_pane.read_with(cx, |pane, cx| {
|
||||
@ -4489,7 +4494,7 @@ mod tests {
|
||||
&[ProjectEntryId::from_proto(2)]
|
||||
);
|
||||
});
|
||||
cx.simulate_prompt_answer(window.window_id(), 0);
|
||||
cx.simulate_prompt_answer(window.id(), 0);
|
||||
|
||||
cx.foreground().run_until_parked();
|
||||
close.await.unwrap();
|
||||
@ -4549,7 +4554,7 @@ mod tests {
|
||||
item.read_with(cx, |item, _| assert_eq!(item.save_count, 2));
|
||||
|
||||
// Deactivating the window still saves the file.
|
||||
cx.simulate_window_activation(Some(window.window_id()));
|
||||
cx.simulate_window_activation(Some(window.id()));
|
||||
item.update(cx, |item, cx| {
|
||||
cx.focus_self();
|
||||
item.is_dirty = true;
|
||||
@ -4591,7 +4596,7 @@ mod tests {
|
||||
pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id))
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(!cx.has_pending_prompt(window.window_id()));
|
||||
assert!(!cx.has_pending_prompt(window.id()));
|
||||
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
|
||||
|
||||
// Add the item again, ensuring autosave is prevented if the underlying file has been deleted.
|
||||
@ -4612,7 +4617,7 @@ mod tests {
|
||||
let _close_items =
|
||||
pane.update(cx, |pane, cx| pane.close_items(cx, move |id| id == item_id));
|
||||
deterministic.run_until_parked();
|
||||
assert!(cx.has_pending_prompt(window.window_id()));
|
||||
assert!(cx.has_pending_prompt(window.id()));
|
||||
item.read_with(cx, |item, _| assert_eq!(item.save_count, 5));
|
||||
}
|
||||
|
||||
|
@ -813,11 +813,12 @@ mod tests {
|
||||
|
||||
// Replace existing windows
|
||||
let window_id = cx.window_ids()[0];
|
||||
let window = cx.read_window(window_id, |cx| cx.window()).flatten();
|
||||
cx.update(|cx| {
|
||||
open_paths(
|
||||
&[PathBuf::from("/root/c"), PathBuf::from("/root/d")],
|
||||
&app_state,
|
||||
Some(window_id),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
@ -982,9 +983,8 @@ mod tests {
|
||||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let workspace = cx
|
||||
.add_window(|cx| Workspace::test_new(project, cx))
|
||||
.root(cx);
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
let file1 = entries[0].clone();
|
||||
@ -1298,7 +1298,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
// Open a file within an existing worktree.
|
||||
workspace
|
||||
@ -1341,7 +1341,7 @@ mod tests {
|
||||
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
let worktree = cx.read(|cx| workspace.read(cx).worktrees(cx).next().unwrap());
|
||||
|
||||
// Create a new untitled buffer
|
||||
@ -1436,7 +1436,7 @@ mod tests {
|
||||
project.update(cx, |project, _| project.languages().add(rust_lang()));
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
// Create a new untitled buffer
|
||||
cx.dispatch_action(window_id, NewFile);
|
||||
@ -1489,7 +1489,7 @@ mod tests {
|
||||
let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await;
|
||||
let window = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||
let workspace = window.root(cx);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
let entries = cx.read(|cx| workspace.file_project_paths(cx));
|
||||
let file1 = entries[0].clone();
|
||||
@ -2087,7 +2087,7 @@ mod tests {
|
||||
cx.foreground().run_until_parked();
|
||||
|
||||
let window = cx.add_window(|_| TestView);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
// Test loading the keymap base at all
|
||||
assert_key_bindings_for(
|
||||
@ -2258,7 +2258,7 @@ mod tests {
|
||||
cx.foreground().run_until_parked();
|
||||
|
||||
let window = cx.add_window(|_| TestView);
|
||||
let window_id = window.window_id();
|
||||
let window_id = window.id();
|
||||
|
||||
// Test loading the keymap base at all
|
||||
assert_key_bindings_for(
|
||||
|
Loading…
Reference in New Issue
Block a user