Remove V parameter on elements

This commit is contained in:
Mikayla 2023-11-19 18:32:31 -08:00
parent c0d85dc1dd
commit 88024ca7c9
No known key found for this signature in database
13 changed files with 578 additions and 665 deletions

View file

@ -631,7 +631,7 @@ impl AnyWindowHandle {
pub struct EmptyView {} pub struct EmptyView {}
impl Render for EmptyView { impl Render for EmptyView {
type Element = Div<Self>; type Element = Div;
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Element { fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Element {
div() div()

View file

@ -1,37 +1,34 @@
use crate::{ use crate::{
AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, WindowContext,
}; };
use derive_more::{Deref, DerefMut}; use derive_more::{Deref, DerefMut};
pub(crate) use smallvec::SmallVec; pub(crate) use smallvec::SmallVec;
use std::{any::Any, fmt::Debug, mem}; use std::{any::Any, fmt::Debug, mem};
pub trait Element<V: 'static> { pub trait Element {
type ElementState: 'static; type ElementState: 'static;
fn element_id(&self) -> Option<ElementId>; fn element_id(&self) -> Option<ElementId>;
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState); ) -> (LayoutId, Self::ElementState);
fn paint( fn paint(
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
view_state: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
); );
fn draw<T, R>( fn draw<T, R>(
self, self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<T>, available_space: Size<T>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>, f: impl FnOnce(&Self::ElementState, &mut WindowContext) -> R,
f: impl FnOnce(&Self::ElementState, &mut ViewContext<V>) -> R,
) -> R ) -> R
where where
Self: Sized, Self: Sized,
@ -41,7 +38,7 @@ pub trait Element<V: 'static> {
element: self, element: self,
phase: ElementRenderPhase::Start, phase: ElementRenderPhase::Start,
}; };
element.draw(origin, available_space.map(Into::into), view_state, cx); element.draw(origin, available_space.map(Into::into), cx);
if let ElementRenderPhase::Painted { frame_state } = &element.phase { if let ElementRenderPhase::Painted { frame_state } = &element.phase {
if let Some(frame_state) = frame_state.as_ref() { if let Some(frame_state) = frame_state.as_ref() {
f(&frame_state, cx) f(&frame_state, cx)
@ -65,10 +62,10 @@ pub trait Element<V: 'static> {
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
pub struct GlobalElementId(SmallVec<[ElementId; 32]>); pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
pub trait ParentComponent<V: 'static> { pub trait ParentComponent {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>; fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>;
fn child(mut self, child: impl Component<V>) -> Self fn child(mut self, child: impl Component) -> Self
where where
Self: Sized, Self: Sized,
{ {
@ -76,7 +73,7 @@ pub trait ParentComponent<V: 'static> {
self self
} }
fn children(mut self, iter: impl IntoIterator<Item = impl Component<V>>) -> Self fn children(mut self, iter: impl IntoIterator<Item = impl Component>) -> Self
where where
Self: Sized, Self: Sized,
{ {
@ -86,26 +83,24 @@ pub trait ParentComponent<V: 'static> {
} }
} }
trait ElementObject<V> { trait ElementObject {
fn element_id(&self) -> Option<ElementId>; fn element_id(&self) -> Option<ElementId>;
fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId; fn layout(&mut self, cx: &mut WindowContext) -> LayoutId;
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>); fn paint(&mut self, cx: &mut WindowContext);
fn measure( fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>,
) -> Size<Pixels>; ) -> Size<Pixels>;
fn draw( fn draw(
&mut self, &mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>,
); );
} }
struct RenderedElement<V: 'static, E: Element<V>> { struct RenderedElement<E: Element> {
element: E, element: E,
phase: ElementRenderPhase<E::ElementState>, phase: ElementRenderPhase<E::ElementState>,
} }
@ -131,7 +126,7 @@ enum ElementRenderPhase<V> {
/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered. /// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for /// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
/// improved usability. /// improved usability.
impl<V, E: Element<V>> RenderedElement<V, E> { impl<E: Element> RenderedElement<E> {
fn new(element: E) -> Self { fn new(element: E) -> Self {
RenderedElement { RenderedElement {
element, element,
@ -140,25 +135,25 @@ impl<V, E: Element<V>> RenderedElement<V, E> {
} }
} }
impl<V, E> ElementObject<V> for RenderedElement<V, E> impl<E> ElementObject for RenderedElement<E>
where where
E: Element<V>, E: Element,
E::ElementState: 'static, E::ElementState: 'static,
{ {
fn element_id(&self) -> Option<ElementId> { fn element_id(&self) -> Option<ElementId> {
self.element.element_id() self.element.element_id()
} }
fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId { fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
let (layout_id, frame_state) = match mem::take(&mut self.phase) { let (layout_id, frame_state) = match mem::take(&mut self.phase) {
ElementRenderPhase::Start => { ElementRenderPhase::Start => {
if let Some(id) = self.element.element_id() { if let Some(id) = self.element.element_id() {
let layout_id = cx.with_element_state(id, |element_state, cx| { let layout_id = cx.with_element_state(id, |element_state, cx| {
self.element.layout(state, element_state, cx) self.element.layout(element_state, cx)
}); });
(layout_id, None) (layout_id, None)
} else { } else {
let (layout_id, frame_state) = self.element.layout(state, None, cx); let (layout_id, frame_state) = self.element.layout(None, cx);
(layout_id, Some(frame_state)) (layout_id, Some(frame_state))
} }
} }
@ -176,7 +171,7 @@ where
layout_id layout_id
} }
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) { fn paint(&mut self, cx: &mut WindowContext) {
self.phase = match mem::take(&mut self.phase) { self.phase = match mem::take(&mut self.phase) {
ElementRenderPhase::LayoutRequested { ElementRenderPhase::LayoutRequested {
layout_id, layout_id,
@ -191,13 +186,12 @@ where
if let Some(id) = self.element.element_id() { if let Some(id) = self.element.element_id() {
cx.with_element_state(id, |element_state, cx| { cx.with_element_state(id, |element_state, cx| {
let mut element_state = element_state.unwrap(); let mut element_state = element_state.unwrap();
self.element self.element.paint(bounds, &mut element_state, cx);
.paint(bounds, view_state, &mut element_state, cx);
((), element_state) ((), element_state)
}); });
} else { } else {
self.element self.element
.paint(bounds, view_state, frame_state.as_mut().unwrap(), cx); .paint(bounds, frame_state.as_mut().unwrap(), cx);
} }
ElementRenderPhase::Painted { frame_state } ElementRenderPhase::Painted { frame_state }
} }
@ -209,11 +203,10 @@ where
fn measure( fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>,
) -> Size<Pixels> { ) -> Size<Pixels> {
if matches!(&self.phase, ElementRenderPhase::Start) { if matches!(&self.phase, ElementRenderPhase::Start) {
self.layout(view_state, cx); self.layout(cx);
} }
let layout_id = match &mut self.phase { let layout_id = match &mut self.phase {
@ -251,21 +244,19 @@ where
&mut self, &mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>,
) { ) {
self.measure(available_space, view_state, cx); self.measure(available_space, cx);
cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx)) cx.with_absolute_element_offset(origin, |cx| self.paint(cx))
} }
} }
pub struct AnyElement<V>(Box<dyn ElementObject<V>>); pub struct AnyElement(Box<dyn ElementObject>);
impl<V> AnyElement<V> { impl AnyElement {
pub fn new<E>(element: E) -> Self pub fn new<E>(element: E) -> Self
where where
V: 'static, E: 'static + Element,
E: 'static + Element<V>,
E::ElementState: Any, E::ElementState: Any,
{ {
AnyElement(Box::new(RenderedElement::new(element))) AnyElement(Box::new(RenderedElement::new(element)))
@ -275,22 +266,21 @@ impl<V> AnyElement<V> {
self.0.element_id() self.0.element_id()
} }
pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId { pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
self.0.layout(view_state, cx) self.0.layout(cx)
} }
pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) { pub fn paint(&mut self, cx: &mut WindowContext) {
self.0.paint(view_state, cx) self.0.paint(cx)
} }
/// Initializes this element and performs layout within the given available space to determine its size. /// Initializes this element and performs layout within the given available space to determine its size.
pub fn measure( pub fn measure(
&mut self, &mut self,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>,
) -> Size<Pixels> { ) -> Size<Pixels> {
self.0.measure(available_space, view_state, cx) self.0.measure(available_space, cx)
} }
/// Initializes this element and performs layout in the available space, then paints it at the given origin. /// Initializes this element and performs layout in the available space, then paints it at the given origin.
@ -298,20 +288,19 @@ impl<V> AnyElement<V> {
&mut self, &mut self,
origin: Point<Pixels>, origin: Point<Pixels>,
available_space: Size<AvailableSpace>, available_space: Size<AvailableSpace>,
view_state: &mut V, cx: &mut WindowContext,
cx: &mut ViewContext<V>,
) { ) {
self.0.draw(origin, available_space, view_state, cx) self.0.draw(origin, available_space, cx)
} }
} }
pub trait Component<V> { pub trait Component {
fn render(self) -> AnyElement<V>; fn render(self) -> AnyElement;
fn map<U>(self, f: impl FnOnce(Self) -> U) -> U fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
where where
Self: Sized, Self: Sized,
U: Component<V>, U: Component,
{ {
f(self) f(self)
} }
@ -337,19 +326,18 @@ pub trait Component<V> {
} }
} }
impl<V> Component<V> for AnyElement<V> { impl Component for AnyElement {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
self self
} }
} }
impl<V, E, F> Element<V> for Option<F> impl<E, F> Element for Option<F>
where where
V: 'static, E: 'static + Component,
E: 'static + Component<V>, F: FnOnce(&mut WindowContext) -> E + 'static,
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
{ {
type ElementState = AnyElement<V>; type ElementState = AnyElement;
fn element_id(&self) -> Option<ElementId> { fn element_id(&self) -> Option<ElementId> {
None None
@ -357,45 +345,41 @@ where
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V,
_: Option<Self::ElementState>, _: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
let render = self.take().unwrap(); let render = self.take().unwrap();
let mut rendered_element = (render)(view_state, cx).render(); let mut rendered_element = (render)(cx).render();
let layout_id = rendered_element.layout(view_state, cx); let layout_id = rendered_element.layout(cx);
(layout_id, rendered_element) (layout_id, rendered_element)
} }
fn paint( fn paint(
&mut self, &mut self,
_bounds: Bounds<Pixels>, _bounds: Bounds<Pixels>,
view_state: &mut V,
rendered_element: &mut Self::ElementState, rendered_element: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) { ) {
rendered_element.paint(view_state, cx) rendered_element.paint(cx)
} }
} }
impl<V, E, F> Component<V> for Option<F> impl<E, F> Component for Option<F>
where where
V: 'static, E: 'static + Component,
E: 'static + Component<V>, F: FnOnce(&mut WindowContext) -> E + 'static,
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
{ {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
impl<V, E, F> Component<V> for F impl<E, F> Component for F
where where
V: 'static, E: 'static + Component,
E: 'static + Component<V>, F: FnOnce(&mut WindowContext) -> E + 'static,
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
{ {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(Some(self)) AnyElement::new(Some(self))
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,17 @@
use crate::{ use crate::{
AnyElement, BorrowWindow, Bounds, Component, Element, InteractiveComponent, AnyElement, Bounds, Component, Element, InteractiveComponent, InteractiveElementState,
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, Styled, WindowContext,
Styled, ViewContext,
}; };
use futures::FutureExt; use futures::FutureExt;
use util::ResultExt; use util::ResultExt;
pub struct Img<V: 'static> { pub struct Img {
interactivity: Interactivity<V>, interactivity: Interactivity,
uri: Option<SharedString>, uri: Option<SharedString>,
grayscale: bool, grayscale: bool,
} }
pub fn img<V: 'static>() -> Img<V> { pub fn img() -> Img {
Img { Img {
interactivity: Interactivity::default(), interactivity: Interactivity::default(),
uri: None, uri: None,
@ -20,10 +19,7 @@ pub fn img<V: 'static>() -> Img<V> {
} }
} }
impl<V> Img<V> impl Img {
where
V: 'static,
{
pub fn uri(mut self, uri: impl Into<SharedString>) -> Self { pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
self.uri = Some(uri.into()); self.uri = Some(uri.into());
self self
@ -35,13 +31,13 @@ where
} }
} }
impl<V> Component<V> for Img<V> { impl Component for Img {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
impl<V> Element<V> for Img<V> { impl Element for Img {
type ElementState = InteractiveElementState; type ElementState = InteractiveElementState;
fn element_id(&self) -> Option<crate::ElementId> { fn element_id(&self) -> Option<crate::ElementId> {
@ -50,9 +46,8 @@ impl<V> Element<V> for Img<V> {
fn layout( fn layout(
&mut self, &mut self,
_view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
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)
@ -62,9 +57,8 @@ impl<V> Element<V> for Img<V> {
fn paint( fn paint(
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
_view_state: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) { ) {
self.interactivity.paint( self.interactivity.paint(
bounds, bounds,
@ -89,7 +83,7 @@ impl<V> Element<V> for Img<V> {
.log_err() .log_err()
}); });
} else { } else {
cx.spawn(|_, mut cx| async move { cx.spawn(|mut cx| async move {
if image_future.await.ok().is_some() { if image_future.await.ok().is_some() {
cx.on_next_frame(|cx| cx.notify()); cx.on_next_frame(|cx| cx.notify());
} }
@ -102,14 +96,14 @@ impl<V> Element<V> for Img<V> {
} }
} }
impl<V> Styled for Img<V> { impl Styled for Img {
fn style(&mut self) -> &mut StyleRefinement { fn style(&mut self) -> &mut StyleRefinement {
&mut self.interactivity.base_style &mut self.interactivity.base_style
} }
} }
impl<V> InteractiveComponent<V> for Img<V> { impl InteractiveComponent for Img {
fn interactivity(&mut self) -> &mut Interactivity<V> { fn interactivity(&mut self) -> &mut Interactivity {
&mut self.interactivity &mut self.interactivity
} }
} }

View file

@ -3,15 +3,15 @@ use taffy::style::{Display, Position};
use crate::{ use crate::{
point, AnyElement, BorrowWindow, Bounds, Component, Element, LayoutId, ParentComponent, Pixels, point, AnyElement, BorrowWindow, Bounds, Component, Element, LayoutId, ParentComponent, Pixels,
Point, Size, Style, Point, Size, Style, WindowContext,
}; };
pub struct OverlayState { pub struct OverlayState {
child_layout_ids: SmallVec<[LayoutId; 4]>, child_layout_ids: SmallVec<[LayoutId; 4]>,
} }
pub struct Overlay<V> { pub struct Overlay {
children: SmallVec<[AnyElement<V>; 2]>, children: SmallVec<[AnyElement; 2]>,
anchor_corner: AnchorCorner, anchor_corner: AnchorCorner,
fit_mode: OverlayFitMode, fit_mode: OverlayFitMode,
// todo!(); // todo!();
@ -21,7 +21,7 @@ pub struct Overlay<V> {
/// overlay gives you a floating element that will avoid overflowing the window bounds. /// overlay gives you a floating element that will avoid overflowing the window bounds.
/// Its children should have no margin to avoid measurement issues. /// Its children should have no margin to avoid measurement issues.
pub fn overlay<V: 'static>() -> Overlay<V> { pub fn overlay() -> Overlay {
Overlay { Overlay {
children: SmallVec::new(), children: SmallVec::new(),
anchor_corner: AnchorCorner::TopLeft, anchor_corner: AnchorCorner::TopLeft,
@ -30,7 +30,7 @@ pub fn overlay<V: 'static>() -> Overlay<V> {
} }
} }
impl<V> Overlay<V> { impl Overlay {
/// Sets which corner of the overlay should be anchored to the current position. /// Sets which corner of the overlay should be anchored to the current position.
pub fn anchor(mut self, anchor: AnchorCorner) -> Self { pub fn anchor(mut self, anchor: AnchorCorner) -> Self {
self.anchor_corner = anchor; self.anchor_corner = anchor;
@ -51,19 +51,19 @@ impl<V> Overlay<V> {
} }
} }
impl<V: 'static> ParentComponent<V> for Overlay<V> { impl ParentComponent for Overlay {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
&mut self.children &mut self.children
} }
} }
impl<V: 'static> Component<V> for Overlay<V> { impl Component for Overlay {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
impl<V: 'static> Element<V> for Overlay<V> { impl Element for Overlay {
type ElementState = OverlayState; type ElementState = OverlayState;
fn element_id(&self) -> Option<crate::ElementId> { fn element_id(&self) -> Option<crate::ElementId> {
@ -72,14 +72,13 @@ impl<V: 'static> Element<V> for Overlay<V> {
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V,
_: Option<Self::ElementState>, _: Option<Self::ElementState>,
cx: &mut crate::ViewContext<V>, cx: &mut WindowContext,
) -> (crate::LayoutId, Self::ElementState) { ) -> (crate::LayoutId, Self::ElementState) {
let child_layout_ids = self let child_layout_ids = self
.children .children
.iter_mut() .iter_mut()
.map(|child| child.layout(view_state, cx)) .map(|child| child.layout(cx))
.collect::<SmallVec<_>>(); .collect::<SmallVec<_>>();
let mut overlay_style = Style::default(); let mut overlay_style = Style::default();
@ -94,9 +93,8 @@ impl<V: 'static> Element<V> for Overlay<V> {
fn paint( fn paint(
&mut self, &mut self,
bounds: crate::Bounds<crate::Pixels>, bounds: crate::Bounds<crate::Pixels>,
view_state: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut crate::ViewContext<V>, cx: &mut WindowContext,
) { ) {
if element_state.child_layout_ids.is_empty() { if element_state.child_layout_ids.is_empty() {
return; return;
@ -157,7 +155,7 @@ impl<V: 'static> Element<V> for Overlay<V> {
cx.with_element_offset(desired.origin - bounds.origin, |cx| { cx.with_element_offset(desired.origin - bounds.origin, |cx| {
for child in &mut self.children { for child in &mut self.children {
child.paint(view_state, cx); child.paint(cx);
} }
}) })
} }

View file

@ -1,36 +1,36 @@
use crate::{ use crate::{
AnyElement, Bounds, Component, Element, ElementId, InteractiveComponent, AnyElement, Bounds, Component, Element, ElementId, InteractiveComponent,
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
Styled, ViewContext, Styled, WindowContext,
}; };
use util::ResultExt; use util::ResultExt;
pub struct Svg<V: 'static> { pub struct Svg {
interactivity: Interactivity<V>, interactivity: Interactivity,
path: Option<SharedString>, path: Option<SharedString>,
} }
pub fn svg<V: 'static>() -> Svg<V> { pub fn svg() -> Svg {
Svg { Svg {
interactivity: Interactivity::default(), interactivity: Interactivity::default(),
path: None, path: None,
} }
} }
impl<V> Svg<V> { impl Svg {
pub fn path(mut self, path: impl Into<SharedString>) -> Self { pub fn path(mut self, path: impl Into<SharedString>) -> Self {
self.path = Some(path.into()); self.path = Some(path.into());
self self
} }
} }
impl<V> Component<V> for Svg<V> { impl Component for Svg {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
impl<V> Element<V> for Svg<V> { impl Element for Svg {
type ElementState = InteractiveElementState; type ElementState = InteractiveElementState;
fn element_id(&self) -> Option<ElementId> { fn element_id(&self) -> Option<ElementId> {
@ -39,9 +39,8 @@ impl<V> Element<V> for Svg<V> {
fn layout( fn layout(
&mut self, &mut self,
_view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
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)
@ -51,9 +50,8 @@ impl<V> Element<V> for Svg<V> {
fn paint( fn paint(
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
_view_state: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) where ) where
Self: Sized, Self: Sized,
{ {
@ -66,14 +64,14 @@ impl<V> Element<V> for Svg<V> {
} }
} }
impl<V> Styled for Svg<V> { impl Styled for Svg {
fn style(&mut self) -> &mut StyleRefinement { fn style(&mut self) -> &mut StyleRefinement {
&mut self.interactivity.base_style &mut self.interactivity.base_style
} }
} }
impl<V> InteractiveComponent<V> for Svg<V> { impl InteractiveComponent for Svg {
fn interactivity(&mut self) -> &mut Interactivity<V> { fn interactivity(&mut self) -> &mut Interactivity {
&mut self.interactivity &mut self.interactivity
} }
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
AnyElement, BorrowWindow, Bounds, Component, Element, ElementId, LayoutId, Pixels, AnyElement, Bounds, Component, Element, ElementId, LayoutId, Pixels, SharedString, Size,
SharedString, Size, TextRun, ViewContext, WrappedLine, TextRun, WindowContext, WrappedLine,
}; };
use parking_lot::{Mutex, MutexGuard}; use parking_lot::{Mutex, MutexGuard};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -26,13 +26,13 @@ impl Text {
} }
} }
impl<V: 'static> Component<V> for Text { impl Component for Text {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
impl<V: 'static> Element<V> for Text { impl Element for Text {
type ElementState = TextState; type ElementState = TextState;
fn element_id(&self) -> Option<crate::ElementId> { fn element_id(&self) -> Option<crate::ElementId> {
@ -41,9 +41,8 @@ impl<V: 'static> Element<V> for Text {
fn layout( fn layout(
&mut self, &mut self,
_view: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
let element_state = element_state.unwrap_or_default(); let element_state = element_state.unwrap_or_default();
let text_system = cx.text_system().clone(); let text_system = cx.text_system().clone();
@ -120,9 +119,8 @@ impl<V: 'static> Element<V> for Text {
fn paint( fn paint(
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
_: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) { ) {
let element_state = element_state.lock(); let element_state = element_state.lock();
let element_state = element_state let element_state = element_state
@ -165,7 +163,7 @@ struct InteractiveTextState {
clicked_range_ixs: Rc<Cell<SmallVec<[usize; 1]>>>, clicked_range_ixs: Rc<Cell<SmallVec<[usize; 1]>>>,
} }
impl<V: 'static> Element<V> for InteractiveText { impl Element for InteractiveText {
type ElementState = InteractiveTextState; type ElementState = InteractiveTextState;
fn element_id(&self) -> Option<ElementId> { fn element_id(&self) -> Option<ElementId> {
@ -174,23 +172,22 @@ impl<V: 'static> Element<V> for InteractiveText {
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
if let Some(InteractiveTextState { if let Some(InteractiveTextState {
text_state, text_state,
clicked_range_ixs, clicked_range_ixs,
}) = element_state }) = element_state
{ {
let (layout_id, text_state) = self.text.layout(view_state, Some(text_state), cx); let (layout_id, text_state) = self.text.layout(Some(text_state), cx);
let element_state = InteractiveTextState { let element_state = InteractiveTextState {
text_state, text_state,
clicked_range_ixs, clicked_range_ixs,
}; };
(layout_id, element_state) (layout_id, element_state)
} else { } else {
let (layout_id, text_state) = self.text.layout(view_state, None, cx); let (layout_id, text_state) = self.text.layout(None, cx);
let element_state = InteractiveTextState { let element_state = InteractiveTextState {
text_state, text_state,
clicked_range_ixs: Rc::default(), clicked_range_ixs: Rc::default(),
@ -202,17 +199,15 @@ impl<V: 'static> Element<V> for InteractiveText {
fn paint( fn paint(
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
view_state: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) { ) {
self.text self.text.paint(bounds, &mut element_state.text_state, cx)
.paint(bounds, view_state, &mut element_state.text_state, cx)
} }
} }
impl<V: 'static> Component<V> for SharedString { impl Component for SharedString {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
Text { Text {
text: self, text: self,
runs: None, runs: None,
@ -221,8 +216,8 @@ impl<V: 'static> Component<V> for SharedString {
} }
} }
impl<V: 'static> Component<V> for &'static str { impl Component for &'static str {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
Text { Text {
text: self.into(), text: self.into(),
runs: None, runs: None,
@ -233,8 +228,8 @@ impl<V: 'static> Component<V> for &'static str {
// TODO: Figure out how to pass `String` to `child` without this. // TODO: Figure out how to pass `String` to `child` without this.
// This impl doesn't exist in the `gpui2` crate. // This impl doesn't exist in the `gpui2` crate.
impl<V: 'static> Component<V> for String { impl Component for String {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
Text { Text {
text: self.into(), text: self.into(),
runs: None, runs: None,

View file

@ -1,7 +1,7 @@
use crate::{ use crate::{
point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element, point, px, size, AnyElement, AvailableSpace, Bounds, Component, Element, ElementId,
ElementId, InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels, InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels, Point, Size,
Point, Size, StyleRefinement, Styled, ViewContext, StyleRefinement, Styled, WindowContext,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{cell::RefCell, cmp, mem, ops::Range, rc::Rc}; use std::{cell::RefCell, cmp, mem, ops::Range, rc::Rc};
@ -10,15 +10,14 @@ use taffy::style::Overflow;
/// uniform_list provides lazy rendering for a set of items that are of uniform height. /// uniform_list provides lazy rendering for a set of items that are of uniform height.
/// When rendered into a container with overflow-y: hidden and a fixed (or max) height, /// When rendered into a container with overflow-y: hidden and a fixed (or max) height,
/// uniform_list will only render the visibile subset of items. /// uniform_list will only render the visibile subset of items.
pub fn uniform_list<I, V, C>( pub fn uniform_list<I, C>(
id: I, id: I,
item_count: usize, item_count: usize,
f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> Vec<C>, f: impl 'static + Fn(Range<usize>, &mut WindowContext) -> Vec<C>,
) -> UniformList<V> ) -> UniformList
where where
I: Into<ElementId>, I: Into<ElementId>,
V: 'static, C: Component,
C: Component<V>,
{ {
let id = id.into(); let id = id.into();
let mut style = StyleRefinement::default(); let mut style = StyleRefinement::default();
@ -29,8 +28,8 @@ where
style, style,
item_count, item_count,
item_to_measure_index: 0, item_to_measure_index: 0,
render_items: Box::new(move |view, visible_range, cx| { render_items: Box::new(move |visible_range, cx| {
f(view, visible_range, cx) f(visible_range, cx)
.into_iter() .into_iter()
.map(|component| component.render()) .map(|component| component.render())
.collect() .collect()
@ -43,19 +42,14 @@ where
} }
} }
pub struct UniformList<V: 'static> { pub struct UniformList {
id: ElementId, id: ElementId,
style: StyleRefinement, style: StyleRefinement,
item_count: usize, item_count: usize,
item_to_measure_index: usize, item_to_measure_index: usize,
render_items: Box< render_items:
dyn for<'a> Fn( Box<dyn for<'a> Fn(Range<usize>, &'a mut WindowContext) -> SmallVec<[AnyElement; 64]>>,
&'a mut V, interactivity: Interactivity,
Range<usize>,
&'a mut ViewContext<V>,
) -> SmallVec<[AnyElement<V>; 64]>,
>,
interactivity: Interactivity<V>,
scroll_handle: Option<UniformListScrollHandle>, scroll_handle: Option<UniformListScrollHandle>,
} }
@ -89,7 +83,7 @@ impl UniformListScrollHandle {
} }
} }
impl<V: 'static> Styled for UniformList<V> { impl Styled for UniformList {
fn style(&mut self) -> &mut StyleRefinement { fn style(&mut self) -> &mut StyleRefinement {
&mut self.style &mut self.style
} }
@ -101,7 +95,7 @@ pub struct UniformListState {
item_size: Size<Pixels>, item_size: Size<Pixels>,
} }
impl<V: 'static> Element<V> for UniformList<V> { impl Element for UniformList {
type ElementState = UniformListState; type ElementState = UniformListState;
fn element_id(&self) -> Option<crate::ElementId> { fn element_id(&self) -> Option<crate::ElementId> {
@ -110,16 +104,15 @@ impl<V: 'static> Element<V> for UniformList<V> {
fn layout( fn layout(
&mut self, &mut self,
view_state: &mut V,
element_state: Option<Self::ElementState>, element_state: Option<Self::ElementState>,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
let max_items = self.item_count; let max_items = self.item_count;
let rem_size = cx.rem_size(); let rem_size = cx.rem_size();
let item_size = element_state let item_size = element_state
.as_ref() .as_ref()
.map(|s| s.item_size) .map(|s| s.item_size)
.unwrap_or_else(|| self.measure_item(view_state, None, cx)); .unwrap_or_else(|| self.measure_item(None, cx));
let (layout_id, interactive) = let (layout_id, interactive) =
self.interactivity self.interactivity
@ -161,9 +154,8 @@ impl<V: 'static> Element<V> for UniformList<V> {
fn paint( fn paint(
&mut self, &mut self,
bounds: Bounds<crate::Pixels>, bounds: Bounds<crate::Pixels>,
view_state: &mut V,
element_state: &mut Self::ElementState, element_state: &mut Self::ElementState,
cx: &mut ViewContext<V>, cx: &mut WindowContext,
) { ) {
let style = let style =
self.interactivity self.interactivity
@ -209,9 +201,8 @@ impl<V: 'static> Element<V> for UniformList<V> {
style.paint(bounds, cx); style.paint(bounds, cx);
if self.item_count > 0 { if self.item_count > 0 {
let item_height = self let item_height =
.measure_item(view_state, Some(padded_bounds.size.width), cx) self.measure_item(Some(padded_bounds.size.width), cx).height;
.height;
if let Some(scroll_handle) = self.scroll_handle.clone() { if let Some(scroll_handle) = self.scroll_handle.clone() {
scroll_handle.0.borrow_mut().replace(ScrollHandleState { scroll_handle.0.borrow_mut().replace(ScrollHandleState {
item_height, item_height,
@ -233,7 +224,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
self.item_count, self.item_count,
); );
let mut items = (self.render_items)(view_state, visible_range.clone(), cx); let mut items = (self.render_items)(visible_range.clone(), cx);
cx.with_z_index(1, |cx| { cx.with_z_index(1, |cx| {
for (item, ix) in items.iter_mut().zip(visible_range) { for (item, ix) in items.iter_mut().zip(visible_range) {
let item_origin = padded_bounds.origin let item_origin = padded_bounds.origin
@ -242,7 +233,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
AvailableSpace::Definite(padded_bounds.size.width), AvailableSpace::Definite(padded_bounds.size.width),
AvailableSpace::Definite(item_height), AvailableSpace::Definite(item_height),
); );
item.draw(item_origin, available_space, view_state, cx); item.draw(item_origin, available_space, cx);
} }
}); });
} }
@ -253,24 +244,19 @@ impl<V: 'static> Element<V> for UniformList<V> {
} }
} }
impl<V> UniformList<V> { impl UniformList {
pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self { pub fn with_width_from_item(mut self, item_index: Option<usize>) -> Self {
self.item_to_measure_index = item_index.unwrap_or(0); self.item_to_measure_index = item_index.unwrap_or(0);
self self
} }
fn measure_item( fn measure_item(&self, list_width: Option<Pixels>, cx: &mut WindowContext) -> Size<Pixels> {
&self,
view_state: &mut V,
list_width: Option<Pixels>,
cx: &mut ViewContext<V>,
) -> Size<Pixels> {
if self.item_count == 0 { if self.item_count == 0 {
return Size::default(); return Size::default();
} }
let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1); let item_ix = cmp::min(self.item_to_measure_index, self.item_count - 1);
let mut items = (self.render_items)(view_state, item_ix..item_ix + 1, cx); let mut items = (self.render_items)(item_ix..item_ix + 1, cx);
let mut item_to_measure = items.pop().unwrap(); let mut item_to_measure = items.pop().unwrap();
let available_space = size( let available_space = size(
list_width.map_or(AvailableSpace::MinContent, |width| { list_width.map_or(AvailableSpace::MinContent, |width| {
@ -278,7 +264,7 @@ impl<V> UniformList<V> {
}), }),
AvailableSpace::MinContent, AvailableSpace::MinContent,
); );
item_to_measure.measure(available_space, view_state, cx) item_to_measure.measure(available_space, cx)
} }
pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self { pub fn track_scroll(mut self, handle: UniformListScrollHandle) -> Self {
@ -287,14 +273,14 @@ impl<V> UniformList<V> {
} }
} }
impl<V> InteractiveComponent<V> for UniformList<V> { impl InteractiveComponent for UniformList {
fn interactivity(&mut self) -> &mut crate::Interactivity<V> { fn interactivity(&mut self) -> &mut crate::Interactivity {
&mut self.interactivity &mut self.interactivity
} }
} }
impl<V: 'static> Component<V> for UniformList<V> { impl Component for UniformList {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }

View file

@ -196,6 +196,30 @@ where
} }
} }
pub struct CallbackHandle<E> {
callback: Box<dyn Fn(&E, &mut WindowContext) + 'static>,
}
impl<E, F: Fn(&E, &mut WindowContext) + 'static> From<F> for CallbackHandle<E> {
fn from(value: F) -> Self {
CallbackHandle {
callback: Box::new(value),
}
}
}
pub struct ConstructorHandle<R> {
callback: Box<dyn Fn(&mut WindowContext) -> R + 'static>,
}
impl<R, F: Fn(&mut WindowContext) -> R + 'static> From<F> for ConstructorHandle<R> {
fn from(value: F) -> Self {
ConstructorHandle {
callback: Box::new(value),
}
}
}
pub trait Flatten<T> { pub trait Flatten<T> {
fn flatten(self) -> Result<T>; fn flatten(self) -> Result<T>;
} }

View file

@ -1,9 +1,8 @@
use crate::{ use crate::{
div, point, Component, Div, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render, div, point, Div, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
ViewContext,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf}; use std::{any::Any, fmt::Debug, ops::Deref, path::PathBuf};
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct KeyDownEvent { pub struct KeyDownEvent {
@ -60,32 +59,6 @@ pub struct ClickEvent {
pub up: MouseUpEvent, pub up: MouseUpEvent,
} }
pub struct Drag<S, R, V, E>
where
R: Fn(&mut V, &mut ViewContext<V>) -> E,
V: 'static,
E: Component<()>,
{
pub state: S,
pub render_drag_handle: R,
view_type: PhantomData<V>,
}
impl<S, R, V, E> Drag<S, R, V, E>
where
R: Fn(&mut V, &mut ViewContext<V>) -> E,
V: 'static,
E: Component<()>,
{
pub fn new(state: S, render_drag_handle: R) -> Self {
Drag {
state,
render_drag_handle,
view_type: PhantomData,
}
}
}
#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] #[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)]
pub enum MouseButton { pub enum MouseButton {
Left, Left,
@ -194,7 +167,7 @@ impl Deref for MouseExitEvent {
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>); pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
impl Render for ExternalPaths { impl Render for ExternalPaths {
type Element = Div<Self>; type Element = Div;
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
div() // Intentionally left empty because the platform will render icons for the dragged files div() // Intentionally left empty because the platform will render icons for the dragged files
@ -287,7 +260,7 @@ pub struct FocusEvent {
mod test { mod test {
use crate::{ use crate::{
self as gpui, div, Component, Div, FocusHandle, InteractiveComponent, KeyBinding, self as gpui, div, Component, Div, FocusHandle, InteractiveComponent, KeyBinding,
Keystroke, ParentComponent, Render, Stateful, TestAppContext, ViewContext, VisualContext, Keystroke, ParentComponent, Render, Stateful, TestAppContext, VisualContext,
}; };
struct TestView { struct TestView {
@ -299,20 +272,24 @@ mod test {
actions!(TestAction); actions!(TestAction);
impl Render for TestView { impl Render for TestView {
type Element = Stateful<Self, Div<Self>>; type Element = Stateful<Div>;
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
div().id("testview").child( div().id("testview").child(
div() div()
.key_context("parent") .key_context("parent")
.on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) .on_key_down(cx.callback(|this, _, _| this.saw_key_down = true))
.on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true) .on_action(
.child(|this: &mut Self, _cx: &mut ViewContext<Self>| { cx.callback(|this: &mut TestView, _: &TestAction, _| {
this.saw_action = true
}),
)
.child(
div() div()
.key_context("nested") .key_context("nested")
.track_focus(&this.focus_handle) .track_focus(&self.focus_handle)
.render() .render(),
}), ),
) )
} }
} }

View file

@ -2,7 +2,7 @@ use crate::{
black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask, black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font, Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font,
FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba,
SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext, SharedString, Size, SizeRefinement, Styled, TextRun, WindowContext,
}; };
use refineable::{Cascade, Refineable}; use refineable::{Cascade, Refineable};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -313,7 +313,7 @@ impl Style {
} }
/// Paints the background of an element styled with this style. /// Paints the background of an element styled with this style.
pub fn paint<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) { pub fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
let rem_size = cx.rem_size(); let rem_size = cx.rem_size();
cx.with_z_index(0, |cx| { cx.with_z_index(0, |cx| {

View file

@ -11,7 +11,7 @@ use std::{
}; };
pub trait Render: 'static + Sized { pub trait Render: 'static + Sized {
type Element: Element<Self> + 'static; type Element: Element + 'static;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element; fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element;
} }
@ -67,7 +67,7 @@ impl<V: 'static> View<V> {
pub fn render_with<C>(&self, component: C) -> RenderViewWith<C, V> pub fn render_with<C>(&self, component: C) -> RenderViewWith<C, V>
where where
C: 'static + Component<V>, C: 'static + Component,
{ {
RenderViewWith { RenderViewWith {
view: self.clone(), view: self.clone(),
@ -105,8 +105,8 @@ impl<V> PartialEq for View<V> {
impl<V> Eq for View<V> {} impl<V> Eq for View<V> {}
impl<V: Render, ParentViewState: 'static> Component<ParentViewState> for View<V> { impl<V: Render> Component for View<V> {
fn render(self) -> AnyElement<ParentViewState> { fn render(self) -> AnyElement {
AnyElement::new(AnyView::from(self)) AnyElement::new(AnyView::from(self))
} }
} }
@ -211,8 +211,8 @@ impl AnyView {
} }
} }
impl<V: 'static> Component<V> for AnyView { impl Component for AnyView {
fn render(self) -> AnyElement<V> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
@ -227,7 +227,7 @@ impl<V: Render> From<View<V>> for AnyView {
} }
} }
impl<ParentViewState: 'static> Element<ParentViewState> for AnyView { impl Element for AnyView {
type ElementState = Box<dyn Any>; type ElementState = Box<dyn Any>;
fn element_id(&self) -> Option<ElementId> { fn element_id(&self) -> Option<ElementId> {
@ -236,9 +236,8 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
fn layout( fn layout(
&mut self, &mut self,
_view_state: &mut ParentViewState,
_element_state: Option<Self::ElementState>, _element_state: Option<Self::ElementState>,
cx: &mut ViewContext<ParentViewState>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
(self.layout)(self, cx) (self.layout)(self, cx)
} }
@ -246,9 +245,8 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
fn paint( fn paint(
&mut self, &mut self,
_bounds: Bounds<Pixels>, _bounds: Bounds<Pixels>,
_view_state: &mut ParentViewState,
rendered_element: &mut Self::ElementState, rendered_element: &mut Self::ElementState,
cx: &mut ViewContext<ParentViewState>, cx: &mut WindowContext,
) { ) {
(self.paint)(self, rendered_element, cx) (self.paint)(self, rendered_element, cx)
} }
@ -281,41 +279,39 @@ impl<V: Render> From<WeakView<V>> for AnyWeakView {
} }
} }
// impl<T, E> Render for T impl<T, E> Render for T
// where where
// T: 'static + FnMut(&mut WindowContext) -> E, T: 'static + FnMut(&mut WindowContext) -> E,
// E: 'static + Send + Element<T>, E: 'static + Send + Element,
// { {
// type Element = E; type Element = E;
// fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
// (self)(cx) (self)(cx)
// } }
// } }
pub struct RenderViewWith<C, V> { pub struct RenderViewWith<C, V> {
view: View<V>, view: View<V>,
component: Option<C>, component: Option<C>,
} }
impl<C, ParentViewState, ViewState> Component<ParentViewState> for RenderViewWith<C, ViewState> impl<C, V> Component for RenderViewWith<C, V>
where where
C: 'static + Component<ViewState>, V: 'static + Render,
ParentViewState: 'static, C: 'static + Component,
ViewState: 'static,
{ {
fn render(self) -> AnyElement<ParentViewState> { fn render(self) -> AnyElement {
AnyElement::new(self) AnyElement::new(self)
} }
} }
impl<C, ParentViewState, ViewState> Element<ParentViewState> for RenderViewWith<C, ViewState> impl<C, V> Element for RenderViewWith<C, V>
where where
C: 'static + Component<ViewState>, V: 'static + Render,
ParentViewState: 'static, C: 'static + Component,
ViewState: 'static,
{ {
type ElementState = AnyElement<ViewState>; type ElementState = AnyElement;
fn element_id(&self) -> Option<ElementId> { fn element_id(&self) -> Option<ElementId> {
Some(self.view.entity_id().into()) Some(self.view.entity_id().into())
@ -323,25 +319,21 @@ where
fn layout( fn layout(
&mut self, &mut self,
_: &mut ParentViewState,
_: Option<Self::ElementState>, _: Option<Self::ElementState>,
cx: &mut ViewContext<ParentViewState>, cx: &mut WindowContext,
) -> (LayoutId, Self::ElementState) { ) -> (LayoutId, Self::ElementState) {
self.view.update(cx, |view, cx| {
let mut element = self.component.take().unwrap().render(); let mut element = self.component.take().unwrap().render();
let layout_id = element.layout(view, cx); let layout_id = element.layout(cx);
(layout_id, element) (layout_id, element)
})
} }
fn paint( fn paint(
&mut self, &mut self,
_: Bounds<Pixels>, _: Bounds<Pixels>,
_: &mut ParentViewState,
element: &mut Self::ElementState, element: &mut Self::ElementState,
cx: &mut ViewContext<ParentViewState>, cx: &mut WindowContext,
) { ) {
self.view.update(cx, |view, cx| element.paint(view, cx)) element.paint(cx)
} }
} }
@ -357,7 +349,7 @@ mod any_view {
let view = view.clone().downcast::<V>().unwrap(); let view = view.clone().downcast::<V>().unwrap();
view.update(cx, |view, cx| { view.update(cx, |view, cx| {
let mut element = AnyElement::new(view.render(cx)); let mut element = AnyElement::new(view.render(cx));
let layout_id = element.layout(view, cx); let layout_id = element.layout(cx);
(layout_id, Box::new(element) as Box<dyn Any>) (layout_id, Box::new(element) as Box<dyn Any>)
}) })
}) })
@ -369,9 +361,8 @@ mod any_view {
cx: &mut WindowContext, cx: &mut WindowContext,
) { ) {
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 element = element.downcast_mut::<AnyElement>().unwrap();
let element = element.downcast_mut::<AnyElement<V>>().unwrap(); element.paint(cx);
view.update(cx, |view, cx| element.paint(view, cx))
}) })
} }
} }

View file

@ -1,15 +1,15 @@
use crate::{ use crate::{
key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext,
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, CallbackHandle, ConstructorHandle,
DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges,
EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId,
ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model, GlobalElementId, GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyBinding, KeyContext,
ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent, KeyDownEvent, LayoutId, Model, ModelContext, Modifiers, MonochromeSprite, MouseButton,
MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay,
PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow,
Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, SharedString, Size, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline,
VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
}; };
use anyhow::{anyhow, Context as _, Result}; use anyhow::{anyhow, Context as _, Result};
use collections::HashMap; use collections::HashMap;
@ -1436,6 +1436,47 @@ impl<'a> WindowContext<'a> {
.dispatch_tree .dispatch_tree
.bindings_for_action(action) .bindings_for_action(action)
} }
///========== ELEMENT RELATED FUNCTIONS ===========
pub fn with_key_dispatch<R>(
&mut self,
context: KeyContext,
focus_handle: Option<FocusHandle>,
f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
) -> R {
let window = &mut self.window;
window
.current_frame
.dispatch_tree
.push_node(context.clone());
if let Some(focus_handle) = focus_handle.as_ref() {
window
.current_frame
.dispatch_tree
.make_focusable(focus_handle.id);
}
let result = f(focus_handle, self);
self.window.current_frame.dispatch_tree.pop_node();
result
}
/// Register a focus listener for the current frame only. It will be cleared
/// on the next frame render. You should use this method only from within elements,
/// and we may want to enforce that better via a different context type.
// todo!() Move this to `FrameContext` to emphasize its individuality?
pub fn on_focus_changed(
&mut self,
listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static,
) {
self.window
.current_frame
.focus_listeners
.push(Box::new(move |event, cx| {
listener(event, cx);
}));
}
} }
impl Context for WindowContext<'_> { impl Context for WindowContext<'_> {
@ -2124,49 +2165,6 @@ impl<'a, V: 'static> ViewContext<'a, V> {
) )
} }
/// Register a focus listener for the current frame only. It will be cleared
/// on the next frame render. You should use this method only from within elements,
/// and we may want to enforce that better via a different context type.
// todo!() Move this to `FrameContext` to emphasize its individuality?
pub fn on_focus_changed(
&mut self,
listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
) {
let handle = self.view().downgrade();
self.window
.current_frame
.focus_listeners
.push(Box::new(move |event, cx| {
handle
.update(cx, |view, cx| listener(view, event, cx))
.log_err();
}));
}
pub fn with_key_dispatch<R>(
&mut self,
context: KeyContext,
focus_handle: Option<FocusHandle>,
f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
) -> R {
let window = &mut self.window;
window
.current_frame
.dispatch_tree
.push_node(context.clone());
if let Some(focus_handle) = focus_handle.as_ref() {
window
.current_frame
.dispatch_tree
.make_focusable(focus_handle.id);
}
let result = f(focus_handle, self);
self.window.current_frame.dispatch_tree.pop_node();
result
}
pub fn spawn<Fut, R>( pub fn spawn<Fut, R>(
&mut self, &mut self,
f: impl FnOnce(WeakView<V>, AsyncWindowContext) -> Fut, f: impl FnOnce(WeakView<V>, AsyncWindowContext) -> Fut,
@ -2284,6 +2282,25 @@ impl<'a, V: 'static> ViewContext<'a, V> {
{ {
self.defer(|_, cx| cx.emit(Manager::Dismiss)) self.defer(|_, cx| cx.emit(Manager::Dismiss))
} }
pub fn callback<E>(
&self,
f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
) -> CallbackHandle<E> {
let view = self.view().clone();
(move |e: &E, cx: &mut WindowContext| {
view.update(cx, |view, cx| f(view, e, cx));
})
.into()
}
pub fn constructor<R>(
&self,
f: impl Fn(&mut V, &mut ViewContext<V>) -> R + 'static,
) -> ConstructorHandle<R> {
let view = self.view().clone();
(move |cx: &mut WindowContext| view.update(cx, |view, cx| f(view, cx))).into()
}
} }
impl<V> Context for ViewContext<'_, V> { impl<V> Context for ViewContext<'_, V> {