Skip to content

Commit

Permalink
Implement View for Arc<dyn AnyView>, and add super bounds of `Vie…
Browse files Browse the repository at this point in the history
…w` to `AnyView`
  • Loading branch information
Philipp-M committed Jan 25, 2024
1 parent f2216c2 commit 12dc722
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 24 deletions.
11 changes: 4 additions & 7 deletions crates/xilem_core/src/any_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ macro_rules! generate_anyview_trait {
$viewmarker:ty,
$cx:ty,
$changeflags:ty,
$anywidget:ident,
$boxedview:ident;
$anywidget:ident;
$(($($super_bounds:tt)*))?
$(,($($state_bounds:tt)*))?
) => {
/// A trait enabling type erasure of views.
pub trait $anyview<T, A = ()> {
pub trait $anyview<T, A = ()>: $($( $super_bounds )*)? {
fn as_any(&self) -> &dyn std::any::Any;

fn dyn_build(
Expand Down Expand Up @@ -105,11 +104,9 @@ macro_rules! generate_anyview_trait {
}
}

pub type $boxedview<T, A = ()> = Box<dyn $anyview<T, A> + $($( $super_bounds )*)? >;
impl<T, A> $viewmarker for Box<dyn $anyview<T, A>> {}

impl<T, A> $viewmarker for $boxedview<T, A> {}

impl<T, A> $viewtrait<T, A> for $boxedview<T, A> {
impl<T, A> $viewtrait<T, A> for Box<dyn $anyview<T, A>> {
type State = Box<dyn std::any::Any + $($( $state_bounds )*)? >;

type Element = Box<dyn $anywidget>;
Expand Down
46 changes: 44 additions & 2 deletions crates/xilem_core/src/view/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

#[macro_export]
macro_rules! generate_rc_view {
($($rc_ty:ident)::*, $viewtrait:ident, $viewmarker:ty, $cx:ty, $changeflags:ty; $($ss:tt)*) => {
($($rc_ty:ident)::*, $viewtrait:ident, $viewmarker:ty, $cx:ty, $changeflags:ty, $anyview:ident, $anywidget:ident; $($state_bounds:tt)*) => {
impl<V> $viewmarker for $($rc_ty)::*<V> {}

impl<T, A, V: $viewtrait<T, A> $( $ss )*> $viewtrait<T, A> for $($rc_ty)::*<V> {
impl<T, A, V: $viewtrait<T, A>> $viewtrait<T, A> for $($rc_ty)::*<V> {
type State = V::State;

type Element = V::Element;
Expand Down Expand Up @@ -40,5 +40,47 @@ macro_rules! generate_rc_view {
V::message(self, id_path, state, message, app_state)
}
}

impl<T, A> $viewmarker for $($rc_ty)::*<dyn $anyview<T, A>> {}
impl<T, A> $viewtrait<T, A> for $($rc_ty)::*<dyn $anyview<T, A>> {
type State = Box<dyn std::any::Any + $( $state_bounds )*>;

type Element = Box<dyn $anywidget>;

fn build(&self, cx: &mut $cx) -> ($crate::Id, Self::State, Self::Element) {
use std::ops::Deref;
self.deref().dyn_build(cx)
}

fn rebuild(
&self,
cx: &mut $cx,
prev: &Self,
id: &mut $crate::Id,
state: &mut Self::State,
element: &mut Self::Element,
) -> $changeflags {
if !$($rc_ty)::*::ptr_eq(self, prev) {
use std::ops::Deref;
self.deref()
.dyn_rebuild(cx, prev.deref(), id, state, element)
} else {
ChangeFlags::empty()
}

}

fn message(
&self,
id_path: &[$crate::Id],
state: &mut Self::State,
message: Box<dyn std::any::Any>,
app_state: &mut T,
) -> $crate::MessageResult<A> {
use std::ops::{Deref, DerefMut};
self.deref()
.dyn_message(id_path, state.deref_mut(), message, app_state)
}
}
};
}
4 changes: 2 additions & 2 deletions crates/xilem_web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub use one_of::{
pub use optional_action::{Action, OptionalAction};
pub use pointer::{Pointer, PointerDetails, PointerMsg};
pub use view::{
memoize, static_view, Adapt, AdaptState, AdaptThunk, AnyView, BoxedView, Memoize, MemoizeState,
Pod, View, ViewMarker, ViewSequence,
memoize, static_view, Adapt, AdaptState, AdaptThunk, AnyView, Memoize, MemoizeState, Pod, View,
ViewMarker, ViewSequence,
};
pub use view_ext::ViewExt;

Expand Down
6 changes: 3 additions & 3 deletions crates/xilem_web/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ impl Pod {

xilem_core::generate_view_trait! {View, DomNode, Cx, ChangeFlags;}
xilem_core::generate_viewsequence_trait! {ViewSequence, View, ViewMarker, DomNode, Cx, ChangeFlags, Pod;}
xilem_core::generate_anyview_trait! {AnyView, View, ViewMarker, Cx, ChangeFlags, AnyNode, BoxedView;}
xilem_core::generate_anyview_trait! {AnyView, View, ViewMarker, Cx, ChangeFlags, AnyNode;}
xilem_core::generate_memoize_view! {Memoize, MemoizeState, View, ViewMarker, Cx, ChangeFlags, static_view, memoize;}
xilem_core::generate_adapt_view! {View, Cx, ChangeFlags;}
xilem_core::generate_adapt_state_view! {View, Cx, ChangeFlags;}
xilem_core::generate_rc_view! {std::rc::Rc, View, ViewMarker, Cx, ChangeFlags; }
xilem_core::generate_rc_view! {std::sync::Arc, View, ViewMarker, Cx, ChangeFlags; + Sync}
xilem_core::generate_rc_view! {std::rc::Rc, View, ViewMarker, Cx, ChangeFlags, AnyView, AnyNode;}
xilem_core::generate_rc_view! {std::sync::Arc, View, ViewMarker, Cx, ChangeFlags, AnyView, AnyNode;}

// strings -> text nodes

Expand Down
11 changes: 5 additions & 6 deletions examples/memoization.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::sync::Arc;
use xilem::view::{button, memoize, v_stack, BoxedView};
use xilem::view::{button, memoize, v_stack, AnyView};
use xilem::{view::View, App, AppLauncher};

// There are currently two ways to do memoization
Expand Down Expand Up @@ -39,19 +39,18 @@ fn app_logic(state: &mut AppState) -> impl View<AppState> {

struct AppState {
count: i32,
// TODO Maybe support `impl View for Arc<dyn AnyView>` to avoid double indirection
count_view: Option<Arc<BoxedView<AppState>>>,
count_view: Option<Arc<dyn AnyView<AppState>>>,
}

impl AppState {
fn make_increase_button(&self) -> Arc<BoxedView<AppState>> {
Arc::new(Box::new(button(
fn make_increase_button(&self) -> Arc<dyn AnyView<AppState>> {
Arc::new(button(
format!("current count is {}", self.count),
|state: &mut AppState| {
state.count += 1;
state.count_view = None;
},
)))
))
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ pub use linear_layout::{h_stack, v_stack, LinearLayout};
pub use list::{list, List};
pub use switch::switch;
pub use view::{
memoize, static_view, Adapt, AdaptState, AnyView, BoxedView, Cx, Memoize, MemoizeState, View,
ViewMarker, ViewSequence,
memoize, static_view, Adapt, AdaptState, AnyView, Cx, Memoize, MemoizeState, View, ViewMarker,
ViewSequence,
};

#[cfg(feature = "taffy")]
Expand Down
4 changes: 2 additions & 2 deletions src/view/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ use crate::widget::{AnyWidget, ChangeFlags, Pod, Widget};

xilem_core::generate_view_trait! {View, Widget, Cx, ChangeFlags; (Send + Sync), (Send)}
xilem_core::generate_viewsequence_trait! {ViewSequence, View, ViewMarker, Widget, Cx, ChangeFlags, Pod; (Send + Sync), (Send)}
xilem_core::generate_anyview_trait! {AnyView, View, ViewMarker, Cx, ChangeFlags, AnyWidget, BoxedView; (Send + Sync), (Send)}
xilem_core::generate_anyview_trait! {AnyView, View, ViewMarker, Cx, ChangeFlags, AnyWidget; (Send + Sync), (Send)}
xilem_core::generate_memoize_view! {Memoize, MemoizeState, View, ViewMarker, Cx, ChangeFlags, static_view, memoize; + Send + Sync}
xilem_core::generate_adapt_view! {View, Cx, ChangeFlags; + Send + Sync}
xilem_core::generate_adapt_state_view! {View, Cx, ChangeFlags; + Send + Sync}
xilem_core::generate_rc_view! {std::sync::Arc, View, ViewMarker, Cx, ChangeFlags; + Sync + Sync}
xilem_core::generate_rc_view! {std::sync::Arc, View, ViewMarker, Cx, ChangeFlags, AnyView, AnyWidget; Send}

#[derive(Clone)]
pub struct Cx {
Expand Down

0 comments on commit 12dc722

Please sign in to comment.