Remove V parameter on elements
This commit is contained in:
parent
c0d85dc1dd
commit
88024ca7c9
13 changed files with 578 additions and 665 deletions
|
@ -631,7 +631,7 @@ impl AnyWindowHandle {
|
|||
pub struct EmptyView {}
|
||||
|
||||
impl Render for EmptyView {
|
||||
type Element = Div<Self>;
|
||||
type Element = Div;
|
||||
|
||||
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Element {
|
||||
div()
|
||||
|
|
|
@ -1,37 +1,34 @@
|
|||
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};
|
||||
pub(crate) use smallvec::SmallVec;
|
||||
use std::{any::Any, fmt::Debug, mem};
|
||||
|
||||
pub trait Element<V: 'static> {
|
||||
pub trait Element {
|
||||
type ElementState: 'static;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId>;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState);
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
);
|
||||
|
||||
fn draw<T, R>(
|
||||
self,
|
||||
origin: Point<Pixels>,
|
||||
available_space: Size<T>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
f: impl FnOnce(&Self::ElementState, &mut ViewContext<V>) -> R,
|
||||
cx: &mut WindowContext,
|
||||
f: impl FnOnce(&Self::ElementState, &mut WindowContext) -> R,
|
||||
) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -41,7 +38,7 @@ pub trait Element<V: 'static> {
|
|||
element: self,
|
||||
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 Some(frame_state) = frame_state.as_ref() {
|
||||
f(&frame_state, cx)
|
||||
|
@ -65,10 +62,10 @@ pub trait Element<V: 'static> {
|
|||
#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
|
||||
|
||||
pub trait ParentComponent<V: 'static> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
|
||||
pub trait ParentComponent {
|
||||
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
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -76,7 +73,7 @@ pub trait ParentComponent<V: 'static> {
|
|||
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
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -86,26 +83,24 @@ pub trait ParentComponent<V: 'static> {
|
|||
}
|
||||
}
|
||||
|
||||
trait ElementObject<V> {
|
||||
trait ElementObject {
|
||||
fn element_id(&self) -> Option<ElementId>;
|
||||
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 layout(&mut self, cx: &mut WindowContext) -> LayoutId;
|
||||
fn paint(&mut self, cx: &mut WindowContext);
|
||||
fn measure(
|
||||
&mut self,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> Size<Pixels>;
|
||||
fn draw(
|
||||
&mut self,
|
||||
origin: Point<Pixels>,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
);
|
||||
}
|
||||
|
||||
struct RenderedElement<V: 'static, E: Element<V>> {
|
||||
struct RenderedElement<E: Element> {
|
||||
element: E,
|
||||
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.
|
||||
/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
|
||||
/// improved usability.
|
||||
impl<V, E: Element<V>> RenderedElement<V, E> {
|
||||
impl<E: Element> RenderedElement<E> {
|
||||
fn new(element: E) -> Self {
|
||||
RenderedElement {
|
||||
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
|
||||
E: Element<V>,
|
||||
E: Element,
|
||||
E::ElementState: 'static,
|
||||
{
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
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) {
|
||||
ElementRenderPhase::Start => {
|
||||
if let Some(id) = self.element.element_id() {
|
||||
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)
|
||||
} 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))
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +171,7 @@ where
|
|||
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) {
|
||||
ElementRenderPhase::LayoutRequested {
|
||||
layout_id,
|
||||
|
@ -191,13 +186,12 @@ where
|
|||
if let Some(id) = self.element.element_id() {
|
||||
cx.with_element_state(id, |element_state, cx| {
|
||||
let mut element_state = element_state.unwrap();
|
||||
self.element
|
||||
.paint(bounds, view_state, &mut element_state, cx);
|
||||
self.element.paint(bounds, &mut element_state, cx);
|
||||
((), element_state)
|
||||
});
|
||||
} else {
|
||||
self.element
|
||||
.paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
|
||||
.paint(bounds, frame_state.as_mut().unwrap(), cx);
|
||||
}
|
||||
ElementRenderPhase::Painted { frame_state }
|
||||
}
|
||||
|
@ -209,11 +203,10 @@ where
|
|||
fn measure(
|
||||
&mut self,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> Size<Pixels> {
|
||||
if matches!(&self.phase, ElementRenderPhase::Start) {
|
||||
self.layout(view_state, cx);
|
||||
self.layout(cx);
|
||||
}
|
||||
|
||||
let layout_id = match &mut self.phase {
|
||||
|
@ -251,21 +244,19 @@ where
|
|||
&mut self,
|
||||
origin: Point<Pixels>,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
self.measure(available_space, view_state, cx);
|
||||
cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx))
|
||||
self.measure(available_space, 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
|
||||
where
|
||||
V: 'static,
|
||||
E: 'static + Element<V>,
|
||||
E: 'static + Element,
|
||||
E::ElementState: Any,
|
||||
{
|
||||
AnyElement(Box::new(RenderedElement::new(element)))
|
||||
|
@ -275,22 +266,21 @@ impl<V> AnyElement<V> {
|
|||
self.0.element_id()
|
||||
}
|
||||
|
||||
pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
|
||||
self.0.layout(view_state, cx)
|
||||
pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId {
|
||||
self.0.layout(cx)
|
||||
}
|
||||
|
||||
pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||
self.0.paint(view_state, cx)
|
||||
pub fn paint(&mut self, cx: &mut WindowContext) {
|
||||
self.0.paint(cx)
|
||||
}
|
||||
|
||||
/// Initializes this element and performs layout within the given available space to determine its size.
|
||||
pub fn measure(
|
||||
&mut self,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> 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.
|
||||
|
@ -298,20 +288,19 @@ impl<V> AnyElement<V> {
|
|||
&mut self,
|
||||
origin: Point<Pixels>,
|
||||
available_space: Size<AvailableSpace>,
|
||||
view_state: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
self.0.draw(origin, available_space, view_state, cx)
|
||||
self.0.draw(origin, available_space, cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Component<V> {
|
||||
fn render(self) -> AnyElement<V>;
|
||||
pub trait Component {
|
||||
fn render(self) -> AnyElement;
|
||||
|
||||
fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
|
||||
where
|
||||
Self: Sized,
|
||||
U: Component<V>,
|
||||
U: Component,
|
||||
{
|
||||
f(self)
|
||||
}
|
||||
|
@ -337,19 +326,18 @@ pub trait Component<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> Component<V> for AnyElement<V> {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for AnyElement {
|
||||
fn render(self) -> AnyElement {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, E, F> Element<V> for Option<F>
|
||||
impl<E, F> Element for Option<F>
|
||||
where
|
||||
V: 'static,
|
||||
E: 'static + Component<V>,
|
||||
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
|
||||
E: 'static + Component,
|
||||
F: FnOnce(&mut WindowContext) -> E + 'static,
|
||||
{
|
||||
type ElementState = AnyElement<V>;
|
||||
type ElementState = AnyElement;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
None
|
||||
|
@ -357,45 +345,41 @@ where
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut V,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
let render = self.take().unwrap();
|
||||
let mut rendered_element = (render)(view_state, cx).render();
|
||||
let layout_id = rendered_element.layout(view_state, cx);
|
||||
let mut rendered_element = (render)(cx).render();
|
||||
let layout_id = rendered_element.layout(cx);
|
||||
(layout_id, rendered_element)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
_bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
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
|
||||
V: 'static,
|
||||
E: 'static + Component<V>,
|
||||
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
|
||||
E: 'static + Component,
|
||||
F: FnOnce(&mut WindowContext) -> E + 'static,
|
||||
{
|
||||
fn render(self) -> AnyElement<V> {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V, E, F> Component<V> for F
|
||||
impl<E, F> Component for F
|
||||
where
|
||||
V: 'static,
|
||||
E: 'static + Component<V>,
|
||||
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
|
||||
E: 'static + Component,
|
||||
F: FnOnce(&mut WindowContext) -> E + 'static,
|
||||
{
|
||||
fn render(self) -> AnyElement<V> {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(Some(self))
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,18 +1,17 @@
|
|||
use crate::{
|
||||
AnyElement, BorrowWindow, Bounds, Component, Element, InteractiveComponent,
|
||||
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
|
||||
Styled, ViewContext,
|
||||
AnyElement, Bounds, Component, Element, InteractiveComponent, InteractiveElementState,
|
||||
Interactivity, LayoutId, Pixels, SharedString, StyleRefinement, Styled, WindowContext,
|
||||
};
|
||||
use futures::FutureExt;
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct Img<V: 'static> {
|
||||
interactivity: Interactivity<V>,
|
||||
pub struct Img {
|
||||
interactivity: Interactivity,
|
||||
uri: Option<SharedString>,
|
||||
grayscale: bool,
|
||||
}
|
||||
|
||||
pub fn img<V: 'static>() -> Img<V> {
|
||||
pub fn img() -> Img {
|
||||
Img {
|
||||
interactivity: Interactivity::default(),
|
||||
uri: None,
|
||||
|
@ -20,10 +19,7 @@ pub fn img<V: 'static>() -> Img<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> Img<V>
|
||||
where
|
||||
V: 'static,
|
||||
{
|
||||
impl Img {
|
||||
pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
|
||||
self.uri = Some(uri.into());
|
||||
self
|
||||
|
@ -35,13 +31,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> Component<V> for Img<V> {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for Img {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Element<V> for Img<V> {
|
||||
impl Element for Img {
|
||||
type ElementState = InteractiveElementState;
|
||||
|
||||
fn element_id(&self) -> Option<crate::ElementId> {
|
||||
|
@ -50,9 +46,8 @@ impl<V> Element<V> for Img<V> {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_view_state: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
self.interactivity.layout(element_state, cx, |style, cx| {
|
||||
cx.request_layout(&style, None)
|
||||
|
@ -62,9 +57,8 @@ impl<V> Element<V> for Img<V> {
|
|||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
self.interactivity.paint(
|
||||
bounds,
|
||||
|
@ -89,7 +83,7 @@ impl<V> Element<V> for Img<V> {
|
|||
.log_err()
|
||||
});
|
||||
} else {
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
cx.spawn(|mut cx| async move {
|
||||
if image_future.await.ok().is_some() {
|
||||
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 {
|
||||
&mut self.interactivity.base_style
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> InteractiveComponent<V> for Img<V> {
|
||||
fn interactivity(&mut self) -> &mut Interactivity<V> {
|
||||
impl InteractiveComponent for Img {
|
||||
fn interactivity(&mut self) -> &mut Interactivity {
|
||||
&mut self.interactivity
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,15 @@ use taffy::style::{Display, Position};
|
|||
|
||||
use crate::{
|
||||
point, AnyElement, BorrowWindow, Bounds, Component, Element, LayoutId, ParentComponent, Pixels,
|
||||
Point, Size, Style,
|
||||
Point, Size, Style, WindowContext,
|
||||
};
|
||||
|
||||
pub struct OverlayState {
|
||||
child_layout_ids: SmallVec<[LayoutId; 4]>,
|
||||
}
|
||||
|
||||
pub struct Overlay<V> {
|
||||
children: SmallVec<[AnyElement<V>; 2]>,
|
||||
pub struct Overlay {
|
||||
children: SmallVec<[AnyElement; 2]>,
|
||||
anchor_corner: AnchorCorner,
|
||||
fit_mode: OverlayFitMode,
|
||||
// todo!();
|
||||
|
@ -21,7 +21,7 @@ pub struct Overlay<V> {
|
|||
|
||||
/// overlay gives you a floating element that will avoid overflowing the window bounds.
|
||||
/// Its children should have no margin to avoid measurement issues.
|
||||
pub fn overlay<V: 'static>() -> Overlay<V> {
|
||||
pub fn overlay() -> Overlay {
|
||||
Overlay {
|
||||
children: SmallVec::new(),
|
||||
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.
|
||||
pub fn anchor(mut self, anchor: AnchorCorner) -> Self {
|
||||
self.anchor_corner = anchor;
|
||||
|
@ -51,19 +51,19 @@ impl<V> Overlay<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> ParentComponent<V> for Overlay<V> {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||
impl ParentComponent for Overlay {
|
||||
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
|
||||
&mut self.children
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for Overlay<V> {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for Overlay {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Element<V> for Overlay<V> {
|
||||
impl Element for Overlay {
|
||||
type ElementState = OverlayState;
|
||||
|
||||
fn element_id(&self) -> Option<crate::ElementId> {
|
||||
|
@ -72,14 +72,13 @@ impl<V: 'static> Element<V> for Overlay<V> {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut V,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut crate::ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (crate::LayoutId, Self::ElementState) {
|
||||
let child_layout_ids = self
|
||||
.children
|
||||
.iter_mut()
|
||||
.map(|child| child.layout(view_state, cx))
|
||||
.map(|child| child.layout(cx))
|
||||
.collect::<SmallVec<_>>();
|
||||
|
||||
let mut overlay_style = Style::default();
|
||||
|
@ -94,9 +93,8 @@ impl<V: 'static> Element<V> for Overlay<V> {
|
|||
fn paint(
|
||||
&mut self,
|
||||
bounds: crate::Bounds<crate::Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut crate::ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
if element_state.child_layout_ids.is_empty() {
|
||||
return;
|
||||
|
@ -157,7 +155,7 @@ impl<V: 'static> Element<V> for Overlay<V> {
|
|||
|
||||
cx.with_element_offset(desired.origin - bounds.origin, |cx| {
|
||||
for child in &mut self.children {
|
||||
child.paint(view_state, cx);
|
||||
child.paint(cx);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
use crate::{
|
||||
AnyElement, Bounds, Component, Element, ElementId, InteractiveComponent,
|
||||
InteractiveElementState, Interactivity, LayoutId, Pixels, SharedString, StyleRefinement,
|
||||
Styled, ViewContext,
|
||||
Styled, WindowContext,
|
||||
};
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct Svg<V: 'static> {
|
||||
interactivity: Interactivity<V>,
|
||||
pub struct Svg {
|
||||
interactivity: Interactivity,
|
||||
path: Option<SharedString>,
|
||||
}
|
||||
|
||||
pub fn svg<V: 'static>() -> Svg<V> {
|
||||
pub fn svg() -> Svg {
|
||||
Svg {
|
||||
interactivity: Interactivity::default(),
|
||||
path: None,
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Svg<V> {
|
||||
impl Svg {
|
||||
pub fn path(mut self, path: impl Into<SharedString>) -> Self {
|
||||
self.path = Some(path.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Component<V> for Svg<V> {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for Svg {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Element<V> for Svg<V> {
|
||||
impl Element for Svg {
|
||||
type ElementState = InteractiveElementState;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
|
@ -39,9 +39,8 @@ impl<V> Element<V> for Svg<V> {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_view_state: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
self.interactivity.layout(element_state, cx, |style, cx| {
|
||||
cx.request_layout(&style, None)
|
||||
|
@ -51,9 +50,8 @@ impl<V> Element<V> for Svg<V> {
|
|||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) where
|
||||
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 {
|
||||
&mut self.interactivity.base_style
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> InteractiveComponent<V> for Svg<V> {
|
||||
fn interactivity(&mut self) -> &mut Interactivity<V> {
|
||||
impl InteractiveComponent for Svg {
|
||||
fn interactivity(&mut self) -> &mut Interactivity {
|
||||
&mut self.interactivity
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
AnyElement, BorrowWindow, Bounds, Component, Element, ElementId, LayoutId, Pixels,
|
||||
SharedString, Size, TextRun, ViewContext, WrappedLine,
|
||||
AnyElement, Bounds, Component, Element, ElementId, LayoutId, Pixels, SharedString, Size,
|
||||
TextRun, WindowContext, WrappedLine,
|
||||
};
|
||||
use parking_lot::{Mutex, MutexGuard};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -26,13 +26,13 @@ impl Text {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for Text {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for Text {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Element<V> for Text {
|
||||
impl Element for Text {
|
||||
type ElementState = TextState;
|
||||
|
||||
fn element_id(&self) -> Option<crate::ElementId> {
|
||||
|
@ -41,9 +41,8 @@ impl<V: 'static> Element<V> for Text {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_view: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
let element_state = element_state.unwrap_or_default();
|
||||
let text_system = cx.text_system().clone();
|
||||
|
@ -120,9 +119,8 @@ impl<V: 'static> Element<V> for Text {
|
|||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
_: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
let element_state = element_state.lock();
|
||||
let element_state = element_state
|
||||
|
@ -165,7 +163,7 @@ struct InteractiveTextState {
|
|||
clicked_range_ixs: Rc<Cell<SmallVec<[usize; 1]>>>,
|
||||
}
|
||||
|
||||
impl<V: 'static> Element<V> for InteractiveText {
|
||||
impl Element for InteractiveText {
|
||||
type ElementState = InteractiveTextState;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
|
@ -174,23 +172,22 @@ impl<V: 'static> Element<V> for InteractiveText {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
if let Some(InteractiveTextState {
|
||||
text_state,
|
||||
clicked_range_ixs,
|
||||
}) = 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 {
|
||||
text_state,
|
||||
clicked_range_ixs,
|
||||
};
|
||||
(layout_id, element_state)
|
||||
} 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 {
|
||||
text_state,
|
||||
clicked_range_ixs: Rc::default(),
|
||||
|
@ -202,17 +199,15 @@ impl<V: 'static> Element<V> for InteractiveText {
|
|||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
self.text
|
||||
.paint(bounds, view_state, &mut element_state.text_state, cx)
|
||||
self.text.paint(bounds, &mut element_state.text_state, cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for SharedString {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for SharedString {
|
||||
fn render(self) -> AnyElement {
|
||||
Text {
|
||||
text: self,
|
||||
runs: None,
|
||||
|
@ -221,8 +216,8 @@ impl<V: 'static> Component<V> for SharedString {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for &'static str {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for &'static str {
|
||||
fn render(self) -> AnyElement {
|
||||
Text {
|
||||
text: self.into(),
|
||||
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.
|
||||
// This impl doesn't exist in the `gpui2` crate.
|
||||
impl<V: 'static> Component<V> for String {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for String {
|
||||
fn render(self) -> AnyElement {
|
||||
Text {
|
||||
text: self.into(),
|
||||
runs: None,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
point, px, size, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, Element,
|
||||
ElementId, InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels,
|
||||
Point, Size, StyleRefinement, Styled, ViewContext,
|
||||
point, px, size, AnyElement, AvailableSpace, Bounds, Component, Element, ElementId,
|
||||
InteractiveComponent, InteractiveElementState, Interactivity, LayoutId, Pixels, Point, Size,
|
||||
StyleRefinement, Styled, WindowContext,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
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.
|
||||
/// 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.
|
||||
pub fn uniform_list<I, V, C>(
|
||||
pub fn uniform_list<I, C>(
|
||||
id: I,
|
||||
item_count: usize,
|
||||
f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> Vec<C>,
|
||||
) -> UniformList<V>
|
||||
f: impl 'static + Fn(Range<usize>, &mut WindowContext) -> Vec<C>,
|
||||
) -> UniformList
|
||||
where
|
||||
I: Into<ElementId>,
|
||||
V: 'static,
|
||||
C: Component<V>,
|
||||
C: Component,
|
||||
{
|
||||
let id = id.into();
|
||||
let mut style = StyleRefinement::default();
|
||||
|
@ -29,8 +28,8 @@ where
|
|||
style,
|
||||
item_count,
|
||||
item_to_measure_index: 0,
|
||||
render_items: Box::new(move |view, visible_range, cx| {
|
||||
f(view, visible_range, cx)
|
||||
render_items: Box::new(move |visible_range, cx| {
|
||||
f(visible_range, cx)
|
||||
.into_iter()
|
||||
.map(|component| component.render())
|
||||
.collect()
|
||||
|
@ -43,19 +42,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct UniformList<V: 'static> {
|
||||
pub struct UniformList {
|
||||
id: ElementId,
|
||||
style: StyleRefinement,
|
||||
item_count: usize,
|
||||
item_to_measure_index: usize,
|
||||
render_items: Box<
|
||||
dyn for<'a> Fn(
|
||||
&'a mut V,
|
||||
Range<usize>,
|
||||
&'a mut ViewContext<V>,
|
||||
) -> SmallVec<[AnyElement<V>; 64]>,
|
||||
>,
|
||||
interactivity: Interactivity<V>,
|
||||
render_items:
|
||||
Box<dyn for<'a> Fn(Range<usize>, &'a mut WindowContext) -> SmallVec<[AnyElement; 64]>>,
|
||||
interactivity: Interactivity,
|
||||
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 {
|
||||
&mut self.style
|
||||
}
|
||||
|
@ -101,7 +95,7 @@ pub struct UniformListState {
|
|||
item_size: Size<Pixels>,
|
||||
}
|
||||
|
||||
impl<V: 'static> Element<V> for UniformList<V> {
|
||||
impl Element for UniformList {
|
||||
type ElementState = UniformListState;
|
||||
|
||||
fn element_id(&self) -> Option<crate::ElementId> {
|
||||
|
@ -110,16 +104,15 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut V,
|
||||
element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
let max_items = self.item_count;
|
||||
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));
|
||||
.unwrap_or_else(|| self.measure_item(None, cx));
|
||||
|
||||
let (layout_id, interactive) =
|
||||
self.interactivity
|
||||
|
@ -161,9 +154,8 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
|||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<crate::Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
let style =
|
||||
self.interactivity
|
||||
|
@ -209,9 +201,8 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
|||
style.paint(bounds, cx);
|
||||
|
||||
if self.item_count > 0 {
|
||||
let item_height = self
|
||||
.measure_item(view_state, Some(padded_bounds.size.width), cx)
|
||||
.height;
|
||||
let item_height =
|
||||
self.measure_item(Some(padded_bounds.size.width), cx).height;
|
||||
if let Some(scroll_handle) = self.scroll_handle.clone() {
|
||||
scroll_handle.0.borrow_mut().replace(ScrollHandleState {
|
||||
item_height,
|
||||
|
@ -233,7 +224,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
|||
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| {
|
||||
for (item, ix) in items.iter_mut().zip(visible_range) {
|
||||
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(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 {
|
||||
self.item_to_measure_index = item_index.unwrap_or(0);
|
||||
self
|
||||
}
|
||||
|
||||
fn measure_item(
|
||||
&self,
|
||||
view_state: &mut V,
|
||||
list_width: Option<Pixels>,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Size<Pixels> {
|
||||
fn measure_item(&self, list_width: Option<Pixels>, cx: &mut WindowContext) -> Size<Pixels> {
|
||||
if self.item_count == 0 {
|
||||
return Size::default();
|
||||
}
|
||||
|
||||
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 available_space = size(
|
||||
list_width.map_or(AvailableSpace::MinContent, |width| {
|
||||
|
@ -278,7 +264,7 @@ impl<V> UniformList<V> {
|
|||
}),
|
||||
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 {
|
||||
|
@ -287,14 +273,14 @@ impl<V> UniformList<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V> InteractiveComponent<V> for UniformList<V> {
|
||||
fn interactivity(&mut self) -> &mut crate::Interactivity<V> {
|
||||
impl InteractiveComponent for UniformList {
|
||||
fn interactivity(&mut self) -> &mut crate::Interactivity {
|
||||
&mut self.interactivity
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for UniformList<V> {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for UniformList {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
fn flatten(self) -> Result<T>;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use crate::{
|
||||
div, point, Component, Div, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render,
|
||||
ViewContext,
|
||||
div, point, Div, FocusHandle, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
|
||||
};
|
||||
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)]
|
||||
pub struct KeyDownEvent {
|
||||
|
@ -60,32 +59,6 @@ pub struct ClickEvent {
|
|||
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)]
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
|
@ -194,7 +167,7 @@ impl Deref for MouseExitEvent {
|
|||
pub struct ExternalPaths(pub(crate) SmallVec<[PathBuf; 2]>);
|
||||
|
||||
impl Render for ExternalPaths {
|
||||
type Element = Div<Self>;
|
||||
type Element = Div;
|
||||
|
||||
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
|
||||
div() // Intentionally left empty because the platform will render icons for the dragged files
|
||||
|
@ -287,7 +260,7 @@ pub struct FocusEvent {
|
|||
mod test {
|
||||
use crate::{
|
||||
self as gpui, div, Component, Div, FocusHandle, InteractiveComponent, KeyBinding,
|
||||
Keystroke, ParentComponent, Render, Stateful, TestAppContext, ViewContext, VisualContext,
|
||||
Keystroke, ParentComponent, Render, Stateful, TestAppContext, VisualContext,
|
||||
};
|
||||
|
||||
struct TestView {
|
||||
|
@ -299,20 +272,24 @@ mod test {
|
|||
actions!(TestAction);
|
||||
|
||||
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()
|
||||
.key_context("parent")
|
||||
.on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true)
|
||||
.on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true)
|
||||
.child(|this: &mut Self, _cx: &mut ViewContext<Self>| {
|
||||
.on_key_down(cx.callback(|this, _, _| this.saw_key_down = true))
|
||||
.on_action(
|
||||
cx.callback(|this: &mut TestView, _: &TestAction, _| {
|
||||
this.saw_action = true
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.key_context("nested")
|
||||
.track_focus(&this.focus_handle)
|
||||
.render()
|
||||
}),
|
||||
.track_focus(&self.focus_handle)
|
||||
.render(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
|
||||
Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font,
|
||||
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 smallvec::SmallVec;
|
||||
|
@ -313,7 +313,7 @@ impl 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();
|
||||
|
||||
cx.with_z_index(0, |cx| {
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::{
|
|||
};
|
||||
|
||||
pub trait Render: 'static + Sized {
|
||||
type Element: Element<Self> + 'static;
|
||||
type Element: Element + 'static;
|
||||
|
||||
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>
|
||||
where
|
||||
C: 'static + Component<V>,
|
||||
C: 'static + Component,
|
||||
{
|
||||
RenderViewWith {
|
||||
view: self.clone(),
|
||||
|
@ -105,8 +105,8 @@ impl<V> PartialEq for View<V> {
|
|||
|
||||
impl<V> Eq for View<V> {}
|
||||
|
||||
impl<V: Render, ParentViewState: 'static> Component<ParentViewState> for View<V> {
|
||||
fn render(self) -> AnyElement<ParentViewState> {
|
||||
impl<V: Render> Component for View<V> {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(AnyView::from(self))
|
||||
}
|
||||
}
|
||||
|
@ -211,8 +211,8 @@ impl AnyView {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: 'static> Component<V> for AnyView {
|
||||
fn render(self) -> AnyElement<V> {
|
||||
impl Component for AnyView {
|
||||
fn render(self) -> AnyElement {
|
||||
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>;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
|
@ -236,9 +236,8 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_view_state: &mut ParentViewState,
|
||||
_element_state: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<ParentViewState>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
(self.layout)(self, cx)
|
||||
}
|
||||
|
@ -246,9 +245,8 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
|||
fn paint(
|
||||
&mut self,
|
||||
_bounds: Bounds<Pixels>,
|
||||
_view_state: &mut ParentViewState,
|
||||
rendered_element: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<ParentViewState>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
(self.paint)(self, rendered_element, cx)
|
||||
}
|
||||
|
@ -281,41 +279,39 @@ impl<V: Render> From<WeakView<V>> for AnyWeakView {
|
|||
}
|
||||
}
|
||||
|
||||
// impl<T, E> Render for T
|
||||
// where
|
||||
// T: 'static + FnMut(&mut WindowContext) -> E,
|
||||
// E: 'static + Send + Element<T>,
|
||||
// {
|
||||
// type Element = E;
|
||||
impl<T, E> Render for T
|
||||
where
|
||||
T: 'static + FnMut(&mut WindowContext) -> E,
|
||||
E: 'static + Send + Element,
|
||||
{
|
||||
type Element = E;
|
||||
|
||||
// fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
// (self)(cx)
|
||||
// }
|
||||
// }
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
(self)(cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RenderViewWith<C, V> {
|
||||
view: View<V>,
|
||||
component: Option<C>,
|
||||
}
|
||||
|
||||
impl<C, ParentViewState, ViewState> Component<ParentViewState> for RenderViewWith<C, ViewState>
|
||||
impl<C, V> Component for RenderViewWith<C, V>
|
||||
where
|
||||
C: 'static + Component<ViewState>,
|
||||
ParentViewState: 'static,
|
||||
ViewState: 'static,
|
||||
V: 'static + Render,
|
||||
C: 'static + Component,
|
||||
{
|
||||
fn render(self) -> AnyElement<ParentViewState> {
|
||||
fn render(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, ParentViewState, ViewState> Element<ParentViewState> for RenderViewWith<C, ViewState>
|
||||
impl<C, V> Element for RenderViewWith<C, V>
|
||||
where
|
||||
C: 'static + Component<ViewState>,
|
||||
ParentViewState: 'static,
|
||||
ViewState: 'static,
|
||||
V: 'static + Render,
|
||||
C: 'static + Component,
|
||||
{
|
||||
type ElementState = AnyElement<ViewState>;
|
||||
type ElementState = AnyElement;
|
||||
|
||||
fn element_id(&self) -> Option<ElementId> {
|
||||
Some(self.view.entity_id().into())
|
||||
|
@ -323,25 +319,21 @@ where
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
_: &mut ParentViewState,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut ViewContext<ParentViewState>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::ElementState) {
|
||||
self.view.update(cx, |view, cx| {
|
||||
let mut element = self.component.take().unwrap().render();
|
||||
let layout_id = element.layout(view, cx);
|
||||
let layout_id = element.layout(cx);
|
||||
(layout_id, element)
|
||||
})
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
_: Bounds<Pixels>,
|
||||
_: &mut ParentViewState,
|
||||
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();
|
||||
view.update(cx, |view, 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>)
|
||||
})
|
||||
})
|
||||
|
@ -369,9 +361,8 @@ mod any_view {
|
|||
cx: &mut WindowContext,
|
||||
) {
|
||||
cx.with_element_id(Some(view.model.entity_id), |cx| {
|
||||
let view = view.clone().downcast::<V>().unwrap();
|
||||
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
||||
view.update(cx, |view, cx| element.paint(view, cx))
|
||||
let element = element.downcast_mut::<AnyElement>().unwrap();
|
||||
element.paint(cx);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use crate::{
|
||||
key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext,
|
||||
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
|
||||
DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
|
||||
EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla,
|
||||
ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model,
|
||||
ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent,
|
||||
MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler,
|
||||
PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams,
|
||||
RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
|
||||
Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View,
|
||||
VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
|
||||
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, CallbackHandle, ConstructorHandle,
|
||||
Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges,
|
||||
Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId,
|
||||
GlobalElementId, GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyBinding, KeyContext,
|
||||
KeyDownEvent, LayoutId, Model, ModelContext, Modifiers, MonochromeSprite, MouseButton,
|
||||
MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay,
|
||||
PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
|
||||
RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow,
|
||||
SharedString, Size, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline,
|
||||
UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use collections::HashMap;
|
||||
|
@ -1436,6 +1436,47 @@ impl<'a> WindowContext<'a> {
|
|||
.dispatch_tree
|
||||
.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<'_> {
|
||||
|
@ -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>(
|
||||
&mut self,
|
||||
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))
|
||||
}
|
||||
|
||||
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> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue