Detailed changes
@@ -5,7 +5,8 @@ use crate::{
platform::{self, Platform, PromptLevel, WindowOptions},
presenter::Presenter,
util::{post_inc, timeout},
- AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
+ AssetCache, AssetSource, ClipboardItem, EventContext, FontCache, PathPromptOptions,
+ TextLayoutCache,
};
use anyhow::{anyhow, Result};
use async_task::Task;
@@ -22,6 +23,7 @@ use std::{
fmt::{self, Debug},
hash::{Hash, Hasher},
marker::PhantomData,
+ ops::Deref,
path::{Path, PathBuf},
rc::{self, Rc},
sync::{Arc, Weak},
@@ -1476,6 +1478,14 @@ impl AsRef<AppContext> for MutableAppContext {
}
}
+impl Deref for MutableAppContext {
+ type Target = AppContext;
+
+ fn deref(&self) -> &Self::Target {
+ &self.cx
+ }
+}
+
pub struct AppContext {
models: HashMap<usize, Box<dyn AnyModel>>,
views: HashMap<(usize, usize), Box<dyn AnyView>>,
@@ -1534,8 +1544,10 @@ impl AppContext {
pub fn value<Tag: 'static, T: 'static + Default>(&self, id: usize) -> ValueHandle<T> {
let key = (TypeId::of::<Tag>(), id);
- let mut values = self.values.write();
- values.entry(key).or_insert_with(|| Box::new(T::default()));
+ self.values
+ .write()
+ .entry(key)
+ .or_insert_with(|| Box::new(T::default()));
ValueHandle::new(TypeId::of::<Tag>(), id, &self.ref_counts)
}
}
@@ -2090,6 +2102,14 @@ impl<M> AsRef<AppContext> for ViewContext<'_, M> {
}
}
+impl<M> Deref for ViewContext<'_, M> {
+ type Target = MutableAppContext;
+
+ fn deref(&self) -> &Self::Target {
+ &self.app
+ }
+}
+
impl<M> AsMut<MutableAppContext> for ViewContext<'_, M> {
fn as_mut(&mut self) -> &mut MutableAppContext {
self.app
@@ -2633,8 +2653,7 @@ impl<T: View> WeakViewHandle<T> {
}
}
- pub fn upgrade(&self, cx: impl AsRef<AppContext>) -> Option<ViewHandle<T>> {
- let cx = cx.as_ref();
+ pub fn upgrade(&self, cx: &AppContext) -> Option<ViewHandle<T>> {
if cx.ref_counts.lock().is_entity_alive(self.view_id) {
Some(ViewHandle::new(
self.window_id,
@@ -2684,13 +2703,25 @@ impl<T: 'static> ValueHandle<T> {
.unwrap())
}
- pub fn update<R>(&self, cx: &AppContext, f: impl FnOnce(&mut T) -> R) -> R {
- f(cx.values
+ pub fn update<R>(
+ &self,
+ cx: &mut EventContext,
+ f: impl FnOnce(&mut T, &mut EventContext) -> R,
+ ) -> R {
+ let mut value = cx
+ .app
+ .cx
+ .values
.write()
- .get_mut(&(self.tag_type_id, self.id))
- .unwrap()
- .downcast_mut()
- .unwrap())
+ .remove(&(self.tag_type_id, self.id))
+ .unwrap();
+ let result = f(value.downcast_mut().unwrap(), cx);
+ cx.app
+ .cx
+ .values
+ .write()
+ .insert((self.tag_type_id, self.id), value);
+ result
}
}
@@ -29,8 +29,8 @@ pub use uniform_list::*;
use crate::{
geometry::{rect::RectF, vector::Vector2F},
- json, AfterLayoutContext, AppContext, DebugContext, Event, EventContext, LayoutContext,
- PaintContext, SizeConstraint,
+ json, AfterLayoutContext, DebugContext, Event, EventContext, LayoutContext, PaintContext,
+ SizeConstraint,
};
use core::panic;
use json::ToJson;
@@ -24,7 +24,7 @@ impl MouseEventHandler {
F: FnOnce(MouseState) -> ElementBox,
{
let state_handle = cx.value::<Tag, _>(id);
- let state = state_handle.read(cx, |state| *state);
+ let state = state_handle.read(cx.as_ref(), |state| *state);
let child = render_child(state);
Self {
state: state_handle,
@@ -81,7 +81,7 @@ impl Element for MouseEventHandler {
let handled_in_child = self.child.dispatch_event(event, cx);
- self.state.update(cx.app, |state| match event {
+ self.state.update(cx, |state, cx| match event {
Event::MouseMoved { position } => {
let mouse_in = bounds.contains_point(*position);
if state.hovered != mouse_in {
@@ -1,6 +1,5 @@
use super::{
- AfterLayoutContext, AppContext, Element, Event, EventContext, LayoutContext, PaintContext,
- SizeConstraint,
+ AfterLayoutContext, Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
};
use crate::{
geometry::{
@@ -8,7 +7,7 @@ use crate::{
vector::{vec2f, Vector2F},
},
json::{self, json},
- ElementBox,
+ AppContext, ElementBox,
};
use json::ToJson;
use parking_lot::Mutex;
@@ -76,7 +76,7 @@ impl Presenter {
let mut scene = Scene::new(scale_factor);
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
- self.layout(window_size, cx.as_ref());
+ self.layout(window_size, cx);
self.after_layout(cx);
let mut paint_cx = PaintContext {
scene: &mut scene,
@@ -98,7 +98,7 @@ impl Presenter {
scene
}
- fn layout(&mut self, size: Vector2F, cx: &AppContext) {
+ fn layout(&mut self, size: Vector2F, cx: &mut MutableAppContext) {
if let Some(root_view_id) = cx.root_view_id(self.window_id) {
let mut layout_ctx = LayoutContext {
rendered_views: &mut self.rendered_views,
@@ -138,7 +138,7 @@ impl Presenter {
text_layout_cache: &self.text_layout_cache,
view_stack: Default::default(),
invalidated_views: Default::default(),
- app: cx.as_ref(),
+ app: cx,
};
event_cx.dispatch_event(root_view_id, &event);
@@ -184,7 +184,7 @@ pub struct LayoutContext<'a> {
pub font_cache: &'a FontCache,
pub text_layout_cache: &'a TextLayoutCache,
pub asset_cache: &'a AssetCache,
- pub app: &'a AppContext,
+ pub app: &'a mut MutableAppContext,
view_stack: Vec<usize>,
}
@@ -240,7 +240,7 @@ pub struct EventContext<'a> {
actions: Vec<ActionToDispatch>,
pub font_cache: &'a FontCache,
pub text_layout_cache: &'a TextLayoutCache,
- pub app: &'a AppContext,
+ pub app: &'a mut MutableAppContext,
view_stack: Vec<usize>,
invalidated_views: HashSet<usize>,
}
@@ -38,8 +38,9 @@ impl EditorElement {
cx: &mut EventContext,
) -> bool {
if paint.text_bounds.contains_point(position) {
- let view = self.view(cx.app);
- let position = paint.point_for_position(view, layout, position, cx.font_cache, cx.app);
+ let view = self.view(cx.app.as_ref());
+ let position =
+ paint.point_for_position(view, layout, position, cx.font_cache, cx.app.as_ref());
cx.dispatch_action("buffer:select", SelectAction::Begin { position, add: cmd });
true
} else {
@@ -48,7 +49,7 @@ impl EditorElement {
}
fn mouse_up(&self, _position: Vector2F, cx: &mut EventContext) -> bool {
- if self.view(cx.app).is_selecting() {
+ if self.view(cx.app.as_ref()).is_selecting() {
cx.dispatch_action("buffer:select", SelectAction::End);
true
} else {
@@ -63,7 +64,7 @@ impl EditorElement {
paint: &mut PaintState,
cx: &mut EventContext,
) -> bool {
- let view = self.view(cx.app);
+ let view = self.view(cx.app.as_ref());
if view.is_selecting() {
let rect = paint.text_bounds;
@@ -93,22 +94,21 @@ impl EditorElement {
))
}
- cx.dispatch_action(
- "buffer:select",
- SelectAction::Update {
- position: paint.point_for_position(
- view,
- layout,
- position,
- cx.font_cache,
- cx.app,
- ),
- scroll_position: (view.scroll_position() + scroll_delta).clamp(
- Vector2F::zero(),
- layout.scroll_max(view, cx.font_cache, cx.text_layout_cache, cx.app),
- ),
- },
- );
+ let action = SelectAction::Update {
+ position: paint.point_for_position(
+ view,
+ layout,
+ position,
+ cx.font_cache,
+ cx.app.as_ref(),
+ ),
+ scroll_position: (view.scroll_position() + scroll_delta).clamp(
+ Vector2F::zero(),
+ layout.scroll_max(view, cx.font_cache, cx.text_layout_cache, cx.app),
+ ),
+ };
+
+ cx.dispatch_action("buffer:select", action);
true
} else {
false
@@ -326,7 +326,7 @@ impl Element for EditorElement {
constraint: SizeConstraint,
cx: &mut LayoutContext,
) -> (Vector2F, Self::LayoutState) {
- let app = cx.app;
+ let app = &mut cx.app;
let mut size = constraint.max;
if size.y().is_infinite() {
let view = self.view(app);
@@ -124,6 +124,7 @@ impl FileFinder {
self.list_state.clone(),
self.matches.len(),
move |mut range, items, cx| {
+ let cx = cx.as_ref();
let finder = handle.upgrade(cx).unwrap();
let finder = finder.read(cx);
let start = range.start;