Eliminate GPUI View, ViewContext, and WindowContext types (#22632)
There's still a bit more work to do on this, but this PR is compiling (with warnings) after eliminating the key types. When the tasks below are complete, this will be the new narrative for GPUI: - `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit of state, and if `T` implements `Render`, then `Entity<T>` implements `Element`. - `&mut App` This replaces `AppContext` and represents the app. - `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It is provided by the framework when updating an entity. - `&mut Window` Broken out of `&mut WindowContext` which no longer exists. Every method that once took `&mut WindowContext` now takes `&mut Window, &mut App` and every method that took `&mut ViewContext<T>` now takes `&mut Window, &mut Context<T>` Not pictured here are the two other failed attempts. It's been quite a month! Tasks: - [x] Remove `View`, `ViewContext`, `WindowContext` and thread through `Window` - [x] [@cole-miller @mikayla-maki] Redraw window when entities change - [x] [@cole-miller @mikayla-maki] Get examples and Zed running - [x] [@cole-miller @mikayla-maki] Fix Zed rendering - [x] [@mikayla-maki] Fix todo! macros and comments - [x] Fix a bug where the editor would not be redrawn because of view caching - [x] remove publicness window.notify() and replace with `AppContext::notify` - [x] remove `observe_new_window_models`, replace with `observe_new_models` with an optional window - [x] Fix a bug where the project panel would not be redrawn because of the wrong refresh() call being used - [x] Fix the tests - [x] Fix warnings by eliminating `Window` params or using `_` - [x] Fix conflicts - [x] Simplify generic code where possible - [x] Rename types - [ ] Update docs ### issues post merge - [x] Issues switching between normal and insert mode - [x] Assistant re-rendering failure - [x] Vim test failures - [x] Mac build issue Release Notes: - N/A --------- Co-authored-by: Antonio Scandurra <me@as-cii.com> Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: Mikayla <mikayla@zed.dev> Co-authored-by: Joseph <joseph@zed.dev> Co-authored-by: max <max@zed.dev> Co-authored-by: Michael Sloan <michael@zed.dev> Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local> Co-authored-by: Mikayla <mikayla.c.maki@gmail.com> Co-authored-by: joão <joao@zed.dev>
This commit is contained in:
parent
21b4a0d50e
commit
6fca1d2b0b
648 changed files with 36248 additions and 28208 deletions
|
@ -1,14 +1,15 @@
|
|||
use crate::{
|
||||
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, BorrowAppContext, Context,
|
||||
DismissEvent, FocusableView, ForegroundExecutor, Global, Model, ModelContext, PromptLevel,
|
||||
Render, Reservation, Result, Task, View, ViewContext, VisualContext, WindowContext,
|
||||
WindowHandle,
|
||||
AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, BorrowAppContext,
|
||||
Entity, Focusable, ForegroundExecutor, Global, PromptLevel, Render, Reservation, Result, Task,
|
||||
VisualContext, Window, WindowHandle,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use futures::channel::oneshot;
|
||||
use std::{future::Future, rc::Weak};
|
||||
|
||||
use super::Context;
|
||||
|
||||
/// An async-friendly version of [AppContext] with a static lifetime so it can be held across `await` points in async code.
|
||||
/// You're provided with an instance when calling [AppContext::spawn], and you can also create one with [AppContext::to_async].
|
||||
/// Internally, this holds a weak reference to an `AppContext`, so its methods are fallible to protect against cases where the [AppContext] is dropped.
|
||||
|
@ -19,19 +20,19 @@ pub struct AsyncAppContext {
|
|||
pub(crate) foreground_executor: ForegroundExecutor,
|
||||
}
|
||||
|
||||
impl Context for AsyncAppContext {
|
||||
impl AppContext for AsyncAppContext {
|
||||
type Result<T> = Result<T>;
|
||||
|
||||
fn new_model<T: 'static>(
|
||||
fn new<T: 'static>(
|
||||
&mut self,
|
||||
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
|
||||
) -> Self::Result<Model<T>> {
|
||||
build_model: impl FnOnce(&mut Context<'_, T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut app = app.borrow_mut();
|
||||
Ok(app.new_model(build_model))
|
||||
Ok(app.new(build_model))
|
||||
}
|
||||
|
||||
fn reserve_model<T: 'static>(&mut self) -> Result<Reservation<T>> {
|
||||
|
@ -46,8 +47,8 @@ impl Context for AsyncAppContext {
|
|||
fn insert_model<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
|
||||
) -> Result<Model<T>> {
|
||||
build_model: impl FnOnce(&mut Context<'_, T>) -> T,
|
||||
) -> Result<Entity<T>> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
|
@ -58,8 +59,8 @@ impl Context for AsyncAppContext {
|
|||
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
|
||||
handle: &Entity<T>,
|
||||
update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
let app = self
|
||||
.app
|
||||
|
@ -71,8 +72,8 @@ impl Context for AsyncAppContext {
|
|||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
callback: impl FnOnce(&T, &AppContext) -> R,
|
||||
handle: &Entity<T>,
|
||||
callback: impl FnOnce(&T, &App) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
|
@ -84,7 +85,7 @@ impl Context for AsyncAppContext {
|
|||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut Window, &mut App) -> T,
|
||||
{
|
||||
let app = self.app.upgrade().context("app was released")?;
|
||||
let mut lock = app.borrow_mut();
|
||||
|
@ -94,7 +95,7 @@ impl Context for AsyncAppContext {
|
|||
fn read_window<T, R>(
|
||||
&self,
|
||||
window: &WindowHandle<T>,
|
||||
read: impl FnOnce(View<T>, &AppContext) -> R,
|
||||
read: impl FnOnce(Entity<T>, &App) -> R,
|
||||
) -> Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
|
@ -113,7 +114,7 @@ impl AsyncAppContext {
|
|||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.borrow_mut();
|
||||
lock.refresh();
|
||||
lock.refresh_windows();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,7 @@ impl AsyncAppContext {
|
|||
}
|
||||
|
||||
/// Invoke the given function in the context of the app, then flush any effects produced during its invocation.
|
||||
pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
|
||||
pub fn update<R>(&self, f: impl FnOnce(&mut App) -> R) -> Result<R> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
|
@ -141,7 +142,7 @@ impl AsyncAppContext {
|
|||
pub fn open_window<V>(
|
||||
&self,
|
||||
options: crate::WindowOptions,
|
||||
build_root_view: impl FnOnce(&mut WindowContext) -> View<V>,
|
||||
build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity<V>,
|
||||
) -> Result<WindowHandle<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
|
@ -178,7 +179,7 @@ impl AsyncAppContext {
|
|||
///
|
||||
/// Panics if no global state of the specified type has been assigned.
|
||||
/// Returns an error if the `AppContext` has been dropped.
|
||||
pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
|
||||
pub fn read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> Result<R> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
|
@ -193,10 +194,7 @@ impl AsyncAppContext {
|
|||
/// if no state of the specified type has been assigned.
|
||||
///
|
||||
/// Returns an error if no state of the specified type has been assigned the `AppContext` has been dropped.
|
||||
pub fn try_read_global<G: Global, R>(
|
||||
&self,
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Option<R> {
|
||||
pub fn try_read_global<G: Global, R>(&self, read: impl FnOnce(&G, &App) -> R) -> Option<R> {
|
||||
let app = self.app.upgrade()?;
|
||||
let app = app.borrow_mut();
|
||||
Some(read(app.try_global()?, &app))
|
||||
|
@ -206,7 +204,7 @@ impl AsyncAppContext {
|
|||
/// for updating the global state of the specified type.
|
||||
pub fn update_global<G: Global, R>(
|
||||
&self,
|
||||
update: impl FnOnce(&mut G, &mut AppContext) -> R,
|
||||
update: impl FnOnce(&mut G, &mut App) -> R,
|
||||
) -> Result<R> {
|
||||
let app = self
|
||||
.app
|
||||
|
@ -228,7 +226,7 @@ pub struct AsyncWindowContext {
|
|||
}
|
||||
|
||||
impl AsyncWindowContext {
|
||||
pub(crate) fn new(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
|
||||
pub(crate) fn new_context(app: AsyncAppContext, window: AnyWindowHandle) -> Self {
|
||||
Self { app, window }
|
||||
}
|
||||
|
||||
|
@ -238,41 +236,47 @@ impl AsyncWindowContext {
|
|||
}
|
||||
|
||||
/// A convenience method for [`AppContext::update_window`].
|
||||
pub fn update<R>(&mut self, update: impl FnOnce(&mut WindowContext) -> R) -> Result<R> {
|
||||
self.app.update_window(self.window, |_, cx| update(cx))
|
||||
pub fn update<R>(&mut self, update: impl FnOnce(&mut Window, &mut App) -> R) -> Result<R> {
|
||||
self.app
|
||||
.update_window(self.window, |_, window, cx| update(window, cx))
|
||||
}
|
||||
|
||||
/// A convenience method for [`AppContext::update_window`].
|
||||
pub fn update_root<R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(AnyView, &mut WindowContext) -> R,
|
||||
update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
|
||||
) -> Result<R> {
|
||||
self.app.update_window(self.window, update)
|
||||
}
|
||||
|
||||
/// A convenience method for [`WindowContext::on_next_frame`].
|
||||
pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
|
||||
self.window.update(self, |_, cx| cx.on_next_frame(f)).ok();
|
||||
/// A convenience method for [`Window::on_next_frame`].
|
||||
pub fn on_next_frame(&mut self, f: impl FnOnce(&mut Window, &mut App) + 'static) {
|
||||
self.window
|
||||
.update(self, |_, window, _| window.on_next_frame(f))
|
||||
.ok();
|
||||
}
|
||||
|
||||
/// A convenience method for [`AppContext::global`].
|
||||
pub fn read_global<G: Global, R>(
|
||||
&mut self,
|
||||
read: impl FnOnce(&G, &WindowContext) -> R,
|
||||
read: impl FnOnce(&G, &Window, &App) -> R,
|
||||
) -> Result<R> {
|
||||
self.window.update(self, |_, cx| read(cx.global(), cx))
|
||||
self.window
|
||||
.update(self, |_, window, cx| read(cx.global(), window, cx))
|
||||
}
|
||||
|
||||
/// A convenience method for [`AppContext::update_global`].
|
||||
/// for updating the global state of the specified type.
|
||||
pub fn update_global<G, R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(&mut G, &mut WindowContext) -> R,
|
||||
update: impl FnOnce(&mut G, &mut Window, &mut App) -> R,
|
||||
) -> Result<R>
|
||||
where
|
||||
G: Global,
|
||||
{
|
||||
self.window.update(self, |_, cx| cx.update_global(update))
|
||||
self.window.update(self, |_, window, cx| {
|
||||
cx.update_global(|global, cx| update(global, window, cx))
|
||||
})
|
||||
}
|
||||
|
||||
/// Schedule a future to be executed on the main thread. This is used for collecting
|
||||
|
@ -296,50 +300,49 @@ impl AsyncWindowContext {
|
|||
answers: &[&str],
|
||||
) -> oneshot::Receiver<usize> {
|
||||
self.window
|
||||
.update(self, |_, cx| cx.prompt(level, message, detail, answers))
|
||||
.update(self, |_, window, cx| {
|
||||
window.prompt(level, message, detail, answers, cx)
|
||||
})
|
||||
.unwrap_or_else(|_| oneshot::channel().1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Context for AsyncWindowContext {
|
||||
impl AppContext for AsyncWindowContext {
|
||||
type Result<T> = Result<T>;
|
||||
|
||||
fn new_model<T>(
|
||||
&mut self,
|
||||
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
|
||||
) -> Result<Model<T>>
|
||||
fn new<T>(&mut self, build_model: impl FnOnce(&mut Context<'_, T>) -> T) -> Result<Entity<T>>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.window.update(self, |_, cx| cx.new_model(build_model))
|
||||
self.window.update(self, |_, _, cx| cx.new(build_model))
|
||||
}
|
||||
|
||||
fn reserve_model<T: 'static>(&mut self) -> Result<Reservation<T>> {
|
||||
self.window.update(self, |_, cx| cx.reserve_model())
|
||||
self.window.update(self, |_, _, cx| cx.reserve_model())
|
||||
}
|
||||
|
||||
fn insert_model<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
|
||||
) -> Self::Result<Model<T>> {
|
||||
build_model: impl FnOnce(&mut Context<'_, T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
self.window
|
||||
.update(self, |_, cx| cx.insert_model(reservation, build_model))
|
||||
.update(self, |_, _, cx| cx.insert_model(reservation, build_model))
|
||||
}
|
||||
|
||||
fn update_model<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Model<T>,
|
||||
update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
|
||||
handle: &Entity<T>,
|
||||
update: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
|
||||
) -> Result<R> {
|
||||
self.window
|
||||
.update(self, |_, cx| cx.update_model(handle, update))
|
||||
.update(self, |_, _, cx| cx.update_model(handle, update))
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
handle: &Entity<T>,
|
||||
read: impl FnOnce(&T, &App) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
|
@ -349,7 +352,7 @@ impl Context for AsyncWindowContext {
|
|||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext) -> T,
|
||||
F: FnOnce(AnyView, &mut Window, &mut App) -> T,
|
||||
{
|
||||
self.app.update_window(window, update)
|
||||
}
|
||||
|
@ -357,7 +360,7 @@ impl Context for AsyncWindowContext {
|
|||
fn read_window<T, R>(
|
||||
&self,
|
||||
window: &WindowHandle<T>,
|
||||
read: impl FnOnce(View<T>, &AppContext) -> R,
|
||||
read: impl FnOnce(Entity<T>, &App) -> R,
|
||||
) -> Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
|
@ -367,51 +370,46 @@ impl Context for AsyncWindowContext {
|
|||
}
|
||||
|
||||
impl VisualContext for AsyncWindowContext {
|
||||
fn new_view<V>(
|
||||
&mut self,
|
||||
build_view_state: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
{
|
||||
fn window_handle(&self) -> AnyWindowHandle {
|
||||
self.window
|
||||
.update(self, |_, cx| cx.new_view(build_view_state))
|
||||
}
|
||||
|
||||
fn update_view<V: 'static, R>(
|
||||
fn new_window_model<T: 'static>(
|
||||
&mut self,
|
||||
view: &View<V>,
|
||||
update: impl FnOnce(&mut V, &mut ViewContext<V>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
build_model: impl FnOnce(&mut Window, &mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
self.window
|
||||
.update(self, |_, cx| cx.update_view(view, update))
|
||||
.update(self, |_, window, cx| cx.new(|cx| build_model(window, cx)))
|
||||
}
|
||||
|
||||
fn update_window_model<T: 'static, R>(
|
||||
&mut self,
|
||||
view: &Entity<T>,
|
||||
update: impl FnOnce(&mut T, &mut Window, &mut Context<T>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
self.window.update(self, |_, window, cx| {
|
||||
view.update(cx, |model, cx| update(model, window, cx))
|
||||
})
|
||||
}
|
||||
|
||||
fn replace_root_view<V>(
|
||||
&mut self,
|
||||
build_view: impl FnOnce(&mut ViewContext<V>) -> V,
|
||||
) -> Self::Result<View<V>>
|
||||
build_view: impl FnOnce(&mut Window, &mut Context<V>) -> V,
|
||||
) -> Self::Result<Entity<V>>
|
||||
where
|
||||
V: 'static + Render,
|
||||
{
|
||||
self.window
|
||||
.update(self, |_, cx| cx.replace_root_view(build_view))
|
||||
}
|
||||
|
||||
fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
|
||||
where
|
||||
V: FocusableView,
|
||||
{
|
||||
self.window.update(self, |_, cx| {
|
||||
view.read(cx).focus_handle(cx).clone().focus(cx);
|
||||
self.window.update(self, |_, window, cx| {
|
||||
window.replace_root_model(cx, build_view)
|
||||
})
|
||||
}
|
||||
|
||||
fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
|
||||
fn focus<V>(&mut self, view: &Entity<V>) -> Self::Result<()>
|
||||
where
|
||||
V: crate::ManagedView,
|
||||
V: Focusable,
|
||||
{
|
||||
self.window
|
||||
.update(self, |_, cx| view.update(cx, |_, cx| cx.emit(DismissEvent)))
|
||||
self.window.update(self, |_, window, cx| {
|
||||
view.read(cx).focus_handle(cx).clone().focus(window);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue