Skip to content

Commit

Permalink
Removed AnyBoardChild
Browse files Browse the repository at this point in the history
  • Loading branch information
RagibHasin committed Sep 18, 2024
1 parent 4140de1 commit 267b0f3
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 187 deletions.
29 changes: 28 additions & 1 deletion masonry/src/widget/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ impl<W: Widget> SvgElement for PositionedElement<W> {
}
}

// TODO Should also implement the other methods...
impl<W: Widget> Widget for PositionedElement<W> {
fn on_status_change(&mut self, ctx: &mut LifeCycleCtx, event: &StatusChange) {
self.inner.on_status_change(ctx, event);
Expand Down Expand Up @@ -318,6 +317,34 @@ impl<W: Widget> Widget for PositionedElement<W> {
fn children_ids(&self) -> SmallVec<[WidgetId; 16]> {
self.inner.children_ids()
}

fn on_pointer_event(&mut self, ctx: &mut EventCtx, event: &PointerEvent) {
self.inner.on_pointer_event(ctx, event);
}

fn on_text_event(&mut self, ctx: &mut EventCtx, event: &TextEvent) {
self.inner.on_text_event(ctx, event);
}

fn on_access_event(&mut self, ctx: &mut EventCtx, event: &AccessEvent) {
self.inner.on_access_event(ctx, event);
}

fn compose(&mut self, ctx: &mut crate::ComposeCtx) {
self.inner.compose(ctx);
}

fn skip_pointer(&self) -> bool {
self.inner.skip_pointer()
}

fn get_debug_text(&self) -> Option<String> {
self.inner.get_debug_text()
}

fn get_cursor(&self) -> cursor_icon::CursorIcon {
self.inner.get_cursor()
}
}

// --- MARK: IMPL BOARD ---
Expand Down
218 changes: 44 additions & 174 deletions xilem/src/view/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@

use std::marker::PhantomData;

use masonry::widget::{self, SvgElement, WidgetMut};
use masonry::widget::{self, KurboShape, SvgElement, WidgetMut};
use xilem_core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewId, ViewMarker, ViewPathTracker, ViewSequence,
AnyElement, AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View,
ViewElement, ViewMarker, ViewSequence,
};

use crate::{AnyWidgetView, Pod, ViewCtx, WidgetView};
use crate::{Pod, ViewCtx, WidgetView};

pub use masonry::widget::BoardParams;

mod kurbo_shape;
mod style_modifier;

pub use kurbo_shape::{AnyGraphicsView, GraphicsView};
pub use kurbo_shape::{AnyBoardView, GraphicsView};
pub use style_modifier::{fill, stroke, transform, Fill, GraphicsExt, Stroke, Transform};

pub fn board<State, Action, Seq: BoardSequence<State, Action>>(
Expand Down Expand Up @@ -121,6 +121,41 @@ impl SuperElement<BoardElement> for BoardElement {
}
}

impl AnyElement<BoardElement> for BoardElement {
fn replace_inner(mut this: Self::Mut<'_>, child: BoardElement) -> Self::Mut<'_> {
this.parent.remove_child(this.idx);
this.parent.insert_child(this.idx, child.element.inner);
this
}
}

impl SuperElement<Pod<KurboShape>> for BoardElement {
fn upcast(child: Pod<KurboShape>) -> Self {
BoardElement {
element: child.inner.svg_boxed().into(),
}
}

fn with_downcast_val<R>(
mut this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, Pod<KurboShape>>) -> R,
) -> (Self::Mut<'_>, R) {
let r = {
let mut child = this.parent.child_mut(this.idx);
f(child.downcast())
};
(this, r)
}
}

impl AnyElement<Pod<KurboShape>> for BoardElement {
fn replace_inner(mut this: Self::Mut<'_>, child: Pod<KurboShape>) -> Self::Mut<'_> {
this.parent.remove_child(this.idx);
this.parent.insert_child(this.idx, child.inner.svg_boxed());
this
}
}

pub struct BoardElementMut<'w> {
parent: WidgetMut<'w, widget::Board>,
idx: usize,
Expand Down Expand Up @@ -236,14 +271,14 @@ where
}
}

impl<State, Action, V> From<PositionedView<V, State, Action>> for AnyBoardChild<State, Action>
impl<State, Action, V> From<PositionedView<V, State, Action>> for Box<AnyBoardView<State, Action>>
where
State: 'static,
Action: 'static,
V: WidgetView<State, Action, ViewState: 'static>,
{
fn from(value: PositionedView<V, State, Action>) -> Self {
AnyBoardChild::View(positioned(value.view.boxed(), value.params))
Box::new(positioned(value.view, value.params))
}
}

Expand Down Expand Up @@ -318,179 +353,14 @@ where
}
}

/// A widget-type-erased positioned child [`View`], can be used within a [`Board`] [`View`]
pub enum AnyBoardChild<State, Action = ()> {
View(PositionedView<Box<AnyWidgetView<State, Action>>, State, Action>),
Graphics(Box<AnyGraphicsView<State, Action>>),
}

impl<State, Action, V> PositionedView<V, State, Action>
where
State: 'static,
Action: 'static,
V: WidgetView<State, Action>,
{
/// Turns this [`BoardItem`] into an [`AnyBoardChild`]
pub fn into_any_board(self) -> AnyBoardChild<State, Action> {
AnyBoardChild::View(positioned(Box::new(self.view), self.params))
}
}

#[doc(hidden)] // Implementation detail, public because of trait visibility rules
pub struct AnyBoardChildState<State: 'static, Action: 'static> {
#[allow(clippy::type_complexity)]
inner: <PositionedView<Box<AnyWidgetView<State, Action>>, State, Action> as View<
State,
Action,
ViewCtx,
>>::ViewState,

/// The generational id handling is essentially very similar to that of the `Option<impl ViewSequence>`,
/// where `None` would represent a Spacer, and `Some` a view
generation: u64,
}

impl<State, Action> ViewMarker for AnyBoardChild<State, Action> {}
impl<State, Action> View<State, Action, ViewCtx> for AnyBoardChild<State, Action>
where
State: 'static,
Action: 'static,
{
type Element = BoardElement;

type ViewState = AnyBoardChildState<State, Action>;

fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
let generation = 0;
let (element, view_state) = match self {
AnyBoardChild::View(view_item) => {
ctx.with_id(ViewId::new(generation), |ctx| view_item.build(ctx))
}
AnyBoardChild::Graphics(shape_item) => {
let (element, state) =
ctx.with_id(ViewId::new(generation), |ctx| shape_item.build(ctx));
(
BoardElement {
element: element.inner.svg_boxed().into(),
},
state,
)
}
};
(
element,
AnyBoardChildState {
inner: view_state,
generation,
},
)
}

fn rebuild<'el>(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
match (prev, self) {
(AnyBoardChild::View(prev), AnyBoardChild::View(this)) => ctx
.with_id(ViewId::new(view_state.generation), |ctx| {
this.rebuild(prev, &mut view_state.inner, ctx, element)
}),
(AnyBoardChild::Graphics(prev), AnyBoardChild::Graphics(this)) => {
{
let mut child = element.parent.child_mut(element.idx);
ctx.with_id(ViewId::new(view_state.generation), |ctx| {
this.rebuild(prev, &mut view_state.inner, ctx, child.downcast())
});
}
element
}
(AnyBoardChild::View(prev_view), AnyBoardChild::Graphics(new_shape)) => {
// Run teardown with the old path
ctx.with_id(ViewId::new(view_state.generation), |ctx| {
prev_view.teardown(
&mut view_state.inner,
ctx,
BoardElementMut {
parent: element.parent.reborrow_mut(),
idx: element.idx,
},
);
});
element.parent.remove_child(element.idx);
view_state.generation = view_state.generation.wrapping_add(1);
let (child, child_state) = ctx.with_id(ViewId::new(view_state.generation), |ctx| {
new_shape.build(ctx)
});
view_state.inner = child_state;
element
.parent
.insert_child(element.idx, child.inner.svg_boxed());
element
}
(AnyBoardChild::Graphics(prev_shape), AnyBoardChild::View(new_view)) => {
// Run teardown with the old path
{
let mut child = element.parent.child_mut(element.idx);
ctx.with_id(ViewId::new(view_state.generation), |ctx| {
prev_shape.teardown(&mut view_state.inner, ctx, child.downcast());
});
}
element.parent.remove_child(element.idx);
view_state.generation = view_state.generation.wrapping_add(1);
let (view_element, child_state) = ctx
.with_id(ViewId::new(view_state.generation), |ctx| {
new_view.build(ctx)
});
view_state.inner = child_state;
element
.parent
.insert_child(element.idx, view_element.element.inner);
element
}
}
}

fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
) {
match self {
AnyBoardChild::View(view_item) => {
view_item.teardown(&mut view_state.inner, ctx, element);
}
AnyBoardChild::Graphics(shape_item) => {
let mut child = element.parent.child_mut(element.idx);
shape_item.teardown(&mut view_state.inner, ctx, child.downcast());
}
}
}

fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
let (start, rest) = id_path
.split_first()
.expect("Id path has elements for AnyBoardChild");
if start.routing_id() != view_state.generation {
// The message was sent to a previous edition of the inner value
return MessageResult::Stale(message);
}
match self {
AnyBoardChild::View(view_item) => {
view_item.message(&mut view_state.inner, rest, message, app_state)
}
AnyBoardChild::Graphics(shape_item) => {
shape_item.message(&mut view_state.inner, rest, message, app_state)
}
}
pub fn into_any_board(self) -> Box<AnyBoardView<State, Action>> {
self.into()
}
}
12 changes: 7 additions & 5 deletions xilem/src/view/board/kurbo_shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@

//! Implementation of the View trait for various kurbo shapes.
use masonry::widget::KurboShape;
use masonry::widget::{KurboShape, SvgElement};
use vello::kurbo;
use xilem_core::{AnyElement, AnyView, DynMessage, MessageResult, Mut, OrphanView, SuperElement};

use crate::{Pod, ViewCtx, WidgetView};

pub trait GraphicsView<State, Action = ()>: WidgetView<State, Action, Widget = KurboShape> {}
use super::BoardElement;

pub trait GraphicsView<State, Action = ()>: WidgetView<State, Action, Widget: SvgElement> {}

impl<V, State, Action> GraphicsView<State, Action> for V where
V: WidgetView<State, Action, Widget = KurboShape> + Send + Sync
V: WidgetView<State, Action, Widget: SvgElement> + Send + Sync
{
}

pub type AnyGraphicsView<State, Action = ()> =
dyn AnyView<State, Action, ViewCtx, Pod<KurboShape>> + Send + Sync;
pub type AnyBoardView<State, Action = ()> =
dyn AnyView<State, Action, ViewCtx, BoardElement> + Send + Sync;

impl SuperElement<Pod<KurboShape>> for Pod<KurboShape> {
fn upcast(child: Pod<KurboShape>) -> Self {
Expand Down
14 changes: 7 additions & 7 deletions xilem/src/view/board/style_modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use xilem_core::{AnyView, DynMessage, MessageResult, Mut, View, ViewId, ViewMark

use crate::{Pod, ViewCtx};

use super::{AnyBoardChild, GraphicsView};
use super::{AnyBoardView, BoardElement, GraphicsView};

pub struct Transform<V, State, Action> {
child: V,
Expand Down Expand Up @@ -100,11 +100,11 @@ pub trait GraphicsExt<State, Action>: GraphicsView<State, Action> + Sized {
stroke(self, brush, style)
}

fn into_any_board(self) -> AnyBoardChild<State, Action>
fn into_any_board(self) -> Box<AnyBoardView<State, Action>>
where
Self: AnyView<State, Action, ViewCtx, Pod<KurboShape>> + Send + Sync + 'static,
Self: AnyView<State, Action, ViewCtx, BoardElement> + Send + Sync + 'static,
{
AnyBoardChild::Graphics(Box::new(self))
Box::new(self)
}
}

Expand All @@ -118,7 +118,7 @@ impl<State, Action, V> View<State, Action, ViewCtx> for Transform<V, State, Acti
where
State: 'static,
Action: 'static,
V: GraphicsView<State, Action>,
V: GraphicsView<State, Action, Widget = KurboShape>,
{
type ViewState = V::ViewState;
type Element = Pod<KurboShape>;
Expand Down Expand Up @@ -173,7 +173,7 @@ impl<State, Action, V> View<State, Action, ViewCtx> for Fill<V, State, Action>
where
State: 'static,
Action: 'static,
V: GraphicsView<State, Action>,
V: GraphicsView<State, Action, Widget = KurboShape>,
{
type ViewState = V::ViewState;
type Element = Pod<KurboShape>;
Expand Down Expand Up @@ -244,7 +244,7 @@ impl<State, Action, V> View<State, Action, ViewCtx> for Stroke<V, State, Action>
where
State: 'static,
Action: 'static,
V: GraphicsView<State, Action>,
V: GraphicsView<State, Action, Widget = KurboShape>,
{
type ViewState = V::ViewState;
type Element = Pod<KurboShape>;
Expand Down

0 comments on commit 267b0f3

Please sign in to comment.