WIP: Everything shredded
This commit is contained in:
parent
7536645eea
commit
6638407ff9
26 changed files with 1136 additions and 1354 deletions
|
@ -32,42 +32,52 @@ use crate::{
|
|||
rect::RectF,
|
||||
vector::{vec2f, Vector2F},
|
||||
},
|
||||
json, Action, DebugContext, EventContext, LayoutContext, PaintContext, RenderContext,
|
||||
SizeConstraint, View,
|
||||
json, Action, RenderContext, SceneBuilder, SizeConstraint, View, ViewContext,
|
||||
};
|
||||
use core::panic;
|
||||
use json::ToJson;
|
||||
use std::{
|
||||
any::Any,
|
||||
borrow::Cow,
|
||||
cell::RefCell,
|
||||
mem,
|
||||
ops::{Deref, DerefMut, Range},
|
||||
rc::Rc,
|
||||
};
|
||||
use std::{any::Any, borrow::Cow, cell::RefCell, marker::PhantomData, mem, ops::Range};
|
||||
|
||||
trait AnyElement<V: View> {
|
||||
fn layout(
|
||||
&mut self,
|
||||
view: &mut V,
|
||||
constraint: SizeConstraint,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Vector2F;
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
view: &mut V,
|
||||
scene: &mut SceneBuilder,
|
||||
origin: Vector2F,
|
||||
visible_bounds: RectF,
|
||||
cx: &mut ViewContext<V>,
|
||||
);
|
||||
|
||||
trait AnyElement {
|
||||
fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F;
|
||||
fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext);
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
view: &V,
|
||||
range_utf16: Range<usize>,
|
||||
cx: &MeasurementContext,
|
||||
cx: &ViewContext<V>,
|
||||
) -> Option<RectF>;
|
||||
fn debug(&self, cx: &DebugContext) -> serde_json::Value;
|
||||
|
||||
fn debug(&self, view: &V, cx: &mut ViewContext<V>) -> serde_json::Value;
|
||||
|
||||
fn size(&self) -> Vector2F;
|
||||
|
||||
fn metadata(&self) -> Option<&dyn Any>;
|
||||
}
|
||||
|
||||
pub trait Element {
|
||||
pub trait Element<V: View> {
|
||||
type LayoutState;
|
||||
type PaintState;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
cx: &mut LayoutContext,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState);
|
||||
|
||||
fn paint(
|
||||
|
@ -75,7 +85,8 @@ pub trait Element {
|
|||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
cx: &mut PaintContext,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState;
|
||||
|
||||
fn rect_for_text_range(
|
||||
|
@ -85,7 +96,8 @@ pub trait Element {
|
|||
visible_bounds: RectF,
|
||||
layout: &Self::LayoutState,
|
||||
paint: &Self::PaintState,
|
||||
cx: &MeasurementContext,
|
||||
view: &V,
|
||||
cx: &ViewContext<V>,
|
||||
) -> Option<RectF>;
|
||||
|
||||
fn metadata(&self) -> Option<&dyn Any> {
|
||||
|
@ -97,27 +109,28 @@ pub trait Element {
|
|||
bounds: RectF,
|
||||
layout: &Self::LayoutState,
|
||||
paint: &Self::PaintState,
|
||||
cx: &DebugContext,
|
||||
view: &V,
|
||||
cx: &ViewContext<V>,
|
||||
) -> serde_json::Value;
|
||||
|
||||
fn boxed(self) -> ElementBox
|
||||
fn boxed(self) -> ElementBox<V>
|
||||
where
|
||||
Self: 'static + Sized,
|
||||
{
|
||||
ElementBox(ElementRc {
|
||||
ElementBox {
|
||||
element: RefCell::new(Lifecycle::Init { element: self }),
|
||||
name: None,
|
||||
element: Rc::new(RefCell::new(Lifecycle::Init { element: self })),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn named(self, name: impl Into<Cow<'static, str>>) -> ElementBox
|
||||
fn named(self, name: impl Into<Cow<'static, str>>) -> ElementBox<V>
|
||||
where
|
||||
Self: 'static + Sized,
|
||||
{
|
||||
ElementBox(ElementRc {
|
||||
ElementBox {
|
||||
element: RefCell::new(Lifecycle::Init { element: self }),
|
||||
name: Some(name.into()),
|
||||
element: Rc::new(RefCell::new(Lifecycle::Init { element: self })),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn constrained(self) -> ConstrainedBox
|
||||
|
@ -205,44 +218,41 @@ pub trait Element {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum Lifecycle<T: Element> {
|
||||
pub enum Lifecycle<V: View, E: Element<V>> {
|
||||
Empty,
|
||||
Init {
|
||||
element: T,
|
||||
element: E,
|
||||
},
|
||||
PostLayout {
|
||||
element: T,
|
||||
element: E,
|
||||
constraint: SizeConstraint,
|
||||
size: Vector2F,
|
||||
layout: T::LayoutState,
|
||||
layout: E::LayoutState,
|
||||
},
|
||||
PostPaint {
|
||||
element: T,
|
||||
element: E,
|
||||
constraint: SizeConstraint,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
layout: T::LayoutState,
|
||||
paint: T::PaintState,
|
||||
layout: E::LayoutState,
|
||||
paint: E::PaintState,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct ElementBox(ElementRc);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ElementRc {
|
||||
name: Option<Cow<'static, str>>,
|
||||
element: Rc<RefCell<dyn AnyElement>>,
|
||||
}
|
||||
|
||||
impl<T: Element> AnyElement for Lifecycle<T> {
|
||||
fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
|
||||
impl<V: View, E: Element<V>> AnyElement<V> for Lifecycle<V, E> {
|
||||
fn layout(
|
||||
&mut self,
|
||||
view: &mut V,
|
||||
constraint: SizeConstraint,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Vector2F {
|
||||
let result;
|
||||
*self = match mem::take(self) {
|
||||
Lifecycle::Empty => unreachable!(),
|
||||
Lifecycle::Init { mut element }
|
||||
| Lifecycle::PostLayout { mut element, .. }
|
||||
| Lifecycle::PostPaint { mut element, .. } => {
|
||||
let (size, layout) = element.layout(constraint, cx);
|
||||
let (size, layout) = element.layout(view, constraint, cx);
|
||||
debug_assert!(size.x().is_finite());
|
||||
debug_assert!(size.y().is_finite());
|
||||
|
||||
|
@ -258,7 +268,13 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
result
|
||||
}
|
||||
|
||||
fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
|
||||
fn paint(
|
||||
&mut self,
|
||||
view: &mut V,
|
||||
origin: Vector2F,
|
||||
visible_bounds: RectF,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
*self = match mem::take(self) {
|
||||
Lifecycle::PostLayout {
|
||||
mut element,
|
||||
|
@ -267,7 +283,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
mut layout,
|
||||
} => {
|
||||
let bounds = RectF::new(origin, size);
|
||||
let paint = element.paint(bounds, visible_bounds, &mut layout, cx);
|
||||
let paint = element.paint(view, bounds, visible_bounds, &mut layout, cx);
|
||||
Lifecycle::PostPaint {
|
||||
element,
|
||||
constraint,
|
||||
|
@ -285,7 +301,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
..
|
||||
} => {
|
||||
let bounds = RectF::new(origin, bounds.size());
|
||||
let paint = element.paint(bounds, visible_bounds, &mut layout, cx);
|
||||
let paint = element.paint(view, bounds, visible_bounds, &mut layout, cx);
|
||||
Lifecycle::PostPaint {
|
||||
element,
|
||||
constraint,
|
||||
|
@ -304,8 +320,9 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
view: &V,
|
||||
range_utf16: Range<usize>,
|
||||
cx: &MeasurementContext,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Option<RectF> {
|
||||
if let Lifecycle::PostPaint {
|
||||
element,
|
||||
|
@ -316,7 +333,15 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
..
|
||||
} = self
|
||||
{
|
||||
element.rect_for_text_range(range_utf16, *bounds, *visible_bounds, layout, paint, cx)
|
||||
element.rect_for_text_range(
|
||||
view,
|
||||
range_utf16,
|
||||
*bounds,
|
||||
*visible_bounds,
|
||||
layout,
|
||||
paint,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -339,7 +364,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn debug(&self, cx: &DebugContext) -> serde_json::Value {
|
||||
fn debug(&self, view: &V, cx: &ViewContext<V>) -> serde_json::Value {
|
||||
match self {
|
||||
Lifecycle::PostPaint {
|
||||
element,
|
||||
|
@ -349,7 +374,7 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
layout,
|
||||
paint,
|
||||
} => {
|
||||
let mut value = element.debug(*bounds, layout, paint, cx);
|
||||
let mut value = element.debug(view, *bounds, layout, paint, cx);
|
||||
if let json::Value::Object(map) = &mut value {
|
||||
let mut new_map: crate::json::Map<String, serde_json::Value> =
|
||||
Default::default();
|
||||
|
@ -371,72 +396,67 @@ impl<T: Element> AnyElement for Lifecycle<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Element> Default for Lifecycle<T> {
|
||||
impl<V: View, E: Element<V>> Default for Lifecycle<V, E> {
|
||||
fn default() -> Self {
|
||||
Self::Empty
|
||||
}
|
||||
}
|
||||
|
||||
impl ElementBox {
|
||||
pub struct ElementBox<V: View> {
|
||||
element: RefCell<dyn AnyElement<V>>,
|
||||
view_type: PhantomData<V>,
|
||||
name: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
impl<V: View> ElementBox<V> {
|
||||
pub fn name(&self) -> Option<&str> {
|
||||
self.0.name.as_deref()
|
||||
}
|
||||
|
||||
pub fn metadata<T: 'static>(&self) -> Option<&T> {
|
||||
let element = unsafe { &*self.0.element.as_ptr() };
|
||||
element.metadata().and_then(|m| m.downcast_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ElementBox {
|
||||
fn clone(&self) -> Self {
|
||||
ElementBox(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ElementBox> for ElementRc {
|
||||
fn from(val: ElementBox) -> Self {
|
||||
val.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ElementBox {
|
||||
type Target = ElementRc;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ElementBox {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ElementRc {
|
||||
pub fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F {
|
||||
self.element.borrow_mut().layout(constraint, cx)
|
||||
// let element = unsafe { &*self.0.element.as_ptr() };
|
||||
// element.metadata().and_then(|m| m.downcast_ref())
|
||||
}
|
||||
|
||||
pub fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext) {
|
||||
self.element.borrow_mut().paint(origin, visible_bounds, cx);
|
||||
pub fn layout(
|
||||
&self,
|
||||
view: &mut V,
|
||||
constraint: SizeConstraint,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Vector2F {
|
||||
self.element.borrow_mut().layout(view, constraint, cx)
|
||||
}
|
||||
|
||||
pub fn paint(
|
||||
&self,
|
||||
view: &mut V,
|
||||
scene: &mut SceneBuilder,
|
||||
origin: Vector2F,
|
||||
visible_bounds: RectF,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
self.element
|
||||
.borrow_mut()
|
||||
.paint(view, scene, origin, visible_bounds, cx);
|
||||
}
|
||||
|
||||
pub fn rect_for_text_range(
|
||||
&self,
|
||||
view: &V,
|
||||
range_utf16: Range<usize>,
|
||||
cx: &MeasurementContext,
|
||||
cx: &ViewContext<V>,
|
||||
) -> Option<RectF> {
|
||||
self.element.borrow().rect_for_text_range(range_utf16, cx)
|
||||
self.element
|
||||
.borrow()
|
||||
.rect_for_text_range(view, range_utf16, cx)
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Vector2F {
|
||||
self.element.borrow().size()
|
||||
}
|
||||
|
||||
pub fn debug(&self, cx: &DebugContext) -> json::Value {
|
||||
let mut value = self.element.borrow().debug(cx);
|
||||
pub fn debug(&self, view: &V, cx: &ViewContext<V>) -> json::Value {
|
||||
let mut value = self.element.borrow().debug(view, cx);
|
||||
|
||||
if let Some(name) = &self.name {
|
||||
if let json::Value::Object(map) = &mut value {
|
||||
|
@ -460,26 +480,26 @@ impl ElementRc {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait ParentElement<'a>: Extend<ElementBox> + Sized {
|
||||
fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox>) {
|
||||
pub trait ParentElement<'a, V: View>: Extend<ElementBox<V>> + Sized {
|
||||
fn add_children(&mut self, children: impl IntoIterator<Item = ElementBox<V>>) {
|
||||
self.extend(children);
|
||||
}
|
||||
|
||||
fn add_child(&mut self, child: ElementBox) {
|
||||
fn add_child(&mut self, child: ElementBox<V>) {
|
||||
self.add_children(Some(child));
|
||||
}
|
||||
|
||||
fn with_children(mut self, children: impl IntoIterator<Item = ElementBox>) -> Self {
|
||||
fn with_children(mut self, children: impl IntoIterator<Item = ElementBox<V>>) -> Self {
|
||||
self.add_children(children);
|
||||
self
|
||||
}
|
||||
|
||||
fn with_child(self, child: ElementBox) -> Self {
|
||||
fn with_child(self, child: ElementBox<V>) -> Self {
|
||||
self.with_children(Some(child))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ParentElement<'a> for T where T: Extend<ElementBox> {}
|
||||
impl<'a, V: View, T> ParentElement<'a, V> for T where T: Extend<ElementBox<V>> {}
|
||||
|
||||
pub fn constrain_size_preserving_aspect_ratio(max_size: Vector2F, size: Vector2F) -> Vector2F {
|
||||
if max_size.x().is_infinite() && max_size.y().is_infinite() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue