WIP: Everything shredded

This commit is contained in:
Nathan Sobo 2023-04-10 16:10:32 -06:00
parent 7536645eea
commit 6638407ff9
26 changed files with 1136 additions and 1354 deletions

View file

@ -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() {