Get collab2 green
This commit is contained in:
parent
c529343ba1
commit
e1525e2b47
265 changed files with 64477 additions and 40 deletions
|
@ -16,8 +16,8 @@ pub use test_context::*;
|
|||
use crate::{
|
||||
current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle,
|
||||
AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId,
|
||||
Entity, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap, LayoutId,
|
||||
PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SharedString,
|
||||
Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap,
|
||||
LayoutId, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SharedString,
|
||||
SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem,
|
||||
View, Window, WindowContext, WindowHandle, WindowId,
|
||||
};
|
||||
|
@ -48,15 +48,19 @@ pub struct AppCell {
|
|||
impl AppCell {
|
||||
#[track_caller]
|
||||
pub fn borrow(&self) -> AppRef {
|
||||
let thread_id = std::thread::current().id();
|
||||
eprintln!("borrowed {thread_id:?}");
|
||||
if let Some(_) = option_env!("TRACK_THREAD_BORROWS") {
|
||||
let thread_id = std::thread::current().id();
|
||||
eprintln!("borrowed {thread_id:?}");
|
||||
}
|
||||
AppRef(self.app.borrow())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn borrow_mut(&self) -> AppRefMut {
|
||||
let thread_id = std::thread::current().id();
|
||||
eprintln!("borrowed {thread_id:?}");
|
||||
if let Some(_) = option_env!("TRACK_THREAD_BORROWS") {
|
||||
let thread_id = std::thread::current().id();
|
||||
eprintln!("borrowed {thread_id:?}");
|
||||
}
|
||||
AppRefMut(self.app.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
@ -292,6 +296,83 @@ impl AppContext {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn observe<W, E>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_notify: impl FnMut(E, &mut AppContext) + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
W: 'static,
|
||||
E: Entity<W>,
|
||||
{
|
||||
self.observe_internal(entity, move |e, cx| {
|
||||
on_notify(e, cx);
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
pub fn observe_internal<W, E>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_notify: impl FnMut(E, &mut AppContext) -> bool + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
W: 'static,
|
||||
E: Entity<W>,
|
||||
{
|
||||
let entity_id = entity.entity_id();
|
||||
let handle = entity.downgrade();
|
||||
self.observers.insert(
|
||||
entity_id,
|
||||
Box::new(move |cx| {
|
||||
if let Some(handle) = E::upgrade_from(&handle) {
|
||||
on_notify(handle, cx)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<T, E>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static + EventEmitter,
|
||||
E: Entity<T>,
|
||||
{
|
||||
self.subscribe_internal(entity, move |entity, event, cx| {
|
||||
on_event(entity, event, cx);
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn subscribe_internal<T, E>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) -> bool + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static + EventEmitter,
|
||||
E: Entity<T>,
|
||||
{
|
||||
let entity_id = entity.entity_id();
|
||||
let entity = entity.downgrade();
|
||||
self.event_listeners.insert(
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
let event: &T::Event = event.downcast_ref().expect("invalid event type");
|
||||
if let Some(handle) = E::upgrade_from(&entity) {
|
||||
on_event(handle, event, cx)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn windows(&self) -> Vec<AnyWindowHandle> {
|
||||
self.windows
|
||||
.values()
|
||||
|
@ -670,6 +751,23 @@ impl AppContext {
|
|||
self.globals_by_type.insert(global_type, Box::new(global));
|
||||
}
|
||||
|
||||
pub fn clear_globals(&mut self) {
|
||||
//todo!(notify globals?)
|
||||
self.globals_by_type.drain();
|
||||
}
|
||||
|
||||
/// Set the value of the global of the given type.
|
||||
pub fn remove_global<G: Any>(&mut self) -> G {
|
||||
let global_type = TypeId::of::<G>();
|
||||
//todo!(notify globals?)
|
||||
*self
|
||||
.globals_by_type
|
||||
.remove(&global_type)
|
||||
.unwrap_or_else(|| panic!("no global added for {}", std::any::type_name::<G>()))
|
||||
.downcast()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Update the global of the given type with a closure. Unlike `global_mut`, this method provides
|
||||
/// your closure with mutable access to the `AppContext` and the global simultaneously.
|
||||
pub fn update_global<G: 'static, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R {
|
||||
|
@ -841,6 +939,18 @@ impl Context for AppContext {
|
|||
Ok(result)
|
||||
})
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let entity = self.entities.read(handle);
|
||||
read(entity, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// These effects are processed at the end of each application update cycle.
|
||||
|
|
|
@ -45,6 +45,19 @@ impl Context for AsyncAppContext {
|
|||
Ok(app.update_model(handle, update))
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
callback: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let app = self.app.upgrade().context("app was released")?;
|
||||
let lock = app.borrow();
|
||||
Ok(lock.read_model(handle, callback))
|
||||
}
|
||||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
|
||||
|
@ -226,6 +239,17 @@ impl Context for AsyncWindowContext {
|
|||
{
|
||||
self.app.update_window(window, update)
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.app.read_model(handle, read)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisualContext for AsyncWindowContext {
|
||||
|
|
|
@ -325,6 +325,14 @@ impl<T: 'static> Model<T> {
|
|||
cx.entities.read(self)
|
||||
}
|
||||
|
||||
pub fn read_with<'a, R, C: Context>(
|
||||
&self,
|
||||
cx: &'a C,
|
||||
f: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> C::Result<R> {
|
||||
cx.read_model(self, f)
|
||||
}
|
||||
|
||||
/// Update the entity referenced by this model with the given function.
|
||||
///
|
||||
/// The update function receives a context appropriate for its environment.
|
||||
|
|
|
@ -49,19 +49,14 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
E: Entity<W>,
|
||||
{
|
||||
let this = self.weak_model();
|
||||
let entity_id = entity.entity_id();
|
||||
let handle = entity.downgrade();
|
||||
self.app.observers.insert(
|
||||
entity_id,
|
||||
Box::new(move |cx| {
|
||||
if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&handle)) {
|
||||
this.update(cx, |this, cx| on_notify(this, handle, cx));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
)
|
||||
self.app.observe_internal(entity, move |e, cx| {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| on_notify(this, e, cx));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn subscribe<T2, E>(
|
||||
|
@ -75,20 +70,14 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
|||
E: Entity<T2>,
|
||||
{
|
||||
let this = self.weak_model();
|
||||
let entity_id = entity.entity_id();
|
||||
let entity = entity.downgrade();
|
||||
self.app.event_listeners.insert(
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
let event: &T2::Event = event.downcast_ref().expect("invalid event type");
|
||||
if let Some((this, handle)) = this.upgrade().zip(E::upgrade_from(&entity)) {
|
||||
this.update(cx, |this, cx| on_event(this, handle, event, cx));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
)
|
||||
self.app.subscribe_internal(entity, move |e, event, cx| {
|
||||
if let Some(this) = this.upgrade() {
|
||||
this.update(cx, |this, cx| on_event(this, e, event, cx));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn on_release(
|
||||
|
@ -236,6 +225,17 @@ impl<'a, T> Context for ModelContext<'a, T> {
|
|||
{
|
||||
self.app.update_window(window, update)
|
||||
}
|
||||
|
||||
fn read_model<U, R>(
|
||||
&self,
|
||||
handle: &Model<U>,
|
||||
read: impl FnOnce(&U, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
U: 'static,
|
||||
{
|
||||
self.app.read_model(handle, read)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Borrow<AppContext> for ModelContext<'_, T> {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, BackgroundExecutor, Context,
|
||||
EventEmitter, ForegroundExecutor, Model, ModelContext, Result, Task, TestDispatcher,
|
||||
TestPlatform, WindowContext,
|
||||
EventEmitter, ForegroundExecutor, Model, ModelContext, Render, Result, Task, TestDispatcher,
|
||||
TestPlatform, ViewContext, VisualContext, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use anyhow::{anyhow, bail};
|
||||
use futures::{Stream, StreamExt};
|
||||
|
@ -12,6 +12,7 @@ pub struct TestAppContext {
|
|||
pub app: Rc<AppCell>,
|
||||
pub background_executor: BackgroundExecutor,
|
||||
pub foreground_executor: ForegroundExecutor,
|
||||
pub dispatcher: TestDispatcher,
|
||||
}
|
||||
|
||||
impl Context for TestAppContext {
|
||||
|
@ -44,13 +45,25 @@ impl Context for TestAppContext {
|
|||
let mut lock = self.app.borrow_mut();
|
||||
lock.update_window(window, f)
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let app = self.app.borrow();
|
||||
app.read_model(handle, read)
|
||||
}
|
||||
}
|
||||
|
||||
impl TestAppContext {
|
||||
pub fn new(dispatcher: TestDispatcher) -> Self {
|
||||
let dispatcher = Arc::new(dispatcher);
|
||||
let background_executor = BackgroundExecutor::new(dispatcher.clone());
|
||||
let foreground_executor = ForegroundExecutor::new(dispatcher);
|
||||
let arc_dispatcher = Arc::new(dispatcher.clone());
|
||||
let background_executor = BackgroundExecutor::new(arc_dispatcher.clone());
|
||||
let foreground_executor = ForegroundExecutor::new(arc_dispatcher);
|
||||
let platform = Rc::new(TestPlatform::new(
|
||||
background_executor.clone(),
|
||||
foreground_executor.clone(),
|
||||
|
@ -61,9 +74,14 @@ impl TestAppContext {
|
|||
app: AppContext::new(platform, asset_source, http_client),
|
||||
background_executor,
|
||||
foreground_executor,
|
||||
dispatcher: dispatcher.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_app(&self) -> TestAppContext {
|
||||
Self::new(self.dispatcher.clone())
|
||||
}
|
||||
|
||||
pub fn quit(&self) {
|
||||
self.app.borrow_mut().quit();
|
||||
}
|
||||
|
@ -87,6 +105,20 @@ impl TestAppContext {
|
|||
cx.update(f)
|
||||
}
|
||||
|
||||
pub fn read<R>(&self, f: impl FnOnce(&AppContext) -> R) -> R {
|
||||
let cx = self.app.borrow();
|
||||
f(&*cx)
|
||||
}
|
||||
|
||||
pub fn add_window<F, V>(&mut self, build_window: F) -> WindowHandle<V>
|
||||
where
|
||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||
V: Render,
|
||||
{
|
||||
let mut cx = self.app.borrow_mut();
|
||||
cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window))
|
||||
}
|
||||
|
||||
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
|
||||
where
|
||||
Fut: Future<Output = R> + 'static,
|
||||
|
|
|
@ -17,6 +17,9 @@ use std::{
|
|||
use util::TryFutureExt;
|
||||
use waker_fn::waker_fn;
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
use rand::rngs::StdRng;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BackgroundExecutor {
|
||||
dispatcher: Arc<dyn PlatformDispatcher>,
|
||||
|
@ -219,6 +222,16 @@ impl BackgroundExecutor {
|
|||
self.dispatcher.as_test().unwrap().allow_parking();
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn record_backtrace(&self) {
|
||||
self.dispatcher.as_test().unwrap().record_backtrace();
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn rng(&self) -> StdRng {
|
||||
self.dispatcher.as_test().unwrap().rng()
|
||||
}
|
||||
|
||||
pub fn num_cpus(&self) -> usize {
|
||||
num_cpus::get()
|
||||
}
|
||||
|
|
|
@ -89,6 +89,14 @@ pub trait Context {
|
|||
where
|
||||
T: 'static;
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static;
|
||||
|
||||
fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(AnyView, &mut WindowContext<'_>) -> T;
|
||||
|
|
|
@ -127,6 +127,14 @@ impl TestDispatcher {
|
|||
b
|
||||
})
|
||||
}
|
||||
|
||||
pub fn record_backtrace(&self) {
|
||||
todo!("record_backtrace")
|
||||
}
|
||||
|
||||
pub fn rng(&self) -> StdRng {
|
||||
todo!("rng")
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for TestDispatcher {
|
||||
|
|
|
@ -1364,6 +1364,18 @@ impl Context for WindowContext<'_> {
|
|||
window.update(self.app, update)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let entity = self.entities.read(handle);
|
||||
read(&*entity, &*self.app)
|
||||
}
|
||||
}
|
||||
|
||||
impl VisualContext for WindowContext<'_> {
|
||||
|
@ -2009,6 +2021,17 @@ impl<V> Context for ViewContext<'_, V> {
|
|||
{
|
||||
self.window_cx.update_window(window, update)
|
||||
}
|
||||
|
||||
fn read_model<T, R>(
|
||||
&self,
|
||||
handle: &Model<T>,
|
||||
read: impl FnOnce(&T, &AppContext) -> R,
|
||||
) -> Self::Result<R>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.window_cx.read_model(handle, read)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> VisualContext for ViewContext<'_, V> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue