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:
commit
e5ada92b7b
10 changed files with 147 additions and 316 deletions
|
@ -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(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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>)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue