diff --git a/gpui/src/app.rs b/gpui/src/app.rs index edb0f17dc1f33c4c30f5bb99c46f35ad6ba5bd36..9312d6b3f3480f6e78093625111d5553bc752139 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -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 for MutableAppContext { } } +impl Deref for MutableAppContext { + type Target = AppContext; + + fn deref(&self) -> &Self::Target { + &self.cx + } +} + pub struct AppContext { models: HashMap>, views: HashMap<(usize, usize), Box>, @@ -1534,8 +1544,10 @@ impl AppContext { pub fn value(&self, id: usize) -> ValueHandle { let key = (TypeId::of::(), 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::(), id, &self.ref_counts) } } @@ -2090,6 +2102,14 @@ impl AsRef for ViewContext<'_, M> { } } +impl Deref for ViewContext<'_, M> { + type Target = MutableAppContext; + + fn deref(&self) -> &Self::Target { + &self.app + } +} + impl AsMut for ViewContext<'_, M> { fn as_mut(&mut self) -> &mut MutableAppContext { self.app @@ -2633,8 +2653,7 @@ impl WeakViewHandle { } } - pub fn upgrade(&self, cx: impl AsRef) -> Option> { - let cx = cx.as_ref(); + pub fn upgrade(&self, cx: &AppContext) -> Option> { if cx.ref_counts.lock().is_entity_alive(self.view_id) { Some(ViewHandle::new( self.window_id, @@ -2684,13 +2703,25 @@ impl ValueHandle { .unwrap()) } - pub fn update(&self, cx: &AppContext, f: impl FnOnce(&mut T) -> R) -> R { - f(cx.values + pub fn update( + &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 } } diff --git a/gpui/src/elements.rs b/gpui/src/elements.rs index a37ee7fea5801e9864ec75194f1d7dbf3359d45a..869a26b542d99d551537b579e5bad6222045fa6d 100644 --- a/gpui/src/elements.rs +++ b/gpui/src/elements.rs @@ -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; diff --git a/gpui/src/elements/mouse_event_handler.rs b/gpui/src/elements/mouse_event_handler.rs index 98de1f6a0f4d0a0b47f8876452c7d2a067967ced..2fc310e8252b88d79217e5783dea6ba3ca53a207 100644 --- a/gpui/src/elements/mouse_event_handler.rs +++ b/gpui/src/elements/mouse_event_handler.rs @@ -24,7 +24,7 @@ impl MouseEventHandler { F: FnOnce(MouseState) -> ElementBox, { let state_handle = cx.value::(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 { diff --git a/gpui/src/elements/uniform_list.rs b/gpui/src/elements/uniform_list.rs index 69cc55217bbcc83896257614e4b20e1650909e0a..b414a20430159ff373422240add657792687f2e9 100644 --- a/gpui/src/elements/uniform_list.rs +++ b/gpui/src/elements/uniform_list.rs @@ -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; diff --git a/gpui/src/presenter.rs b/gpui/src/presenter.rs index a6e37097c08229f0363071823e5a2af93134a06d..844dc0502432dc2c96fabca95a92aac36ac202dd 100644 --- a/gpui/src/presenter.rs +++ b/gpui/src/presenter.rs @@ -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, } @@ -240,7 +240,7 @@ pub struct EventContext<'a> { actions: Vec, pub font_cache: &'a FontCache, pub text_layout_cache: &'a TextLayoutCache, - pub app: &'a AppContext, + pub app: &'a mut MutableAppContext, view_stack: Vec, invalidated_views: HashSet, } diff --git a/zed/src/editor/element.rs b/zed/src/editor/element.rs index 86e425df411e5b028e2d64bd3b4f9c6f75c40f7b..8bc98c21aca1d7862ddd185c679ba80affc03b2a 100644 --- a/zed/src/editor/element.rs +++ b/zed/src/editor/element.rs @@ -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); diff --git a/zed/src/file_finder.rs b/zed/src/file_finder.rs index 2f5ad01101e38c450cf740d6faeaf4a7a463cc43..362ee34e65ce5f49053b49f92797603e169a3502 100644 --- a/zed/src/file_finder.rs +++ b/zed/src/file_finder.rs @@ -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;