Remove initialize from the Element trait (#3338)

Initially, we imagined registering keyboard handlers in the initialize
phase so we would understand the relationships between focus handles
during the layout pass, which would allow us to assign assign `focus_in`
styles that impact layout.

However, we soon realized that many elements aren't created until paint
time anyway, such as within the uniform list. Since it's impossible to
know prior to paint whether an element contains the focused element, it
makes more sense to eliminate the `focus_in` styling helper.

Release Notes:

- N/A
This commit is contained in:
Nathan Sobo 2023-11-15 19:36:35 -07:00 committed by GitHub
commit e5ada92b7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 147 additions and 316 deletions

View file

@ -2398,21 +2398,14 @@ impl Element<Editor> for EditorElement {
Some(self.editor_id.into()) Some(self.editor_id.into())
} }
fn initialize( fn layout(
&mut self, &mut self,
editor: &mut Editor, editor: &mut Editor,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut gpui::ViewContext<Editor>, cx: &mut gpui::ViewContext<Editor>,
) -> Self::ElementState { ) -> (gpui::LayoutId, Self::ElementState) {
editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this. editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this.
}
fn layout(
&mut self,
editor: &mut Editor,
element_state: &mut Self::ElementState,
cx: &mut gpui::ViewContext<Editor>,
) -> gpui::LayoutId {
let rem_size = cx.rem_size(); let rem_size = cx.rem_size();
let mut style = Style::default(); let mut style = Style::default();
style.size.width = relative(1.).into(); style.size.width = relative(1.).into();
@ -2421,7 +2414,8 @@ impl Element<Editor> for EditorElement {
EditorMode::AutoHeight { .. } => todo!(), EditorMode::AutoHeight { .. } => todo!(),
EditorMode::Full => relative(1.).into(), EditorMode::Full => relative(1.).into(),
}; };
cx.request_layout(&style, None) let layout_id = cx.request_layout(&style, None);
(layout_id, ())
} }
fn paint( fn paint(

View file

@ -10,21 +10,12 @@ pub trait Element<V: 'static> {
fn element_id(&self) -> Option<ElementId>; fn element_id(&self) -> Option<ElementId>;
/// Called to initialize this element for the current frame. If this
/// element had state in a previous frame, it will be passed in for the 3rd argument.
fn initialize(
&mut self,
view_state: &mut V,
element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>,
) -> Self::ElementState;
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V, view_state: &mut V,
element_state: &mut Self::ElementState, previous_element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> LayoutId; ) -> (LayoutId, Self::ElementState);
fn paint( fn paint(
&mut self, &mut self,
@ -96,7 +87,6 @@ pub trait ParentComponent<V: 'static> {
} }
trait ElementObject<V> { trait ElementObject<V> {
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId; fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>); fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
fn measure( fn measure(
@ -123,9 +113,6 @@ struct RenderedElement<V: 'static, E: Element<V>> {
enum ElementRenderPhase<V> { enum ElementRenderPhase<V> {
#[default] #[default]
Start, Start,
Initialized {
frame_state: Option<V>,
},
LayoutRequested { LayoutRequested {
layout_id: LayoutId, layout_id: LayoutId,
frame_state: Option<V>, frame_state: Option<V>,
@ -157,42 +144,19 @@ where
E: Element<V>, E: Element<V>,
E::ElementState: 'static, E::ElementState: 'static,
{ {
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
let frame_state = if let Some(id) = self.element.element_id() {
cx.with_element_state(id, |element_state, cx| {
let element_state = self.element.initialize(view_state, element_state, cx);
((), element_state)
});
None
} else {
let frame_state = self.element.initialize(view_state, None, cx);
Some(frame_state)
};
self.phase = ElementRenderPhase::Initialized { frame_state };
}
fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId { fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
let layout_id; let (layout_id, frame_state) = match mem::take(&mut self.phase) {
let mut frame_state; ElementRenderPhase::Start => {
match mem::take(&mut self.phase) {
ElementRenderPhase::Initialized {
frame_state: initial_frame_state,
} => {
frame_state = initial_frame_state;
if let Some(id) = self.element.element_id() { if let Some(id) = self.element.element_id() {
layout_id = cx.with_element_state(id, |element_state, cx| { let layout_id = cx.with_element_state(id, |element_state, cx| {
let mut element_state = element_state.unwrap(); self.element.layout(state, element_state, cx)
let layout_id = self.element.layout(state, &mut element_state, cx);
(layout_id, element_state)
}); });
(layout_id, None)
} else { } else {
layout_id = self let (layout_id, frame_state) = self.element.layout(state, None, cx);
.element (layout_id, Some(frame_state))
.layout(state, frame_state.as_mut().unwrap(), cx);
} }
} }
ElementRenderPhase::Start => panic!("must call initialize before layout"),
ElementRenderPhase::LayoutRequested { .. } ElementRenderPhase::LayoutRequested { .. }
| ElementRenderPhase::LayoutComputed { .. } | ElementRenderPhase::LayoutComputed { .. }
| ElementRenderPhase::Painted { .. } => { | ElementRenderPhase::Painted { .. } => {
@ -244,10 +208,6 @@ where
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Size<Pixels> { ) -> Size<Pixels> {
if matches!(&self.phase, ElementRenderPhase::Start) { if matches!(&self.phase, ElementRenderPhase::Start) {
self.initialize(view_state, cx);
}
if matches!(&self.phase, ElementRenderPhase::Initialized { .. }) {
self.layout(view_state, cx); self.layout(view_state, cx);
} }
@ -284,16 +244,13 @@ where
fn draw( fn draw(
&mut self, &mut self,
mut origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, view_state: &mut V,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) { ) {
self.measure(available_space, view_state, cx); self.measure(available_space, view_state, cx);
// Ignore the element offset when drawing this element, as the origin is already specified cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx))
// in absolute terms.
origin -= cx.element_offset();
cx.with_element_offset(origin, |cx| self.paint(view_state, cx))
} }
} }
@ -309,10 +266,6 @@ impl<V> AnyElement<V> {
AnyElement(Box::new(RenderedElement::new(element))) AnyElement(Box::new(RenderedElement::new(element)))
} }
pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
self.0.initialize(view_state, cx);
}
pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId { pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
self.0.layout(view_state, cx) self.0.layout(view_state, cx)
} }
@ -393,25 +346,16 @@ where
None None
} }
fn initialize(
&mut self,
view_state: &mut V,
_rendered_element: Option<Self::ElementState>,
cx: &mut ViewContext<V>,
) -> Self::ElementState {
let render = self.take().unwrap();
let mut rendered_element = (render)(view_state, cx).render();
rendered_element.initialize(view_state, cx);
rendered_element
}
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V, view_state: &mut V,
rendered_element: &mut Self::ElementState, _: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> LayoutId { ) -> (LayoutId, Self::ElementState) {
rendered_element.layout(view_state, cx) let render = self.take().unwrap();
let mut rendered_element = (render)(view_state, cx).render();
let layout_id = rendered_element.layout(view_state, cx);
(layout_id, rendered_element)
} }
fn paint( fn paint(

View file

@ -437,14 +437,6 @@ pub trait FocusableComponent<V: 'static>: InteractiveComponent<V> {
self self
} }
fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
where
Self: Sized,
{
self.interactivity().focus_in_style = f(StyleRefinement::default());
self
}
fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
where where
Self: Sized, Self: Sized,
@ -617,46 +609,36 @@ impl<V: 'static> Element<V> for Div<V> {
self.interactivity.element_id.clone() self.interactivity.element_id.clone()
} }
fn initialize( fn layout(
&mut self, &mut self,
view_state: &mut V, view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
let interactive_state = self let mut child_layout_ids = SmallVec::new();
.interactivity
.initialize(element_state.map(|s| s.interactive_state), cx);
for child in &mut self.children {
child.initialize(view_state, cx);
}
DivState {
interactive_state,
child_layout_ids: SmallVec::new(),
}
}
fn layout(
&mut self,
view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> crate::LayoutId {
let mut interactivity = mem::take(&mut self.interactivity); let mut interactivity = mem::take(&mut self.interactivity);
let layout_id = let (layout_id, interactive_state) = interactivity.layout(
interactivity.layout(&mut element_state.interactive_state, cx, |style, cx| { element_state.map(|s| s.interactive_state),
cx,
|style, cx| {
cx.with_text_style(style.text_style().cloned(), |cx| { cx.with_text_style(style.text_style().cloned(), |cx| {
element_state.child_layout_ids = self child_layout_ids = self
.children .children
.iter_mut() .iter_mut()
.map(|child| child.layout(view_state, cx)) .map(|child| child.layout(view_state, cx))
.collect::<SmallVec<_>>(); .collect::<SmallVec<_>>();
cx.request_layout(&style, element_state.child_layout_ids.iter().copied()) cx.request_layout(&style, child_layout_ids.iter().copied())
}) })
}); },
);
self.interactivity = interactivity; self.interactivity = interactivity;
layout_id (
layout_id,
DivState {
interactive_state,
child_layout_ids,
},
)
} }
fn paint( fn paint(
@ -740,7 +722,6 @@ pub struct Interactivity<V> {
pub group: Option<SharedString>, pub group: Option<SharedString>,
pub base_style: StyleRefinement, pub base_style: StyleRefinement,
pub focus_style: StyleRefinement, pub focus_style: StyleRefinement,
pub focus_in_style: StyleRefinement,
pub in_focus_style: StyleRefinement, pub in_focus_style: StyleRefinement,
pub hover_style: StyleRefinement, pub hover_style: StyleRefinement,
pub group_hover_style: Option<GroupStyle>, pub group_hover_style: Option<GroupStyle>,
@ -766,11 +747,12 @@ impl<V> Interactivity<V>
where where
V: 'static, V: 'static,
{ {
pub fn initialize( pub fn layout(
&mut self, &mut self,
element_state: Option<InteractiveElementState>, element_state: Option<InteractiveElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> InteractiveElementState { f: impl FnOnce(Style, &mut ViewContext<V>) -> LayoutId,
) -> (LayoutId, InteractiveElementState) {
let mut element_state = element_state.unwrap_or_default(); let mut element_state = element_state.unwrap_or_default();
// Ensure we store a focus handle in our element state if we're focusable. // Ensure we store a focus handle in our element state if we're focusable.
@ -785,17 +767,9 @@ where
}); });
} }
element_state let style = self.compute_style(None, &mut element_state, cx);
} let layout_id = f(style, cx);
(layout_id, element_state)
pub fn layout(
&mut self,
element_state: &mut InteractiveElementState,
cx: &mut ViewContext<V>,
f: impl FnOnce(Style, &mut ViewContext<V>) -> LayoutId,
) -> LayoutId {
let style = self.compute_style(None, element_state, cx);
f(style, cx)
} }
pub fn paint( pub fn paint(
@ -1130,10 +1104,6 @@ where
style.refine(&self.base_style); style.refine(&self.base_style);
if let Some(focus_handle) = self.tracked_focus_handle.as_ref() { if let Some(focus_handle) = self.tracked_focus_handle.as_ref() {
if focus_handle.contains_focused(cx) {
style.refine(&self.focus_in_style);
}
if focus_handle.within_focused(cx) { if focus_handle.within_focused(cx) {
style.refine(&self.in_focus_style); style.refine(&self.in_focus_style);
} }
@ -1206,7 +1176,6 @@ impl<V: 'static> Default for Interactivity<V> {
group: None, group: None,
base_style: StyleRefinement::default(), base_style: StyleRefinement::default(),
focus_style: StyleRefinement::default(), focus_style: StyleRefinement::default(),
focus_in_style: StyleRefinement::default(),
in_focus_style: StyleRefinement::default(), in_focus_style: StyleRefinement::default(),
hover_style: StyleRefinement::default(), hover_style: StyleRefinement::default(),
group_hover_style: None, group_hover_style: None,
@ -1327,21 +1296,12 @@ where
self.element.element_id() self.element.element_id()
} }
fn initialize( fn layout(
&mut self, &mut self,
view_state: &mut V, view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
self.element.initialize(view_state, element_state, cx)
}
fn layout(
&mut self,
view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId {
self.element.layout(view_state, element_state, cx) self.element.layout(view_state, element_state, cx)
} }
@ -1422,21 +1382,12 @@ where
self.element.element_id() self.element.element_id()
} }
fn initialize( fn layout(
&mut self, &mut self,
view_state: &mut V, view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
self.element.initialize(view_state, element_state, cx)
}
fn layout(
&mut self,
view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId {
self.element.layout(view_state, element_state, cx) self.element.layout(view_state, element_state, cx)
} }

View file

@ -48,21 +48,12 @@ impl<V> Element<V> for Img<V> {
self.interactivity.element_id.clone() self.interactivity.element_id.clone()
} }
fn initialize( fn layout(
&mut self, &mut self,
_view_state: &mut V, _view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
self.interactivity.initialize(element_state, cx)
}
fn layout(
&mut self,
_view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId {
self.interactivity.layout(element_state, cx, |style, cx| { self.interactivity.layout(element_state, cx, |style, cx| {
cx.request_layout(&style, None) cx.request_layout(&style, None)
}) })

View file

@ -37,21 +37,12 @@ impl<V> Element<V> for Svg<V> {
self.interactivity.element_id.clone() self.interactivity.element_id.clone()
} }
fn initialize( fn layout(
&mut self, &mut self,
_view_state: &mut V, _view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
self.interactivity.initialize(element_state, cx)
}
fn layout(
&mut self,
_view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId {
self.interactivity.layout(element_state, cx, |style, cx| { self.interactivity.layout(element_state, cx, |style, cx| {
cx.request_layout(&style, None) cx.request_layout(&style, None)
}) })

View file

@ -76,21 +76,13 @@ impl<V: 'static> Element<V> for Text<V> {
None None
} }
fn initialize(
&mut self,
_view_state: &mut V,
element_state: Option<Self::ElementState>,
_cx: &mut ViewContext<V>,
) -> Self::ElementState {
element_state.unwrap_or_default()
}
fn layout( fn layout(
&mut self, &mut self,
_view: &mut V, _view: &mut V,
element_state: &mut Self::ElementState, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> LayoutId { ) -> (LayoutId, Self::ElementState) {
let element_state = element_state.unwrap_or_default();
let text_system = cx.text_system().clone(); let text_system = cx.text_system().clone();
let text_style = cx.text_style(); let text_style = cx.text_style();
let font_size = text_style.font_size.to_pixels(cx.rem_size()); let font_size = text_style.font_size.to_pixels(cx.rem_size());
@ -148,7 +140,7 @@ impl<V: 'static> Element<V> for Text<V> {
} }
}); });
layout_id (layout_id, element_state)
} }
fn paint( fn paint(

View file

@ -108,45 +108,30 @@ impl<V: 'static> Element<V> for UniformList<V> {
Some(self.id.clone()) Some(self.id.clone())
} }
fn initialize( fn layout(
&mut self, &mut self,
view_state: &mut V, view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut ViewContext<V>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
if let Some(mut element_state) = element_state {
element_state.interactive = self
.interactivity
.initialize(Some(element_state.interactive), cx);
element_state
} else {
let item_size = self.measure_item(view_state, None, cx);
UniformListState {
interactive: self.interactivity.initialize(None, cx),
item_size,
}
}
}
fn layout(
&mut self,
_view_state: &mut V,
element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>,
) -> LayoutId {
let max_items = self.item_count; let max_items = self.item_count;
let item_size = element_state.item_size;
let rem_size = cx.rem_size(); let rem_size = cx.rem_size();
let item_size = element_state
.as_ref()
.map(|s| s.item_size)
.unwrap_or_else(|| self.measure_item(view_state, None, cx));
let (layout_id, interactive) =
self.interactivity self.interactivity
.layout(&mut element_state.interactive, cx, |style, cx| { .layout(element_state.map(|s| s.interactive), cx, |style, cx| {
cx.request_measured_layout( cx.request_measured_layout(
style, style,
rem_size, rem_size,
move |known_dimensions: Size<Option<Pixels>>, move |known_dimensions: Size<Option<Pixels>>,
available_space: Size<AvailableSpace>| { available_space: Size<AvailableSpace>| {
let desired_height = item_size.height * max_items; let desired_height = item_size.height * max_items;
let width = known_dimensions let width =
known_dimensions
.width .width
.unwrap_or(match available_space.width { .unwrap_or(match available_space.width {
AvailableSpace::Definite(x) => x, AvailableSpace::Definite(x) => x,
@ -163,7 +148,14 @@ impl<V: 'static> Element<V> for UniformList<V> {
size(width, height) size(width, height)
}, },
) )
}) });
let element_state = UniformListState {
interactive,
item_size,
};
(layout_id, element_state)
} }
fn paint( fn paint(

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace,
Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId, Model, Pixels, BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId,
Size, ViewContext, VisualContext, WeakModel, WindowContext, Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel, WindowContext,
}; };
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::{ use std::{
@ -155,8 +155,7 @@ impl<V> Eq for WeakView<V> {}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct AnyView { pub struct AnyView {
model: AnyModel, model: AnyModel,
initialize: fn(&AnyView, &mut WindowContext) -> AnyBox, layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
} }
@ -164,7 +163,6 @@ impl AnyView {
pub fn downgrade(&self) -> AnyWeakView { pub fn downgrade(&self) -> AnyWeakView {
AnyWeakView { AnyWeakView {
model: self.model.downgrade(), model: self.model.downgrade(),
initialize: self.initialize,
layout: self.layout, layout: self.layout,
paint: self.paint, paint: self.paint,
} }
@ -175,7 +173,6 @@ impl AnyView {
Ok(model) => Ok(View { model }), Ok(model) => Ok(View { model }),
Err(model) => Err(Self { Err(model) => Err(Self {
model, model,
initialize: self.initialize,
layout: self.layout, layout: self.layout,
paint: self.paint, paint: self.paint,
}), }),
@ -186,13 +183,19 @@ impl AnyView {
self.model.entity_type self.model.entity_type
} }
pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) { pub(crate) fn draw(
let mut rendered_element = (self.initialize)(self, cx); &self,
let layout_id = (self.layout)(self, &mut rendered_element, cx); origin: Point<Pixels>,
available_space: Size<AvailableSpace>,
cx: &mut WindowContext,
) {
cx.with_absolute_element_offset(origin, |cx| {
let (layout_id, mut rendered_element) = (self.layout)(self, cx);
cx.window cx.window
.layout_engine .layout_engine
.compute_layout(layout_id, available_space); .compute_layout(layout_id, available_space);
(self.paint)(self, &mut rendered_element, cx); (self.paint)(self, &mut rendered_element, cx);
})
} }
} }
@ -206,7 +209,6 @@ impl<V: Render> From<View<V>> for AnyView {
fn from(value: View<V>) -> Self { fn from(value: View<V>) -> Self {
AnyView { AnyView {
model: value.model.into_any(), model: value.model.into_any(),
initialize: any_view::initialize::<V>,
layout: any_view::layout::<V>, layout: any_view::layout::<V>,
paint: any_view::paint::<V>, paint: any_view::paint::<V>,
} }
@ -220,22 +222,13 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
Some(self.model.entity_id.into()) Some(self.model.entity_id.into())
} }
fn initialize( fn layout(
&mut self, &mut self,
_view_state: &mut ParentViewState, _view_state: &mut ParentViewState,
_element_state: Option<Self::ElementState>, _element_state: Option<Self::ElementState>,
cx: &mut ViewContext<ParentViewState>, cx: &mut ViewContext<ParentViewState>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
(self.initialize)(self, cx) (self.layout)(self, cx)
}
fn layout(
&mut self,
_view_state: &mut ParentViewState,
rendered_element: &mut Self::ElementState,
cx: &mut ViewContext<ParentViewState>,
) -> LayoutId {
(self.layout)(self, rendered_element, cx)
} }
fn paint( fn paint(
@ -251,8 +244,7 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
pub struct AnyWeakView { pub struct AnyWeakView {
model: AnyWeakModel, model: AnyWeakModel,
initialize: fn(&AnyView, &mut WindowContext) -> AnyBox, layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
paint: fn(&AnyView, &mut AnyBox, &mut WindowContext), paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
} }
@ -261,7 +253,6 @@ impl AnyWeakView {
let model = self.model.upgrade()?; let model = self.model.upgrade()?;
Some(AnyView { Some(AnyView {
model, model,
initialize: self.initialize,
layout: self.layout, layout: self.layout,
paint: self.paint, paint: self.paint,
}) })
@ -272,7 +263,6 @@ impl<V: Render> From<WeakView<V>> for AnyWeakView {
fn from(view: WeakView<V>) -> Self { fn from(view: WeakView<V>) -> Self {
Self { Self {
model: view.model.into(), model: view.model.into(),
initialize: any_view::initialize::<V>,
layout: any_view::layout::<V>, layout: any_view::layout::<V>,
paint: any_view::paint::<V>, paint: any_view::paint::<V>,
} }
@ -319,28 +309,19 @@ where
Some(self.view.entity_id().into()) Some(self.view.entity_id().into())
} }
fn initialize( fn layout(
&mut self, &mut self,
_: &mut ParentViewState, _: &mut ParentViewState,
_: Option<Self::ElementState>, _: Option<Self::ElementState>,
cx: &mut ViewContext<ParentViewState>, cx: &mut ViewContext<ParentViewState>,
) -> Self::ElementState { ) -> (LayoutId, Self::ElementState) {
self.view.update(cx, |view, cx| { self.view.update(cx, |view, cx| {
let mut element = self.component.take().unwrap().render(); let mut element = self.component.take().unwrap().render();
element.initialize(view, cx); let layout_id = element.layout(view, cx);
element (layout_id, element)
}) })
} }
fn layout(
&mut self,
_: &mut ParentViewState,
element: &mut Self::ElementState,
cx: &mut ViewContext<ParentViewState>,
) -> LayoutId {
self.view.update(cx, |view, cx| element.layout(view, cx))
}
fn paint( fn paint(
&mut self, &mut self,
_: Bounds<Pixels>, _: Bounds<Pixels>,
@ -356,27 +337,17 @@ mod any_view {
use crate::{AnyElement, AnyView, BorrowWindow, LayoutId, Render, WindowContext}; use crate::{AnyElement, AnyView, BorrowWindow, LayoutId, Render, WindowContext};
use std::any::Any; use std::any::Any;
pub(crate) fn initialize<V: Render>(view: &AnyView, cx: &mut WindowContext) -> Box<dyn Any> {
cx.with_element_id(Some(view.model.entity_id), |cx| {
let view = view.clone().downcast::<V>().unwrap();
let element = view.update(cx, |view, cx| {
let mut element = AnyElement::new(view.render(cx));
element.initialize(view, cx);
element
});
Box::new(element)
})
}
pub(crate) fn layout<V: Render>( pub(crate) fn layout<V: Render>(
view: &AnyView, view: &AnyView,
element: &mut Box<dyn Any>,
cx: &mut WindowContext, cx: &mut WindowContext,
) -> LayoutId { ) -> (LayoutId, Box<dyn Any>) {
cx.with_element_id(Some(view.model.entity_id), |cx| { cx.with_element_id(Some(view.model.entity_id), |cx| {
let view = view.clone().downcast::<V>().unwrap(); let view = view.clone().downcast::<V>().unwrap();
let element = element.downcast_mut::<AnyElement<V>>().unwrap(); view.update(cx, |view, cx| {
view.update(cx, |view, cx| element.layout(view, cx)) let mut element = AnyElement::new(view.render(cx));
let layout_id = element.layout(view, cx);
(layout_id, Box::new(element) as Box<dyn Any>)
})
}) })
} }

View file

@ -1076,26 +1076,22 @@ impl<'a> WindowContext<'a> {
self.with_z_index(0, |cx| { self.with_z_index(0, |cx| {
let available_space = cx.window.viewport_size.map(Into::into); let available_space = cx.window.viewport_size.map(Into::into);
root_view.draw(available_space, cx); root_view.draw(Point::zero(), available_space, cx);
}); });
if let Some(active_drag) = self.app.active_drag.take() { if let Some(active_drag) = self.app.active_drag.take() {
self.with_z_index(1, |cx| { self.with_z_index(1, |cx| {
let offset = cx.mouse_position() - active_drag.cursor_offset; let offset = cx.mouse_position() - active_drag.cursor_offset;
cx.with_element_offset(offset, |cx| { let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
let available_space = active_drag.view.draw(offset, available_space, cx);
size(AvailableSpace::MinContent, AvailableSpace::MinContent);
active_drag.view.draw(available_space, cx);
cx.active_drag = Some(active_drag); cx.active_drag = Some(active_drag);
}); });
});
} else if let Some(active_tooltip) = self.app.active_tooltip.take() { } else if let Some(active_tooltip) = self.app.active_tooltip.take() {
self.with_z_index(1, |cx| { self.with_z_index(1, |cx| {
cx.with_element_offset(active_tooltip.cursor_offset, |cx| { let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
let available_space = active_tooltip
size(AvailableSpace::MinContent, AvailableSpace::MinContent); .view
active_tooltip.view.draw(available_space, cx); .draw(active_tooltip.cursor_offset, available_space, cx);
});
}); });
} }
@ -1633,8 +1629,8 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
} }
} }
/// Update the global element offset based on the given offset. This is used to implement /// Update the global element offset relative to the current offset. This is used to implement
/// scrolling and position drag handles. /// scrolling.
fn with_element_offset<R>( fn with_element_offset<R>(
&mut self, &mut self,
offset: Point<Pixels>, offset: Point<Pixels>,
@ -1644,7 +1640,17 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
return f(self); return f(self);
}; };
let offset = self.element_offset() + offset; let abs_offset = self.element_offset() + offset;
self.with_absolute_element_offset(abs_offset, f)
}
/// Update the global element offset based on the given offset. This is used to implement
/// drag handles and other manual painting of elements.
fn with_absolute_element_offset<R>(
&mut self,
offset: Point<Pixels>,
f: impl FnOnce(&mut Self) -> R,
) -> R {
self.window_mut() self.window_mut()
.current_frame .current_frame
.element_offset_stack .element_offset_stack

View file

@ -57,7 +57,6 @@ impl Render for FocusStory {
.size_full() .size_full()
.bg(color_1) .bg(color_1)
.focus(|style| style.bg(color_2)) .focus(|style| style.bg(color_2))
.focus_in(|style| style.bg(color_3))
.child( .child(
div() div()
.track_focus(&self.child_1_focus) .track_focus(&self.child_1_focus)