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 {}
|
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()
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(),
|
||||||
}),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue