Skip to content

Commit

Permalink
Simplify BoardElement
Browse files Browse the repository at this point in the history
  • Loading branch information
RagibHasin committed Sep 18, 2024
1 parent 6571b0a commit 4140de1
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 58 deletions.
125 changes: 112 additions & 13 deletions masonry/src/widget/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ pub struct Board {
/// Parameters for an item in a [`Board`] container.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct BoardParams {
origin: Point,
size: Size,
pub origin: Point,
pub size: Size,
}

pub struct KurboShape {
Expand Down Expand Up @@ -62,6 +62,9 @@ pub enum ConcreteShape {
pub trait SvgElement: Widget {
fn origin(&self) -> Point; // relative to parents transform
fn size(&self) -> Size;

fn set_origin(&mut self, origin: Point); // relative to parents transform
fn set_size(&mut self, size: Size);
}

impl SvgElement for KurboShape {
Expand All @@ -72,6 +75,14 @@ impl SvgElement for KurboShape {
fn size(&self) -> Size {
self.shape.bounding_box().size()
}

fn set_origin(&mut self, _: Point) {
panic!("a shape doens not support setting its origin after creation")
}

fn set_size(&mut self, _: Size) {
panic!("a shape doens not support setting its size after creation")
}
}

impl SvgElement for Box<dyn SvgElement> {
Expand All @@ -82,6 +93,14 @@ impl SvgElement for Box<dyn SvgElement> {
fn size(&self) -> Size {
self.deref().size()
}

fn set_origin(&mut self, origin: Point) {
self.deref_mut().set_origin(origin);
}

fn set_size(&mut self, size: Size) {
self.deref_mut().set_size(size);
}
}

impl Widget for Box<dyn SvgElement> {
Expand Down Expand Up @@ -162,6 +181,62 @@ impl Widget for Box<dyn SvgElement> {
}
}

impl<'a> WidgetMut<'a, Box<dyn SvgElement>> {
/// Attempt to downcast to `WidgetMut` of concrete Widget type.
pub fn try_downcast<W2: Widget>(&mut self) -> Option<WidgetMut<'_, W2>> {
Some(WidgetMut {
ctx: self.ctx.reborrow_mut(),
widget: self.widget.as_mut_any().downcast_mut()?,
})
}

/// Downcasts to `WidgetMut` of concrete Widget type.
///
/// ## Panics
///
/// Panics if the downcast fails, with an error message that shows the
/// discrepancy between the expected and actual types.
pub fn downcast_positioned<W2: Widget>(&mut self) -> WidgetMut<'_, W2> {
let w1_name = self.widget.type_name();
match self.widget.as_mut_any().downcast_mut() {
Some(PositionedElement { inner: widget, .. }) => WidgetMut {
ctx: self.ctx.reborrow_mut(),
widget,
},
None => {
panic!(
"failed to downcast widget: expected widget of type `{}`, found `{}`",
std::any::type_name::<W2>(),
w1_name,
);
}
}
}

/// Downcasts to `WidgetMut` of concrete Widget type.
///
/// ## Panics
///
/// Panics if the downcast fails, with an error message that shows the
/// discrepancy between the expected and actual types.
pub fn downcast<W2: Widget>(&mut self) -> WidgetMut<'_, W2> {
let w1_name = self.widget.type_name();
match self.widget.as_mut_any().downcast_mut() {
Some(widget) => WidgetMut {
ctx: self.ctx.reborrow_mut(),
widget,
},
None => {
panic!(
"failed to downcast widget: expected widget of type `{}`, found `{}`",
std::any::type_name::<W2>(),
w1_name,
);
}
}
}
}

pub struct PositionedElement<W> {
inner: W,
params: BoardParams,
Expand All @@ -176,6 +251,26 @@ impl<W> PositionedElement<W> {
}
}

impl<W: Widget> WidgetPod<W> {
pub fn positioned(self, params: impl Into<BoardParams>) -> WidgetPod<Box<dyn SvgElement>> {
let id = self.id();
WidgetPod::new_with_id(
Box::new(PositionedElement {
inner: self.inner().unwrap(),
params: params.into(),
}),
id,
)
}
}

impl WidgetPod<KurboShape> {
pub fn svg_boxed(self) -> WidgetPod<Box<dyn SvgElement>> {
let id = self.id();
WidgetPod::new_with_id(Box::new(self.inner().unwrap()), id)
}
}

impl<W: Widget> SvgElement for PositionedElement<W> {
fn origin(&self) -> Point {
self.params.origin
Expand All @@ -184,6 +279,14 @@ impl<W: Widget> SvgElement for PositionedElement<W> {
fn size(&self) -> Size {
self.params.size
}

fn set_origin(&mut self, origin: Point) {
self.params.origin = origin;
}

fn set_size(&mut self, size: Size) {
self.params.size = size;
}
}

// TODO Should also implement the other methods...
Expand Down Expand Up @@ -427,12 +530,13 @@ impl Widget for Board {
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
bc.debug_check("Board");

for widget in &mut self.children {
ctx.run_layout(
widget,
&BoxConstraints::tight(widget.as_ref().unwrap().size()),
);
ctx.place_child(widget, widget.as_ref().unwrap().origin());
for child in &mut self.children {
let (size, origin) = {
let child_ref = ctx.get_raw_ref(child);
(child_ref.widget().size(), child_ref.widget().origin())
};
ctx.run_layout(child, &BoxConstraints::tight(size));
ctx.place_child(child, origin);
}

bc.max()
Expand Down Expand Up @@ -525,11 +629,6 @@ impl From<Rect> for BoardParams {
}
}

struct Child {
widget: WidgetPod<Box<dyn Widget>>,
params: BoardParams,
}

macro_rules! for_all_variants {
($self:expr; $i:ident => $e:expr) => {
match $self {
Expand Down
6 changes: 6 additions & 0 deletions masonry/src/widget/widget_pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ impl<W: Widget> WidgetPod<W> {
}

/// Take the inner widget, if it has not been inserted yet.
///
/// Never call it outside of `Widget::lyfecycle` or `View::build`
pub fn inner(self) -> Option<W> {
if let WidgetPodInner::Created(w) = self.inner {
Some(w)
Expand All @@ -68,6 +70,8 @@ impl<W: Widget> WidgetPod<W> {
}

/// Get access to the inner widget, if it has not been inserted yet.
///
/// Never call it outside of `Widget::lyfecycle` or `View::build`
pub fn as_ref(&self) -> Option<&W> {
if let WidgetPodInner::Created(w) = &self.inner {
Some(w)
Expand All @@ -77,6 +81,8 @@ impl<W: Widget> WidgetPod<W> {
}

/// Get access to the inner widget, if it has not been inserted yet.
///
/// Never call it outside of `Widget::lyfecycle` or `View::build`
pub fn as_mut(&mut self) -> Option<&mut W> {
if let WidgetPodInner::Created(w) = &mut self.inner {
Some(w)
Expand Down
83 changes: 38 additions & 45 deletions xilem/src/view/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@

use std::marker::PhantomData;

use masonry::{
widget::{self, KurboShape, WidgetMut},
Widget,
};
use masonry::widget::{self, SvgElement, WidgetMut};
use xilem_core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewId, ViewMarker, ViewPathTracker, ViewSequence,
Expand Down Expand Up @@ -51,11 +48,8 @@ where
let mut elements = AppendVec::default();
let mut widget = widget::Board::new();
let seq_state = self.sequence.seq_build(ctx, &mut elements);
for child in elements.into_inner() {
widget = match child {
BoardElement::View(pod, params) => widget.with_child_pod(pod.inner, params),
BoardElement::Graphics(pod) => widget.with_shape_pod(pod.inner),
}
for BoardElement { element } in elements.into_inner() {
widget = widget.with_child_pod(element.inner);
}
(Pod::new(widget), seq_state)
}
Expand Down Expand Up @@ -98,10 +92,8 @@ where
}
}

#[expect(clippy::large_enum_variant)]
pub enum BoardElement {
View(Pod<Box<dyn Widget>>, BoardParams),
Graphics(Pod<KurboShape>),
pub struct BoardElement {
element: Pod<Box<dyn SvgElement>>,
}

impl ViewElement for BoardElement {
Expand Down Expand Up @@ -151,29 +143,15 @@ impl<'w> BoardSplice<'w> {
}

impl ElementSplice<BoardElement> for BoardSplice<'_> {
fn insert(&mut self, element: BoardElement) {
match element {
BoardElement::View(pod, params) => {
self.element.insert_child_pod(self.idx, pod.inner, params);
}
BoardElement::Graphics(pod) => {
self.element.insert_shape_pod(self.idx, pod.inner);
}
}
fn insert(&mut self, BoardElement { element }: BoardElement) {
self.element.insert_child(self.idx, element.inner);
self.idx += 1;
}

fn with_scratch<R>(&mut self, f: impl FnOnce(&mut AppendVec<BoardElement>) -> R) -> R {
let ret = f(&mut self.scratch);
for element in self.scratch.drain() {
match element {
BoardElement::View(pod, params) => {
self.element.insert_child_pod(self.idx, pod.inner, params);
}
BoardElement::Graphics(pod) => {
self.element.insert_shape_pod(self.idx, pod.inner);
}
}
for BoardElement { element } in self.scratch.drain() {
self.element.insert_child(self.idx, element.inner);
self.idx += 1;
}
ret
Expand Down Expand Up @@ -283,7 +261,9 @@ where
fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
let (pod, state) = self.view.build(ctx);
(
BoardElement::View(pod.inner.boxed().into(), self.params),
BoardElement {
element: pod.inner.positioned(self.params).into(),
},
state,
)
}
Expand All @@ -296,14 +276,22 @@ where
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
{
if self.params != prev.params {
element
.parent
.update_child_board_params(element.idx, self.params);
}
// if self.params != prev.params {
// element
// .parent
// .update_child_board_params(element.idx, self.params);
// }
let mut child = element.parent.child_mut(element.idx);
self.view
.rebuild(&prev.view, view_state, ctx, child.downcast());
.rebuild(&prev.view, view_state, ctx, child.downcast_positioned());
if self.params.origin != prev.params.origin {
child.widget.set_origin(self.params.origin);
child.ctx.request_layout();
}
if self.params.size != prev.params.size {
child.widget.set_size(self.params.size);
child.ctx.request_layout();
}
}
element
}
Expand All @@ -315,7 +303,8 @@ where
mut element: Mut<'_, Self::Element>,
) {
let mut child = element.parent.child_mut(element.idx);
self.view.teardown(view_state, ctx, child.downcast());
self.view
.teardown(view_state, ctx, child.downcast_positioned());
}

fn message(
Expand Down Expand Up @@ -380,7 +369,12 @@ where
AnyBoardChild::Graphics(shape_item) => {
let (element, state) =
ctx.with_id(ViewId::new(generation), |ctx| shape_item.build(ctx));
(BoardElement::Graphics(element), state)
(
BoardElement {
element: element.inner.svg_boxed().into(),
},
state,
)
}
};
(
Expand Down Expand Up @@ -431,7 +425,9 @@ where
new_shape.build(ctx)
});
view_state.inner = child_state;
element.parent.insert_shape_pod(element.idx, child.inner);
element
.parent
.insert_child(element.idx, child.inner.svg_boxed());
element
}
(AnyBoardChild::Graphics(prev_shape), AnyBoardChild::View(new_view)) => {
Expand All @@ -449,12 +445,9 @@ where
new_view.build(ctx)
});
view_state.inner = child_state;
let BoardElement::View(pod, params) = view_element else {
unreachable!()
};
element
.parent
.insert_child_pod(element.idx, pod.inner, params);
.insert_child(element.idx, view_element.element.inner);
element
}
}
Expand Down

0 comments on commit 4140de1

Please sign in to comment.