xilem: Change `View::rebuild` to not return the element, and cleanup imports and `Mut` (#681)

It's possible to avoid returning the `ViewElement::Mut` in
`View::rebuild`, while having access to the element *after* a child view
was rebuilt.

This PR removes that again making the signature a little bit cleaner,
and also cleans up a lot of other stuff:
* `Mut<'_, Self::Element>` can be shortened to `Mut<Self::Element>`
* `use xilem::core::*` instead of `use xilem_core::*`, this is
especially useful in the examples, to avoid newcomers giving the
impression, that an additional dependency xilem_core is needed.
* Various cosmetic stuff, like one typo fix, empty line between
doc-comment (as (nightly) clippy currently bleats for me)

For more context see
https://xi.zulipchat.com/#narrow/stream/354396-xilem/topic/.E2.9C.94.20.60.26mut.20ViewElement.3A.3AMut.3C'_.3E.60.20in.20.60View.3A.3Arebuild.60.3F
This commit is contained in:
Philipp Mildenberger 2024-10-17 13:56:31 +02:00 committed by GitHub
parent 3ba0df6064
commit bad934b21a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
56 changed files with 683 additions and 824 deletions

View File

@ -9,13 +9,13 @@ use std::sync::Arc;
use vello::peniko::{Blob, Image};
use winit::{dpi::LogicalSize, error::EventLoopError, window::Window};
use xilem::{
core::{fork, one_of::OneOf3},
view::{
button, flex, image, portal, prose, sized_box, spinner, worker, Axis, CrossAxisAlignment,
FlexExt, FlexSpacer,
},
Color, EventLoop, EventLoopBuilder, TextAlignment, WidgetView, Xilem,
};
use xilem_core::{fork, one_of::OneOf3};
/// The main state of the application.
struct HttpCats {

View File

@ -7,6 +7,7 @@
use std::time::Duration;
use xilem::{
core::{fork, run_once},
tokio::time,
view::{
button, button_any_pointer, checkbox, flex, label, prose, task, textbox, Axis,
@ -166,7 +167,6 @@ fn main() {
#[cfg(target_os = "android")]
use winit::platform::android::activity::AndroidApp;
use xilem_core::{fork, run_once};
#[cfg(target_os = "android")]
// Safety: We are following `android_activity`'s docs here

View File

@ -12,10 +12,11 @@ use tokio::time;
use tracing::warn;
use winit::error::EventLoopError;
use winit::window::Window;
use xilem::view::{button, flex, label, task, FlexSequence, FlexSpacer};
use xilem::{WidgetView, Xilem};
use xilem_core::fork;
use xilem_core::one_of::Either;
use xilem::{
core::{fork, one_of::Either},
view::{button, flex, label, task, FlexSequence, FlexSpacer},
WidgetView, Xilem,
};
/// The state of the entire application.
///

View File

@ -12,13 +12,13 @@ use masonry::parley::{
use time::{error::IndeterminateOffset, macros::format_description, OffsetDateTime, UtcOffset};
use winit::error::EventLoopError;
use xilem::{
core::fork,
view::{
button, flex, label, portal, prose, sized_box, task, variable_label, Axis, FlexExt,
FlexSpacer,
},
Color, EventLoop, EventLoopBuilder, WidgetView, Xilem,
};
use xilem_core::fork;
/// The state of the application, owned by Xilem and updated by the callbacks below.
struct Clocks {

View File

@ -10,9 +10,11 @@ use masonry::{
use smallvec::{smallvec, SmallVec};
use tracing::{trace_span, Span};
use vello::Scene;
use xilem_core::{AnyElement, AnyView, SuperElement};
use crate::{Pod, ViewCtx};
use crate::{
core::{AnyElement, AnyView, Mut, SuperElement},
Pod, ViewCtx,
};
/// A view which can have any underlying view type.
///
@ -35,7 +37,7 @@ impl<W: Widget> SuperElement<Pod<W>, ViewCtx> for Pod<DynWidget> {
fn with_downcast_val<R>(
mut this: Self::Mut<'_>,
f: impl FnOnce(<Pod<W> as xilem_core::ViewElement>::Mut<'_>) -> R,
f: impl FnOnce(Mut<Pod<W>>) -> R,
) -> (Self::Mut<'_>, R) {
let ret = {
let mut child = this.ctx.get_mut(&mut this.widget.inner);

View File

@ -1,17 +1,17 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use std::sync::Arc;
use crate::{
core::{DynMessage, Message, MessageResult, ProxyError, RawProxy, ViewId},
ViewCtx, WidgetView,
};
use masonry::{
app_driver::AppDriver,
event_loop_runner::{self, EventLoopProxy, MasonryUserEvent},
widget::RootWidget,
WidgetId,
};
use xilem_core::{DynMessage, Message, MessageResult, ProxyError, RawProxy, ViewId};
use crate::{ViewCtx, WidgetView};
use std::sync::Arc;
pub struct MasonryDriver<State, Logic, View, ViewState> {
pub(crate) state: State,

View File

@ -7,6 +7,10 @@
#![warn(clippy::print_stdout, clippy::print_stderr, clippy::dbg_macro)]
use std::{collections::HashMap, sync::Arc};
use crate::core::{
AsyncCtx, MessageResult, Mut, RawProxy, SuperElement, View, ViewElement, ViewId,
ViewPathTracker, ViewSequence,
};
use masonry::{
dpi::LogicalSize,
event_loop_runner,
@ -17,10 +21,6 @@ use winit::{
error::EventLoopError,
window::{Window, WindowAttributes},
};
use xilem_core::{
AsyncCtx, MessageResult, RawProxy, SuperElement, View, ViewElement, ViewId, ViewPathTracker,
ViewSequence,
};
pub use masonry::{
dpi,
@ -166,7 +166,7 @@ impl<W: Widget> SuperElement<Pod<W>, ViewCtx> for Pod<Box<dyn Widget>> {
fn with_downcast_val<R>(
mut this: Self::Mut<'_>,
f: impl FnOnce(<Pod<W> as xilem_core::ViewElement>::Mut<'_>) -> R,
f: impl FnOnce(Mut<Pod<W>>) -> R,
) -> (Self::Mut<'_>, R) {
let downcast = this.downcast();
let ret = f(downcast);
@ -245,7 +245,7 @@ pub struct ViewCtx {
}
impl ViewPathTracker for ViewCtx {
fn push_id(&mut self, id: xilem_core::ViewId) {
fn push_id(&mut self, id: ViewId) {
self.id_path.push(id);
}
@ -253,7 +253,7 @@ impl ViewPathTracker for ViewCtx {
self.id_path.pop();
}
fn view_path(&mut self) -> &[xilem_core::ViewId] {
fn view_path(&mut self) -> &[ViewId] {
&self.id_path
}
}

View File

@ -3,6 +3,10 @@
//! Statically typed alternatives to the type-erased [`AnyView`](`crate::AnyView`).
use crate::{
core::{one_of::OneOf, Mut},
Pod, ViewCtx,
};
use accesskit::{NodeBuilder, Role};
use masonry::{
AccessCtx, AccessEvent, BoxConstraints, EventCtx, LayoutCtx, LifeCycleCtx, PaintCtx, Point,
@ -11,8 +15,6 @@ use masonry::{
use smallvec::{smallvec, SmallVec};
use vello::Scene;
use crate::{Pod, ViewCtx};
impl<
A: Widget,
B: Widget,
@ -38,82 +40,55 @@ impl<
{
type OneOfElement = Pod<OneOfWidget<A, B, C, D, E, F, G, H, I>>;
fn with_downcast_a(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<A>>),
) {
fn with_downcast_a(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<A>>)) {
match elem.widget {
OneOfWidget::A(a) => f(elem.ctx.get_mut(a)),
_ => unreachable!(),
}
}
fn with_downcast_b(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<B>>),
) {
fn with_downcast_b(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<B>>)) {
match elem.widget {
OneOfWidget::B(b) => f(elem.ctx.get_mut(b)),
_ => unreachable!(),
}
}
fn with_downcast_c(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<C>>),
) {
fn with_downcast_c(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<C>>)) {
match elem.widget {
OneOfWidget::C(c) => f(elem.ctx.get_mut(c)),
_ => unreachable!(),
}
}
fn with_downcast_d(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<D>>),
) {
fn with_downcast_d(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<D>>)) {
match elem.widget {
OneOfWidget::D(d) => f(elem.ctx.get_mut(d)),
_ => unreachable!(),
}
}
fn with_downcast_e(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<E>>),
) {
fn with_downcast_e(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<E>>)) {
match elem.widget {
OneOfWidget::E(e) => f(elem.ctx.get_mut(e)),
_ => unreachable!(),
}
}
fn with_downcast_f(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<F>>),
) {
fn with_downcast_f(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<F>>)) {
match elem.widget {
OneOfWidget::F(f_) => f(elem.ctx.get_mut(f_)),
_ => unreachable!(),
}
}
fn with_downcast_g(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<G>>),
) {
fn with_downcast_g(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<G>>)) {
match elem.widget {
OneOfWidget::G(g) => f(elem.ctx.get_mut(g)),
_ => unreachable!(),
}
}
fn with_downcast_h(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<H>>),
) {
fn with_downcast_h(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<H>>)) {
match elem.widget {
OneOfWidget::H(h) => f(elem.ctx.get_mut(h)),
_ => unreachable!(),
}
}
fn with_downcast_i(
elem: &mut xilem_core::Mut<'_, Self::OneOfElement>,
f: impl FnOnce(xilem_core::Mut<'_, Pod<I>>),
) {
fn with_downcast_i(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<I>>)) {
match elem.widget {
OneOfWidget::I(i) => f(elem.ctx.get_mut(i)),
_ => unreachable!(),
@ -121,55 +96,35 @@ impl<
}
fn upcast_one_of_element(
&mut self,
elem: xilem_core::one_of::OneOf<
Pod<A>,
Pod<B>,
Pod<C>,
Pod<D>,
Pod<E>,
Pod<F>,
Pod<G>,
Pod<H>,
Pod<I>,
>,
elem: OneOf<Pod<A>, Pod<B>, Pod<C>, Pod<D>, Pod<E>, Pod<F>, Pod<G>, Pod<H>, Pod<I>>,
) -> Self::OneOfElement {
match elem {
xilem_core::one_of::OneOf::A(w) => self.new_pod(OneOfWidget::A(w.inner)),
xilem_core::one_of::OneOf::B(w) => self.new_pod(OneOfWidget::B(w.inner)),
xilem_core::one_of::OneOf::C(w) => self.new_pod(OneOfWidget::C(w.inner)),
xilem_core::one_of::OneOf::D(w) => self.new_pod(OneOfWidget::D(w.inner)),
xilem_core::one_of::OneOf::E(w) => self.new_pod(OneOfWidget::E(w.inner)),
xilem_core::one_of::OneOf::F(w) => self.new_pod(OneOfWidget::F(w.inner)),
xilem_core::one_of::OneOf::G(w) => self.new_pod(OneOfWidget::G(w.inner)),
xilem_core::one_of::OneOf::H(w) => self.new_pod(OneOfWidget::H(w.inner)),
xilem_core::one_of::OneOf::I(w) => self.new_pod(OneOfWidget::I(w.inner)),
OneOf::A(w) => self.new_pod(OneOfWidget::A(w.inner)),
OneOf::B(w) => self.new_pod(OneOfWidget::B(w.inner)),
OneOf::C(w) => self.new_pod(OneOfWidget::C(w.inner)),
OneOf::D(w) => self.new_pod(OneOfWidget::D(w.inner)),
OneOf::E(w) => self.new_pod(OneOfWidget::E(w.inner)),
OneOf::F(w) => self.new_pod(OneOfWidget::F(w.inner)),
OneOf::G(w) => self.new_pod(OneOfWidget::G(w.inner)),
OneOf::H(w) => self.new_pod(OneOfWidget::H(w.inner)),
OneOf::I(w) => self.new_pod(OneOfWidget::I(w.inner)),
}
}
fn update_one_of_element_mut(
elem_mut: &mut xilem_core::Mut<'_, Self::OneOfElement>,
new_elem: xilem_core::one_of::OneOf<
Pod<A>,
Pod<B>,
Pod<C>,
Pod<D>,
Pod<E>,
Pod<F>,
Pod<G>,
Pod<H>,
Pod<I>,
>,
elem_mut: &mut Mut<Self::OneOfElement>,
new_elem: OneOf<Pod<A>, Pod<B>, Pod<C>, Pod<D>, Pod<E>, Pod<F>, Pod<G>, Pod<H>, Pod<I>>,
) {
let new_inner = match new_elem {
xilem_core::one_of::OneOf::A(w) => OneOfWidget::A(w.inner),
xilem_core::one_of::OneOf::B(w) => OneOfWidget::B(w.inner),
xilem_core::one_of::OneOf::C(w) => OneOfWidget::C(w.inner),
xilem_core::one_of::OneOf::D(w) => OneOfWidget::D(w.inner),
xilem_core::one_of::OneOf::E(w) => OneOfWidget::E(w.inner),
xilem_core::one_of::OneOf::F(w) => OneOfWidget::F(w.inner),
xilem_core::one_of::OneOf::G(w) => OneOfWidget::G(w.inner),
xilem_core::one_of::OneOf::H(w) => OneOfWidget::H(w.inner),
xilem_core::one_of::OneOf::I(w) => OneOfWidget::I(w.inner),
OneOf::A(w) => OneOfWidget::A(w.inner),
OneOf::B(w) => OneOfWidget::B(w.inner),
OneOf::C(w) => OneOfWidget::C(w.inner),
OneOf::D(w) => OneOfWidget::D(w.inner),
OneOf::E(w) => OneOfWidget::E(w.inner),
OneOf::F(w) => OneOfWidget::F(w.inner),
OneOf::G(w) => OneOfWidget::G(w.inner),
OneOf::H(w) => OneOfWidget::H(w.inner),
OneOf::I(w) => OneOfWidget::I(w.inner),
};
let old_inner = std::mem::replace(elem_mut.widget, new_inner);
match old_inner {

View File

@ -1,13 +1,12 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{core::View, Pod};
use masonry::{widget, ArcStr};
use xilem_core::{Mut, ViewMarker};
use crate::{
core::{DynMessage, Mut, View, ViewMarker},
MessageResult, Pod, ViewCtx, ViewId,
};
pub use masonry::PointerButton;
use crate::{MessageResult, ViewCtx, ViewId};
use masonry::{widget, ArcStr};
/// A button which calls `callback` when the primary mouse button (normally left) is pressed.
pub fn button<State, Action>(
@ -53,25 +52,19 @@ where
ctx.with_leaf_action_widget(|ctx| ctx.new_pod(widget::Button::new(self.label.clone())))
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
_: &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.label != self.label {
element.set_text(self.label.clone());
}
element
}
fn teardown(
&self,
_: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
) {
fn teardown(&self, _: &mut Self::ViewState, ctx: &mut ViewCtx, element: Mut<Self::Element>) {
ctx.teardown_leaf(element);
}
@ -79,7 +72,7 @@ where
&self,
_: &mut Self::ViewState,
id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
debug_assert!(

View File

@ -1,10 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, ViewMarker},
MessageResult, Pod, View, ViewCtx, ViewId,
};
use masonry::{widget, ArcStr};
use xilem_core::{Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};
pub fn checkbox<F, State, Action>(
label: impl Into<ArcStr>,
@ -44,28 +45,22 @@ where
})
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.label != self.label {
element.set_text(self.label.clone());
}
if prev.checked != self.checked {
element.set_checked(self.checked);
}
element
}
fn teardown(
&self,
(): &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
) {
fn teardown(&self, (): &mut Self::ViewState, ctx: &mut ViewCtx, element: Mut<Self::Element>) {
ctx.teardown_leaf(element);
}
@ -73,7 +68,7 @@ where
&self,
(): &mut Self::ViewState,
id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
debug_assert!(

View File

@ -1,18 +1,18 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use std::marker::PhantomData;
use crate::{
core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewId, ViewMarker, ViewPathTracker, ViewSequence,
},
AnyWidgetView, Pod, ViewCtx, WidgetView,
};
use masonry::{
widget::{self, WidgetMut},
Widget,
};
use xilem_core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewId, ViewMarker, ViewPathTracker, ViewSequence,
};
use crate::{AnyWidgetView, Pod, ViewCtx, WidgetView};
use std::marker::PhantomData;
pub use masonry::widget::{Axis, CrossAxisAlignment, FlexParams, MainAxisAlignment};
@ -118,13 +118,13 @@ where
(ctx.new_pod(widget), seq_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.axis != self.axis {
element.set_direction(self.axis);
}
@ -145,14 +145,13 @@ where
self.sequence
.seq_rebuild(&prev.sequence, view_state, ctx, &mut splice);
debug_assert!(splice.scratch.is_empty());
splice.element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
let mut splice = FlexSplice::new(element);
self.sequence.seq_teardown(view_state, ctx, &mut splice);
@ -162,7 +161,7 @@ where
fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
@ -210,8 +209,8 @@ impl SuperElement<FlexElement, ViewCtx> for FlexElement {
}
fn with_downcast_val<R>(
mut this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, FlexElement>) -> R,
mut this: Mut<Self>,
f: impl FnOnce(Mut<FlexElement>) -> R,
) -> (Self::Mut<'_>, R) {
let r = {
let parent = this.parent.reborrow_mut();
@ -231,9 +230,9 @@ impl<W: Widget> SuperElement<Pod<W>, ViewCtx> for FlexElement {
}
fn with_downcast_val<R>(
mut this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, Pod<W>>) -> R,
) -> (Mut<'_, Self>, R) {
mut this: Mut<Self>,
f: impl FnOnce(Mut<Pod<W>>) -> R,
) -> (Mut<Self>, R) {
let ret = {
let mut child = this
.parent
@ -276,7 +275,7 @@ impl ElementSplice<FlexElement> for FlexSplice<'_> {
ret
}
fn mutate<R>(&mut self, f: impl FnOnce(Mut<'_, FlexElement>) -> R) -> R {
fn mutate<R>(&mut self, f: impl FnOnce(Mut<FlexElement>) -> R) -> R {
let child = FlexElementMut {
parent: self.element.reborrow_mut(),
idx: self.idx,
@ -286,7 +285,7 @@ impl ElementSplice<FlexElement> for FlexSplice<'_> {
ret
}
fn delete<R>(&mut self, f: impl FnOnce(Mut<'_, FlexElement>) -> R) -> R {
fn delete<R>(&mut self, f: impl FnOnce(Mut<FlexElement>) -> R) -> R {
let ret = {
let child = FlexElementMut {
parent: self.element.reborrow_mut(),
@ -448,13 +447,13 @@ where
(FlexElement::Child(ctx.boxed_pod(pod), self.params), state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
{
if self.params != prev.params {
element
@ -468,14 +467,13 @@ where
self.view
.rebuild(&prev.view, view_state, ctx, child.downcast());
}
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
mut element: Mut<Self::Element>,
) {
let mut child = element
.parent
@ -487,7 +485,7 @@ where
fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
@ -524,28 +522,27 @@ impl<State, Action> View<State, Action, ViewCtx> for FlexSpacer {
(el, ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
_: &mut Self::ViewState,
_: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if self != prev {
match self {
FlexSpacer::Fixed(len) => element.parent.update_spacer_fixed(element.idx, *len),
FlexSpacer::Flex(flex) => element.parent.update_spacer_flex(element.idx, *flex),
};
}
element
}
fn teardown(&self, _: &mut Self::ViewState, _: &mut ViewCtx, _: Mut<'_, Self::Element>) {}
fn teardown(&self, _: &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {}
fn message(
&self,
_: &mut Self::ViewState,
_: &[xilem_core::ViewId],
_: &[ViewId],
_: DynMessage,
_: &mut State,
) -> MessageResult<Action> {
@ -651,20 +648,21 @@ where
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
match (prev, self) {
(AnyFlexChild::Item(prev), AnyFlexChild::Item(this)) => ctx
.with_id(ViewId::new(view_state.generation), |ctx| {
this.rebuild(prev, view_state.inner.as_mut().unwrap(), ctx, element)
}),
(AnyFlexChild::Item(prev), AnyFlexChild::Item(this)) => {
ctx.with_id(ViewId::new(view_state.generation), |ctx| {
this.rebuild(prev, view_state.inner.as_mut().unwrap(), ctx, element);
});
}
(AnyFlexChild::Spacer(prev), AnyFlexChild::Spacer(this)) => {
View::<(), (), ViewCtx>::rebuild(this, prev, &mut (), ctx, element)
View::<(), (), ViewCtx>::rebuild(this, prev, &mut (), ctx, element);
}
(AnyFlexChild::Item(prev_flex_item), AnyFlexChild::Spacer(new_spacer)) => {
// Run teardown with the old path
@ -697,7 +695,6 @@ where
}
FlexElement::Child(_, _) => unreachable!(),
};
element
}
(AnyFlexChild::Spacer(prev_spacer), AnyFlexChild::Item(new_flex_item)) => {
View::<(), (), ViewCtx>::teardown(
@ -723,8 +720,6 @@ where
} else {
unreachable!("We just created a new flex item, this should not be reached")
}
element
}
}
}
@ -733,7 +728,7 @@ where
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
match self {
AnyFlexChild::Item(flex_item) => {
@ -748,7 +743,7 @@ where
fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {

View File

@ -1,19 +1,19 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use std::marker::PhantomData;
use crate::{
core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewId, ViewMarker, ViewSequence,
},
Pod, ViewCtx, WidgetView,
};
use masonry::widget::GridParams;
use masonry::{
widget::{self, WidgetMut},
Widget,
};
use xilem_core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewMarker, ViewSequence,
};
use crate::{Pod, ViewCtx, WidgetView};
use std::marker::PhantomData;
pub fn grid<State, Action, Seq: GridSequence<State, Action>>(
sequence: Seq,
@ -77,13 +77,13 @@ where
(ctx.new_pod(widget), seq_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.height != self.height {
element.set_height(self.height);
}
@ -98,14 +98,13 @@ where
self.sequence
.seq_rebuild(&prev.sequence, view_state, ctx, &mut splice);
debug_assert!(splice.scratch.is_empty());
splice.element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
let mut splice = GridSplice::new(element);
self.sequence.seq_teardown(view_state, ctx, &mut splice);
@ -115,7 +114,7 @@ where
fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
@ -136,8 +135,8 @@ impl SuperElement<GridElement, ViewCtx> for GridElement {
}
fn with_downcast_val<R>(
mut this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, GridElement>) -> R,
mut this: Mut<Self>,
f: impl FnOnce(Mut<GridElement>) -> R,
) -> (Self::Mut<'_>, R) {
let r = {
let parent = this.parent.reborrow_mut();
@ -162,9 +161,9 @@ impl<W: Widget> SuperElement<Pod<W>, ViewCtx> for GridElement {
}
fn with_downcast_val<R>(
mut this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, Pod<W>>) -> R,
) -> (Mut<'_, Self>, R) {
mut this: Mut<Self>,
f: impl FnOnce(Mut<Pod<W>>) -> R,
) -> (Mut<Self>, R) {
let ret = {
let mut child = this
.parent
@ -204,7 +203,7 @@ impl ElementSplice<GridElement> for GridSplice<'_> {
self.idx += 1;
}
fn mutate<R>(&mut self, f: impl FnOnce(Mut<'_, GridElement>) -> R) -> R {
fn mutate<R>(&mut self, f: impl FnOnce(Mut<GridElement>) -> R) -> R {
let child = GridElementMut {
parent: self.element.reborrow_mut(),
idx: self.idx,
@ -218,7 +217,7 @@ impl ElementSplice<GridElement> for GridSplice<'_> {
self.idx += n;
}
fn delete<R>(&mut self, f: impl FnOnce(Mut<'_, GridElement>) -> R) -> R {
fn delete<R>(&mut self, f: impl FnOnce(Mut<GridElement>) -> R) -> R {
let ret = {
let child = GridElementMut {
parent: self.element.reborrow_mut(),
@ -364,13 +363,13 @@ where
(GridElement::Child(ctx.boxed_pod(pod), self.params), state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
{
if self.params != prev.params {
element
@ -384,14 +383,13 @@ where
self.view
.rebuild(&prev.view, view_state, ctx, child.downcast());
}
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
mut element: Mut<Self::Element>,
) {
let mut child = element
.parent
@ -403,7 +401,7 @@ where
fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {

View File

@ -3,10 +3,11 @@
//! The bitmap image widget.
use crate::{
core::{DynMessage, Mut, ViewMarker},
MessageResult, Pod, View, ViewCtx, ViewId,
};
use masonry::widget::{self, ObjectFit};
use xilem_core::{Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};
/// Displays the bitmap `image`.
///
@ -53,29 +54,28 @@ impl<State, Action> View<State, Action, ViewCtx> for Image {
(ctx.new_pod(widget::Image::new(self.image.clone())), ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.object_fit != self.object_fit {
element.set_fit_mode(self.object_fit);
}
if prev.image != self.image {
element.set_image_data(self.image.clone());
}
element
}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<'_, Self::Element>) {}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {}
fn message(
&self,
(): &mut Self::ViewState,
_: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
_: &mut State,
) -> MessageResult<Action> {
tracing::error!("Message arrived in Label::message, but Label doesn't consume any messages, this is a bug");

View File

@ -1,10 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, ViewMarker},
Color, MessageResult, Pod, TextAlignment, TextWeight, View, ViewCtx, ViewId,
};
use masonry::{text::TextBrush, widget, ArcStr};
use xilem_core::{Mut, ViewMarker};
use crate::{Color, MessageResult, Pod, TextAlignment, TextWeight, View, ViewCtx, ViewId};
pub fn label(label: impl Into<ArcStr>) -> Label {
Label {
@ -66,13 +67,13 @@ impl<State, Action> View<State, Action, ViewCtx> for Label {
(widget_pod, ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.label != self.label {
element.set_text(self.label.clone());
}
@ -88,16 +89,15 @@ impl<State, Action> View<State, Action, ViewCtx> for Label {
if prev.weight != self.weight {
element.set_weight(self.weight);
}
element
}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<'_, Self::Element>) {}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {}
fn message(
&self,
(): &mut Self::ViewState,
_id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
_app_state: &mut State,
) -> crate::MessageResult<Action> {
tracing::error!("Message arrived in Label::message, but Label doesn't consume any messages, this is a bug");

View File

@ -1,12 +1,12 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use std::marker::PhantomData;
use crate::{
core::{DynMessage, Mut, ViewMarker},
MessageResult, Pod, View, ViewCtx, ViewId, WidgetView,
};
use masonry::widget;
use xilem_core::{Mut, ViewMarker};
use crate::{Pod, View, ViewCtx, ViewId, WidgetView};
use std::marker::PhantomData;
/// A view which puts `child` into a scrollable region.
///
@ -44,24 +44,23 @@ where
(widget_pod, child_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
let child_element = element.child_mut();
self.child
.rebuild(&prev.child, view_state, ctx, child_element);
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
mut element: Mut<Self::Element>,
) {
let child_element = element.child_mut();
self.child.teardown(view_state, ctx, child_element);
@ -71,9 +70,9 @@ where
&self,
view_state: &mut Self::ViewState,
id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
app_state: &mut State,
) -> crate::MessageResult<Action> {
) -> MessageResult<Action> {
self.child.message(view_state, id_path, message, app_state)
}
}

View File

@ -1,10 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, ViewMarker},
MessageResult, Pod, View, ViewCtx, ViewId,
};
use masonry::widget;
use xilem_core::{Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};
pub fn progress_bar(progress: Option<f64>) -> ProgressBar {
ProgressBar { progress }
@ -25,25 +26,19 @@ impl<State, Action> View<State, Action, ViewCtx> for ProgressBar {
})
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.progress != self.progress {
element.set_progress(self.progress);
}
element
}
fn teardown(
&self,
(): &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
) {
fn teardown(&self, (): &mut Self::ViewState, ctx: &mut ViewCtx, element: Mut<Self::Element>) {
ctx.teardown_leaf(element);
}
@ -51,7 +46,7 @@ impl<State, Action> View<State, Action, ViewCtx> for ProgressBar {
&self,
(): &mut Self::ViewState,
_id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
_app_state: &mut State,
) -> MessageResult<Action> {
tracing::error!("Message arrived in ProgressBar::message, but ProgressBar doesn't consume any messages, this is a bug");

View File

@ -1,10 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, ViewMarker},
Color, MessageResult, Pod, TextAlignment, View, ViewCtx, ViewId,
};
use masonry::{text::TextBrush, widget, ArcStr};
use xilem_core::{Mut, ViewMarker};
use crate::{Color, MessageResult, Pod, TextAlignment, View, ViewCtx, ViewId};
pub fn prose(content: impl Into<ArcStr>) -> Prose {
Prose {
@ -59,13 +60,13 @@ impl<State, Action> View<State, Action, ViewCtx> for Prose {
(widget_pod, ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.content != self.content {
element.set_text(self.content.clone());
}
@ -78,16 +79,15 @@ impl<State, Action> View<State, Action, ViewCtx> for Prose {
if prev.text_size != self.text_size {
element.set_text_size(self.text_size);
}
element
}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<'_, Self::Element>) {}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {}
fn message(
&self,
_view_state: &mut Self::ViewState,
_id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
_app_state: &mut State,
) -> crate::MessageResult<Action> {
tracing::error!("Message arrived in Prose::message, but Prose doesn't consume any messages, this is a bug");

View File

@ -6,10 +6,9 @@ use std::marker::PhantomData;
use masonry::widget;
use vello::kurbo::RoundedRectRadii;
use vello::peniko::{Brush, Color};
use xilem_core::ViewMarker;
use crate::{
core::{Mut, View, ViewId},
core::{DynMessage, Mut, View, ViewId, ViewMarker},
Pod, ViewCtx, WidgetView,
};
@ -138,13 +137,13 @@ where
(ctx.new_pod(widget), child_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if self.width != prev.width {
match self.width {
Some(width) => element.set_width(width),
@ -179,14 +178,13 @@ where
self.inner
.rebuild(&prev.inner, view_state, ctx, child.downcast());
}
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
mut element: Mut<Self::Element>,
) {
let mut child = element
.child_mut()
@ -198,7 +196,7 @@ where
&self,
view_state: &mut Self::ViewState,
id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
app_state: &mut State,
) -> crate::MessageResult<Action> {
self.inner.message(view_state, id_path, message, app_state)

View File

@ -1,10 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, ViewMarker},
MessageResult, Pod, View, ViewCtx, ViewId,
};
use masonry::{widget, Color};
use xilem_core::{Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};
/// An indefinite spinner.
///
@ -59,29 +60,28 @@ impl<State, Action> View<State, Action, ViewCtx> for Spinner {
(ctx.new_pod(widget::Spinner::new()), ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.color != self.color {
match self.color {
Some(color) => element.set_color(color),
None => element.reset_color(),
};
}
element
}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<'_, Self::Element>) {}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {}
fn message(
&self,
(): &mut Self::ViewState,
_: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
_: &mut State,
) -> MessageResult<Action> {
tracing::error!("Message arrived in Label::message, but Label doesn't consume any messages, this is a bug");

View File

@ -1,14 +1,15 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use std::{future::Future, marker::PhantomData, sync::Arc};
use tokio::task::JoinHandle;
use xilem_core::{
DynMessage, Message, MessageProxy, NoElement, View, ViewId, ViewMarker, ViewPathTracker,
use crate::{
core::{
DynMessage, Message, MessageProxy, MessageResult, Mut, NoElement, View, ViewId, ViewMarker,
ViewPathTracker,
},
ViewCtx,
};
use crate::ViewCtx;
use std::{future::Future, marker::PhantomData, sync::Arc};
use tokio::task::JoinHandle;
/// Launch a task which will run until the view is no longer in the tree.
/// `init_future` is given a [`MessageProxy`], which it will store in the future it returns.
@ -88,37 +89,26 @@ where
(NoElement, handle)
}
fn rebuild<'el>(
&self,
_: &Self,
_: &mut Self::ViewState,
_: &mut ViewCtx,
(): xilem_core::Mut<'el, Self::Element>,
) -> xilem_core::Mut<'el, Self::Element> {
fn rebuild(&self, _: &Self, _: &mut Self::ViewState, _: &mut ViewCtx, (): Mut<Self::Element>) {
// Nothing to do
}
fn teardown(
&self,
join_handle: &mut Self::ViewState,
_: &mut ViewCtx,
_: xilem_core::Mut<'_, Self::Element>,
) {
fn teardown(&self, join_handle: &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {
join_handle.abort();
}
fn message(
&self,
_: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> xilem_core::MessageResult<Action> {
) -> MessageResult<Action> {
debug_assert!(
id_path.is_empty(),
"id path should be empty in Task::message"
);
let message = message.downcast::<M>().unwrap();
xilem_core::MessageResult::Action((self.on_event)(app_state, *message))
MessageResult::Action((self.on_event)(app_state, *message))
}
}

View File

@ -1,10 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, View, ViewMarker},
Color, MessageResult, Pod, TextAlignment, ViewCtx, ViewId,
};
use masonry::{text::TextBrush, widget};
use xilem_core::{Mut, View, ViewMarker};
use crate::{Color, MessageResult, Pod, TextAlignment, ViewCtx, ViewId};
// FIXME - A major problem of the current approach (always setting the textbox contents)
// is that if the user forgets to hook up the modify the state's contents in the callback,
@ -78,13 +79,13 @@ impl<State: 'static, Action: 'static> View<State, Action, ViewCtx> for Textbox<S
})
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
_: &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
// Unlike the other properties, we don't compare to the previous value;
// instead, we compare directly to the element's text. This is to handle
// cases like "Previous data says contents is 'fooba', user presses 'r',
@ -102,15 +103,9 @@ impl<State: 'static, Action: 'static> View<State, Action, ViewCtx> for Textbox<S
if prev.alignment != self.alignment {
element.set_alignment(self.alignment);
}
element
}
fn teardown(
&self,
_: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
) {
fn teardown(&self, _: &mut Self::ViewState, ctx: &mut ViewCtx, element: Mut<Self::Element>) {
ctx.teardown_leaf(element);
}
@ -118,7 +113,7 @@ impl<State: 'static, Action: 'static> View<State, Action, ViewCtx> for Textbox<S
&self,
_: &mut Self::ViewState,
id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
app_state: &mut State,
) -> MessageResult<Action> {
debug_assert!(

View File

@ -1,6 +1,10 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{DynMessage, Mut, ViewMarker},
Color, MessageResult, Pod, TextAlignment, View, ViewCtx, ViewId,
};
use masonry::{
parley::{
fontique::Weight,
@ -9,9 +13,6 @@ use masonry::{
text::TextBrush,
widget, ArcStr,
};
use xilem_core::{Mut, ViewMarker};
use crate::{Color, MessageResult, Pod, TextAlignment, View, ViewCtx, ViewId};
/// A view for displaying non-editable text, with a variable [weight](masonry::parley::style::FontWeight).
pub fn variable_label(label: impl Into<ArcStr>) -> VariableLabel {
@ -113,13 +114,13 @@ impl<State, Action> View<State, Action, ViewCtx> for VariableLabel {
(widget_pod, ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
if prev.label != self.label {
element.set_text(self.label.clone());
}
@ -140,16 +141,15 @@ impl<State, Action> View<State, Action, ViewCtx> for VariableLabel {
if !fonts_eq {
element.set_font(self.font);
}
element
}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<'_, Self::Element>) {}
fn teardown(&self, (): &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {}
fn message(
&self,
(): &mut Self::ViewState,
_id_path: &[ViewId],
message: xilem_core::DynMessage,
message: DynMessage,
_app_state: &mut State,
) -> crate::MessageResult<Action> {
tracing::error!("Message arrived in Label::message, but Label doesn't consume any messages, this is a bug");

View File

@ -1,24 +1,26 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{
DynMessage, Message, MessageProxy, MessageResult, Mut, NoElement, View, ViewId, ViewMarker,
ViewPathTracker,
},
ViewCtx,
};
use std::{future::Future, marker::PhantomData, sync::Arc};
use tokio::{
sync::mpsc::{UnboundedReceiver, UnboundedSender},
task::JoinHandle,
};
use xilem_core::{
DynMessage, Message, MessageProxy, NoElement, View, ViewId, ViewMarker, ViewPathTracker,
};
use crate::ViewCtx;
/// Launch a task which will run until the view is no longer in the tree.
///
/// `init_future` is given a [`MessageProxy`], which it will store in the future it returns.
/// This `MessageProxy` can be used to send a message to `on_event`, which can then update
/// the app's state.
///
/// For exampe, this can be used with the time functions in [`crate::tokio::time`].
/// For example, this can be used with the time functions in [`crate::tokio::time`].
///
/// Note that this task will not be updated if the view is rebuilt, so `init_future`
/// cannot capture.
@ -114,40 +116,35 @@ where
(NoElement, WorkerState { handle, sender: tx })
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
_: &mut ViewCtx,
(): xilem_core::Mut<'el, Self::Element>,
) -> xilem_core::Mut<'el, Self::Element> {
(): Mut<Self::Element>,
) {
if self.value != prev.value {
// TODO: Error handling
drop(view_state.sender.send(self.value.clone()));
}
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
_: &mut ViewCtx,
_: xilem_core::Mut<'_, Self::Element>,
) {
fn teardown(&self, view_state: &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {
view_state.handle.abort();
}
fn message(
&self,
_: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> xilem_core::MessageResult<Action> {
) -> MessageResult<Action> {
debug_assert!(
id_path.is_empty(),
"id path should be empty in Task::message"
);
let message = message.downcast::<M>().unwrap();
xilem_core::MessageResult::Action((self.on_response)(app_state, *message))
MessageResult::Action((self.on_response)(app_state, *message))
}
}

View File

@ -105,7 +105,7 @@ impl SuperElement<FsPath, ViewCtx> for FsPath {
fn with_downcast_val<R>(
this: Self::Mut<'_>,
f: impl FnOnce(Mut<'_, FsPath>) -> R,
f: impl FnOnce(Mut<FsPath>) -> R,
) -> (Self::Mut<'_>, R) {
let ret = f(this);
(this, ret)
@ -158,13 +158,13 @@ impl<State, Action> View<State, Action, ViewCtx> for File {
(path.into(), ())
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
_view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
if prev.name != self.name {
let new_path = ctx.current_folder_path.join(&*self.name);
let _ = std::fs::rename(&*element, &new_path);
@ -173,14 +173,13 @@ impl<State, Action> View<State, Action, ViewCtx> for File {
if self.contents != prev.contents {
let _ = std::fs::write(&*element, self.contents.as_bytes());
}
element
}
fn teardown(
&self,
_view_state: &mut Self::ViewState,
_ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
let _ = std::fs::remove_file(element);
}

View File

@ -59,22 +59,21 @@ impl<State, Action> View<State, Action, ViewCtx> for Button {
)
}
fn rebuild<'el>(
fn rebuild(
&self,
_prev: &Self,
_view_state: &mut Self::ViewState,
_ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
_element: Mut<Self::Element>,
) {
// Nothing to do
element
}
fn teardown(
&self,
_view_state: &mut Self::ViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Self::Element>,
_element: Mut<Self::Element>,
) {
// Nothing to do
}

View File

@ -35,13 +35,13 @@ pub trait AnyView<State, Action, Context, Element: ViewElement, Message = DynMes
fn dyn_build(&self, ctx: &mut Context) -> (Element, AnyViewState);
/// Type erased [`View::rebuild`].
fn dyn_rebuild<'el>(
fn dyn_rebuild(
&self,
dyn_state: &mut AnyViewState,
ctx: &mut Context,
prev: &dyn AnyView<State, Action, Context, Element, Message>,
element: Element::Mut<'el>,
) -> Element::Mut<'el>;
element: Element::Mut<'_>,
);
/// Type erased [`View::teardown`].
///
@ -88,13 +88,13 @@ where
)
}
fn dyn_rebuild<'el>(
fn dyn_rebuild(
&self,
dyn_state: &mut AnyViewState,
ctx: &mut Context,
prev: &dyn AnyView<State, Action, Context, DynamicElement, Message>,
mut element: DynamicElement::Mut<'el>,
) -> DynamicElement::Mut<'el> {
mut element: DynamicElement::Mut<'_>,
) {
if let Some(prev) = prev.as_any().downcast_ref() {
// If we were previously of this type, then do a normal rebuild
DynamicElement::with_downcast(element, |element| {
@ -106,7 +106,7 @@ where
ctx.with_id(ViewId::new(dyn_state.generation), move |ctx| {
self.rebuild(prev, state, ctx, element);
});
})
});
} else {
// Otherwise, teardown the old element, then replace the value
// Note that we need to use `dyn_teardown` here, because `prev`
@ -120,7 +120,7 @@ where
let (new_element, view_state) =
ctx.with_id(ViewId::new(dyn_state.generation), |ctx| self.build(ctx));
dyn_state.inner_state = Box::new(view_state);
DynamicElement::replace_inner(element, new_element)
DynamicElement::replace_inner(element, new_element);
}
}
fn dyn_teardown<'el>(
@ -194,21 +194,21 @@ where
self.dyn_build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.dyn_rebuild(view_state, ctx, prev, element)
element: Mut<Self::Element>,
) {
self.dyn_rebuild(view_state, ctx, prev, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.dyn_teardown(view_state, ctx, element);
}
@ -248,21 +248,21 @@ where
self.dyn_build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.dyn_rebuild(view_state, ctx, prev, element)
element: Mut<Self::Element>,
) {
self.dyn_rebuild(view_state, ctx, prev, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.dyn_teardown(view_state, ctx, element);
}
@ -300,21 +300,21 @@ where
self.dyn_build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.dyn_rebuild(view_state, ctx, prev, element)
element: Mut<Self::Element>,
) {
self.dyn_rebuild(view_state, ctx, prev, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.dyn_teardown(view_state, ctx, element);
}
@ -352,21 +352,21 @@ where
self.dyn_build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.dyn_rebuild(view_state, ctx, prev, element)
element: Mut<Self::Element>,
) {
self.dyn_rebuild(view_state, ctx, prev, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.dyn_teardown(view_state, ctx, element);
}

View File

@ -58,7 +58,7 @@ where
/// You can safely use this methods in contexts where it is known that the
///
/// If you need to return a value, see [`with_downcast_val`](SuperElement::with_downcast_val).
fn with_downcast(this: Mut<'_, Self>, f: impl FnOnce(Mut<'_, Child>)) -> Mut<'_, Self> {
fn with_downcast(this: Mut<Self>, f: impl FnOnce(Mut<Child>)) -> Mut<Self> {
let (this, ()) = Self::with_downcast_val(this, f);
this
}
@ -68,10 +68,8 @@ where
/// `Self::upcast`.
///
/// If you don't need to return a value, see [`with_downcast`](SuperElement::with_downcast).
fn with_downcast_val<R>(
this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, Child>) -> R,
) -> (Self::Mut<'_>, R);
fn with_downcast_val<R>(this: Mut<Self>, f: impl FnOnce(Mut<Child>) -> R)
-> (Self::Mut<'_>, R);
}
/// An element which can be used for an [`AnyView`](crate::AnyView) containing `Child`.
@ -101,8 +99,8 @@ impl<Context> SuperElement<NoElement, Context> for NoElement {
}
fn with_downcast_val<R>(
this: Mut<'_, Self>,
f: impl FnOnce(Mut<'_, NoElement>) -> R,
this: Mut<Self>,
f: impl FnOnce(Mut<NoElement>) -> R,
) -> (Self::Mut<'_>, R) {
((), f(this))
}

View File

@ -74,17 +74,13 @@ pub trait View<State, Action, Context: ViewPathTracker, Message = DynMessage>:
fn build(&self, ctx: &mut Context) -> (Self::Element, Self::ViewState);
/// Update `element` based on the difference between `self` and `prev`.
///
/// This returns `element`, to allow parent views to modify the element after this `rebuild` has
/// completed. This returning is needed as some reference types do not allow reborrowing,
/// without unwieldy boilerplate.
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element>;
element: Mut<Self::Element>,
);
/// Handle `element` being removed from the tree.
///
@ -97,7 +93,7 @@ pub trait View<State, Action, Context: ViewPathTracker, Message = DynMessage>:
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
);
/// Route `message` to `id_path`, if that is still a valid path.
@ -176,21 +172,21 @@ where
self.deref().build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.deref().rebuild(prev, view_state, ctx, element)
element: Mut<Self::Element>,
) {
self.deref().rebuild(prev, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.deref().teardown(view_state, ctx, element);
}
@ -233,19 +229,17 @@ where
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
// If this is the same value, or no rebuild was forced, there's no need to rebuild
if core::mem::take(&mut view_state.dirty) || !Arc::ptr_eq(self, prev) {
self.deref()
.rebuild(prev, &mut view_state.view_state, ctx, element)
} else {
// If this is the same value, or no rebuild was forced, there's no need to rebuild
element
.rebuild(prev, &mut view_state.view_state, ctx, element);
}
}
@ -253,7 +247,7 @@ where
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.deref()
.teardown(&mut view_state.view_state, ctx, element);

View File

@ -174,21 +174,21 @@ where
self.child.build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.child.rebuild(&prev.child, view_state, ctx, element)
element: Mut<Self::Element>,
) {
self.child.rebuild(&prev.child, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.child.teardown(view_state, ctx, element);
}

View File

@ -47,16 +47,16 @@ where
(element, (active_state, alongside_state))
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(active_state, alongside_state): &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
let element = ctx.with_id(ViewId::new(0), |ctx| {
element: Mut<Self::Element>,
) {
ctx.with_id(ViewId::new(0), |ctx| {
self.active_view
.rebuild(&prev.active_view, active_state, ctx, element)
.rebuild(&prev.active_view, active_state, ctx, element);
});
ctx.with_id(ViewId::new(1), |ctx| {
self.alongside_view.seq_rebuild(
@ -66,14 +66,13 @@ where
&mut NoElements,
);
});
element
}
fn teardown(
&self,
(active_state, alongside_state): &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
ctx.with_id(ViewId::new(0), |ctx| {
self.alongside_view

View File

@ -88,21 +88,21 @@ where
self.child.build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.child.rebuild(&prev.child, view_state, ctx, element)
element: Mut<Self::Element>,
) {
self.child.rebuild(&prev.child, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.child.teardown(view_state, ctx, element);
}

View File

@ -135,21 +135,21 @@ where
self.child.build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
self.child.rebuild(&prev.child, view_state, ctx, element)
element: Mut<Self::Element>,
) {
self.child.rebuild(&prev.child, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.child.teardown(view_state, ctx, element);
}

View File

@ -90,20 +90,17 @@ where
(element, memoize_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
if core::mem::take(&mut view_state.dirty) || prev.data != self.data {
let view = (self.init_view)(&self.data);
let el = view.rebuild(&view_state.view, &mut view_state.view_state, ctx, element);
view.rebuild(&view_state.view, &mut view_state.view_state, ctx, element);
view_state.view = view;
el
} else {
element
}
}
@ -128,7 +125,7 @@ where
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
view_state
.view
@ -198,23 +195,19 @@ where
(element, memoize_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
_prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: crate::Mut<'el, Self::Element>,
) -> crate::Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
if core::mem::take(&mut view_state.dirty) {
let view = (self.init_view)();
let element =
view_state
.view
.rebuild(&view_state.view, &mut view_state.view_state, ctx, element);
view_state
.view
.rebuild(&view_state.view, &mut view_state.view_state, ctx, element);
view_state.view = view;
element
} else {
element
}
}
@ -222,7 +215,7 @@ where
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: crate::Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
view_state
.view

View File

@ -6,8 +6,9 @@
use crate::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker, ViewPathTracker};
use hidden::OneOfState;
/// This trait allows, specifying a type as `ViewElement`, which should never be constructed or used,
/// but allows downstream implementations to adjust the behaviour of [`PhantomElementCtx::PhantomElement`],
/// This trait allows, specifying a type as `ViewElement`, which should never be constructed or used.
///
/// But it allows downstream implementations to adjust the behaviour of [`PhantomElementCtx::PhantomElement`],
/// e.g. adding trait impls, or a wrapper type, to support features that would depend on the `ViewElement` implementing certain traits, or being a specific type.
///
/// It's necessary to please the type-checker
@ -102,39 +103,39 @@ pub trait OneOfCtx<
/// Casts the view element `elem` to the `OneOf::A` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_a(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, A>));
fn with_downcast_a(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<A>));
/// Casts the view element `elem` to the `OneOf::B` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_b(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, B>));
fn with_downcast_b(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<B>));
/// Casts the view element `elem` to the `OneOf::C` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_c(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, C>));
fn with_downcast_c(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<C>));
/// Casts the view element `elem` to the `OneOf::D` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_d(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, D>));
fn with_downcast_d(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<D>));
/// Casts the view element `elem` to the `OneOf::E` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_e(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, E>));
fn with_downcast_e(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<E>));
/// Casts the view element `elem` to the `OneOf::F` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_f(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, F>));
fn with_downcast_f(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<F>));
/// Casts the view element `elem` to the `OneOf::G` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_g(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, G>));
fn with_downcast_g(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<G>));
/// Casts the view element `elem` to the `OneOf::H` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_h(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, H>));
fn with_downcast_h(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<H>));
/// Casts the view element `elem` to the `OneOf::I` variant.
/// `f` needs to be invoked with that inner `ViewElement`
fn with_downcast_i(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, I>));
fn with_downcast_i(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<I>));
/// Creates the wrapping element, this is used in `View::build` to wrap the inner view element variant
fn upcast_one_of_element(
@ -144,7 +145,7 @@ pub trait OneOfCtx<
/// When the variant of the inner view element has changed, the wrapping element needs to be updated, this is used in `View::rebuild`
fn update_one_of_element_mut(
elem_mut: &mut Mut<'_, Self::OneOfElement>,
elem_mut: &mut Mut<Self::OneOfElement>,
new_elem: OneOf<A, B, C, D, E, F, G, H, I>,
);
}
@ -245,13 +246,13 @@ where
}
#[doc(hidden)]
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
let id = ViewId::new(view_state.generation);
// If both elements are of the same type, do a simple rebuild
match (self, prev, &mut view_state.inner_state) {
@ -261,7 +262,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::B(this), OneOf::B(prev), OneOf::B(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -269,7 +270,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::C(this), OneOf::C(prev), OneOf::C(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -277,7 +278,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::D(this), OneOf::D(prev), OneOf::D(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -285,7 +286,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::E(this), OneOf::E(prev), OneOf::E(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -293,7 +294,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::F(this), OneOf::F(prev), OneOf::F(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -301,7 +302,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::G(this), OneOf::G(prev), OneOf::G(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -309,7 +310,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::H(this), OneOf::H(prev), OneOf::H(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -317,7 +318,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
(OneOf::I(this), OneOf::I(prev), OneOf::I(ref mut state)) => {
ctx.with_id(id, |ctx| {
@ -325,7 +326,7 @@ where
this.rebuild(prev, state, ctx, element);
});
});
return element;
return;
}
_ => (),
}
@ -425,8 +426,6 @@ where
});
view_state.inner_state = state;
Context::update_one_of_element_mut(&mut element, new_element);
element
}
#[doc(hidden)]
@ -434,7 +433,7 @@ where
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
mut element: Mut<'_, Self::Element>,
mut element: Mut<Self::Element>,
) {
ctx.with_id(ViewId::new(view_state.generation), |ctx| {
match (self, &mut view_state.inner_state) {
@ -540,22 +539,17 @@ mod hidden {
match *self {}
}
fn rebuild<'el>(
fn rebuild(
&self,
_: &Self,
_: &mut Self::ViewState,
_: &mut Context,
_: crate::Mut<'el, Self::Element>,
) -> crate::Mut<'el, Self::Element> {
_: crate::Mut<Self::Element>,
) {
match *self {}
}
fn teardown(
&self,
_: &mut Self::ViewState,
_: &mut Context,
_: crate::Mut<'_, Self::Element>,
) {
fn teardown(&self, _: &mut Self::ViewState, _: &mut Context, _: crate::Mut<Self::Element>) {
match *self {}
}

View File

@ -6,6 +6,7 @@ use crate::{
};
/// This trait provides a way to add [`View`] implementations for types that would be restricted otherwise by the orphan rules.
///
/// Every type that can be supported with this trait, needs a concrete `View` implementation in `xilem_core`, possibly feature-gated.
pub trait OrphanView<V, State, Action, Message = DynMessage>: ViewPathTracker + Sized {
/// See [`View::Element`]
@ -17,20 +18,20 @@ pub trait OrphanView<V, State, Action, Message = DynMessage>: ViewPathTracker +
fn orphan_build(view: &V, ctx: &mut Self) -> (Self::OrphanElement, Self::OrphanViewState);
/// See [`View::rebuild`]
fn orphan_rebuild<'el>(
fn orphan_rebuild(
new: &V,
prev: &V,
view_state: &mut Self::OrphanViewState,
ctx: &mut Self,
element: Mut<'el, Self::OrphanElement>,
) -> Mut<'el, Self::OrphanElement>;
element: Mut<Self::OrphanElement>,
);
/// See [`View::teardown`]
fn orphan_teardown(
view: &V,
view_state: &mut Self::OrphanViewState,
ctx: &mut Self,
element: Mut<'_, Self::OrphanElement>,
element: Mut<Self::OrphanElement>,
);
/// See [`View::message`]
@ -59,21 +60,21 @@ macro_rules! impl_orphan_view_for {
Context::orphan_build(self, ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
Context::orphan_rebuild(self, prev, view_state, ctx, element)
element: Mut<Self::Element>,
) {
Context::orphan_rebuild(self, prev, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut Context,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
Context::orphan_teardown(self, view_state, ctx, element);
}

View File

@ -92,22 +92,17 @@ where
(NoElement, ())
}
fn rebuild<'el>(
fn rebuild(
&self,
_: &Self,
(): &mut Self::ViewState,
_: &mut Context,
(): crate::Mut<'el, Self::Element>,
) -> crate::Mut<'el, Self::Element> {
(): crate::Mut<Self::Element>,
) {
// Nothing to do
}
fn teardown(
&self,
(): &mut Self::ViewState,
_: &mut Context,
_: crate::Mut<'_, Self::Element>,
) {
fn teardown(&self, (): &mut Self::ViewState, _: &mut Context, _: crate::Mut<Self::Element>) {
// Nothing to do
}

View File

@ -103,13 +103,13 @@ where
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut TestCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
assert_eq!(&*element.view_path, ctx.view_path());
element.operations.push(Operation::Rebuild {
from: prev.id,
@ -122,14 +122,13 @@ where
};
self.seq
.seq_rebuild(&prev.seq, &mut view_state.0, ctx, &mut elements);
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut TestCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
assert_eq!(&*element.view_path, ctx.view_path());
element.operations.push(Operation::Teardown(self.id));
@ -170,27 +169,21 @@ impl<const N: u32> View<(), Action, TestCtx> for OperationView<N> {
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
_: &mut Self::ViewState,
ctx: &mut TestCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
assert_eq!(&*element.view_path, ctx.view_path());
element.operations.push(Operation::Rebuild {
from: prev.0,
to: self.0,
});
element
}
fn teardown(
&self,
_: &mut Self::ViewState,
ctx: &mut TestCtx,
element: Mut<'_, Self::Element>,
) {
fn teardown(&self, _: &mut Self::ViewState, ctx: &mut TestCtx, element: Mut<Self::Element>) {
assert_eq!(&*element.view_path, ctx.view_path());
element.operations.push(Operation::Teardown(self.0));
}
@ -217,7 +210,7 @@ impl SuperElement<TestElement, TestCtx> for TestElement {
fn with_downcast_val<R>(
this: Self::Mut<'_>,
f: impl FnOnce(Mut<'_, TestElement>) -> R,
f: impl FnOnce(Mut<TestElement>) -> R,
) -> (Self::Mut<'_>, R) {
let ret = f(this);
(this, ret)
@ -275,7 +268,7 @@ impl<'a> ElementSplice<TestElement> for SeqTracker<'a> {
fn insert(&mut self, element: TestElement) {
self.inner.active.push(element);
}
fn mutate<R>(&mut self, f: impl FnOnce(Mut<'_, TestElement>) -> R) -> R {
fn mutate<R>(&mut self, f: impl FnOnce(Mut<TestElement>) -> R) -> R {
let ix = self.ix;
self.ix += 1;
f(&mut self.inner.active[ix])
@ -283,7 +276,7 @@ impl<'a> ElementSplice<TestElement> for SeqTracker<'a> {
fn skip(&mut self, n: usize) {
self.ix += n;
}
fn delete<R>(&mut self, f: impl FnOnce(Mut<'_, TestElement>) -> R) -> R {
fn delete<R>(&mut self, f: impl FnOnce(Mut<TestElement>) -> R) -> R {
let ret = f(&mut self.inner.active[self.ix]);
let val = self.inner.active.remove(self.ix);
self.inner.deleted.push((self.ix, val));

View File

@ -62,7 +62,7 @@ impl
}
fn update_one_of_element_mut(
elem_mut: &mut Mut<'_, Self::OneOfElement>,
elem_mut: &mut Mut<Self::OneOfElement>,
new_elem: OneOf<
TestElement,
TestElement,
@ -89,66 +89,60 @@ impl
}
}
fn with_downcast_a(
elem: &mut Mut<'_, Self::OneOfElement>,
f: impl FnOnce(Mut<'_, TestElement>),
) {
fn with_downcast_a(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<TestElement>)) {
f(elem);
}
fn with_downcast_b(
elem: &mut Mut<'_, Self::OneOfElement>,
f: impl FnOnce(Mut<'_, TestElement>),
) {
fn with_downcast_b(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<TestElement>)) {
f(elem);
}
// when one of the following would be invoked, it would be an error in the impl of `OneOfN`
fn with_downcast_c(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}
fn with_downcast_d(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}
fn with_downcast_e(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}
fn with_downcast_f(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}
fn with_downcast_g(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}
fn with_downcast_h(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}
fn with_downcast_i(
_elem: &mut Mut<'_, Self::OneOfElement>,
_f: impl FnOnce(Mut<'_, <Self as PhantomElementCtx>::PhantomElement>),
_elem: &mut Mut<Self::OneOfElement>,
_f: impl FnOnce(Mut<<Self as PhantomElementCtx>::PhantomElement>),
) {
unreachable!()
}

View File

@ -6,7 +6,7 @@
//!
//! This is an integration test so that it can use the infrastructure in [`common`].
use xilem_core::{DynMessage, MessageResult, Mut, OrphanView, View, ViewPathTracker};
use xilem_core::{DynMessage, MessageResult, Mut, OrphanView, View, ViewId, ViewPathTracker};
mod common;
use common::*;
@ -33,13 +33,13 @@ impl<State, Action> OrphanView<&'static str, State, Action> for TestCtx {
)
}
fn orphan_rebuild<'el>(
fn orphan_rebuild(
new: &&'static str,
prev: &&'static str,
generation: &mut Self::OrphanViewState,
ctx: &mut Self,
element: Mut<'el, Self::OrphanElement>,
) -> Mut<'el, Self::OrphanElement> {
element: Mut<Self::OrphanElement>,
) {
assert_eq!(&*element.view_path, ctx.view_path());
let old_generation = *generation;
@ -52,14 +52,13 @@ impl<State, Action> OrphanView<&'static str, State, Action> for TestCtx {
from: old_generation,
to: *generation,
});
element
}
fn orphan_teardown(
_view: &&'static str,
generation: &mut Self::OrphanViewState,
_ctx: &mut Self,
element: Mut<'_, Self::OrphanElement>,
element: Mut<Self::OrphanElement>,
) {
element.operations.push(Operation::Teardown(*generation));
}
@ -67,7 +66,7 @@ impl<State, Action> OrphanView<&'static str, State, Action> for TestCtx {
fn orphan_message(
_view: &&'static str,
_view_state: &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> MessageResult<Action, DynMessage> {
@ -83,9 +82,8 @@ fn str_as_orphan_view() {
let view2 = "This string is now an updated view";
assert_eq!(element.operations[0], Operation::Build(0));
let element =
View::<(), (), TestCtx>::rebuild(&view1, &view2, &mut generation, &mut ctx, &mut element);
View::<(), (), TestCtx>::rebuild(&view1, &view2, &mut generation, &mut ctx, &mut element);
assert_eq!(element.operations[1], Operation::Rebuild { from: 0, to: 1 });
View::<(), (), TestCtx>::teardown(&view1, &mut generation, &mut ctx, element);
View::<(), (), TestCtx>::teardown(&view1, &mut generation, &mut ctx, &mut element);
assert_eq!(element.operations[2], Operation::Teardown(1));
}

View File

@ -3,9 +3,10 @@
use std::marker::PhantomData;
use xilem_core::{MessageResult, Mut, View, ViewId, ViewMarker};
use crate::{DomNode, DomView, DynMessage, ViewCtx};
use crate::{
core::{MessageResult, Mut, View, ViewId, ViewMarker},
DomNode, DomView, DynMessage, ViewCtx,
};
/// Invokes the `callback` after the inner `element` [`DomView`] was created.
/// See [`after_build`] for more details.
@ -125,22 +126,22 @@ where
(el, view_state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
self.element
.rebuild(&prev.element, view_state, ctx, element)
.rebuild(&prev.element, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
el: Mut<'_, Self::Element>,
el: Mut<Self::Element>,
) {
self.element.teardown(view_state, ctx, el);
}
@ -173,26 +174,24 @@ where
self.element.build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
let element = self
.element
.rebuild(&prev.element, view_state, ctx, element);
mut element: Mut<Self::Element>,
) {
self.element
.rebuild(&prev.element, view_state, ctx, element.reborrow_mut());
element.node.apply_props(element.props);
(self.callback)(element.node);
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
el: Mut<'_, Self::Element>,
el: Mut<Self::Element>,
) {
self.element.teardown(view_state, ctx, el);
}
@ -225,22 +224,22 @@ where
self.element.build(ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
self.element
.rebuild(&prev.element, view_state, ctx, element)
.rebuild(&prev.element, view_state, ctx, element);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
el: Mut<'_, Self::Element>,
el: Mut<Self::Element>,
) {
(self.callback)(el.node);
self.element.teardown(view_state, ctx, el);

View File

@ -1,12 +1,13 @@
// Copyright 2023 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{elements::DomChildrenSplice, AnyPod, DomFragment, ViewCtx};
use crate::{
core::{AppendVec, MessageResult, ViewId},
elements::DomChildrenSplice,
AnyPod, DomFragment, DynMessage, ViewCtx,
};
use std::{cell::RefCell, rc::Rc};
use crate::DynMessage;
use wasm_bindgen::UnwrapThrowExt;
use xilem_core::{AppendVec, MessageResult, ViewId};
pub(crate) struct AppMessage {
pub id_path: Rc<[ViewId]>,

View File

@ -1,13 +1,13 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker},
vecmap::VecMap,
AttributeValue, DomNode, DomView, DynMessage, ElementProps, Pod, PodMut, ViewCtx,
};
use std::marker::PhantomData;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use xilem_core::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker};
use crate::{
vecmap::VecMap, AttributeValue, DomNode, DynMessage, ElementProps, Pod, PodMut, ViewCtx,
};
type CowStr = std::borrow::Cow<'static, str>;
@ -347,7 +347,7 @@ impl<E, T, A> View<T, A, ViewCtx, DynMessage> for Attr<E, T, A>
where
T: 'static,
A: 'static,
E: View<T, A, ViewCtx, DynMessage, Element: ElementWithAttributes>,
E: DomView<T, A, DomNode: DomNode<Props: WithAttributes>>,
{
type Element = E::Element;
@ -361,25 +361,25 @@ where
(element, state)
}
fn rebuild<'e>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'e, Self::Element>,
) -> Mut<'e, Self::Element> {
mut element: Mut<Self::Element>,
) {
element.rebuild_attribute_modifier();
let mut element = self.el.rebuild(&prev.el, view_state, ctx, element);
self.el
.rebuild(&prev.el, view_state, ctx, element.reborrow_mut());
element.set_attribute(&self.name, &self.value);
element.mark_end_of_attribute_modifier();
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.el.teardown(view_state, ctx, element);
}

View File

@ -1,13 +1,14 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker},
vecmap::VecMap,
DomNode, DomView, DynMessage, ElementProps, Pod, PodMut, ViewCtx,
};
use std::marker::PhantomData;
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use xilem_core::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker};
use crate::{vecmap::VecMap, DomNode, DynMessage, ElementProps, Pod, PodMut, ViewCtx};
type CowStr = std::borrow::Cow<'static, str>;
/// Types implementing this trait can be used in the [`Class`] view, see also [`Element::class`](`crate::interfaces::Element::class`)
@ -327,7 +328,7 @@ where
T: 'static,
A: 'static,
C: AsClassIter + 'static,
E: View<T, A, ViewCtx, DynMessage, Element: ElementWithClasses>,
E: DomView<T, A, DomNode: DomNode<Props: WithClasses>>,
{
type Element = E::Element;
@ -344,29 +345,29 @@ where
(e, s)
}
fn rebuild<'e>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'e, Self::Element>,
) -> Mut<'e, Self::Element> {
mut element: Mut<Self::Element>,
) {
// This has to happen, before any children are rebuilt, otherwise this state machine breaks...
// The actual modifiers also have to happen after the children are rebuilt, see `add_class` below.
element.rebuild_class_modifier();
let mut element = self.el.rebuild(&prev.el, view_state, ctx, element);
self.el
.rebuild(&prev.el, view_state, ctx, element.reborrow_mut());
for class in self.classes.class_iter() {
element.add_class(&class);
}
element.mark_end_of_class_modifier();
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.el.teardown(view_state, ctx, element);
}

View File

@ -1,12 +1,12 @@
// Copyright 2024 the Xilem Authors and the Druid Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, NoElement, View, ViewId, ViewMarker},
DynMessage, OptionalAction, ViewCtx,
};
use std::marker::PhantomData;
use wasm_bindgen::{closure::Closure, JsCast, UnwrapThrowExt};
use xilem_core::{MessageResult, Mut, NoElement, View, ViewId, ViewMarker};
use crate::{DynMessage, OptionalAction, ViewCtx};
/// Start an interval which invokes `callback` every `ms` milliseconds
pub struct Interval<Callback, State, Action> {
@ -109,25 +109,20 @@ where
(NoElement, state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
_: &mut ViewCtx,
(): Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
(): Mut<Self::Element>,
) {
if prev.ms != self.ms {
clear_interval(view_state.interval_handle);
view_state.interval_handle = start_interval(&view_state.interval_fn, self.ms);
}
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
_: &mut ViewCtx,
_: Mut<'_, Self::Element>,
) {
fn teardown(&self, view_state: &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {
clear_interval(view_state.interval_handle);
}

View File

@ -1,13 +1,13 @@
// Copyright 2024 the Xilem Authors and the Druid Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, NoElement, View, ViewId, ViewMarker, ViewPathTracker},
DynMessage, OptionalAction, ViewCtx,
};
use std::{future::Future, marker::PhantomData};
use wasm_bindgen::{closure::Closure, JsCast, UnwrapThrowExt};
use wasm_bindgen_futures::spawn_local;
use xilem_core::{MessageResult, Mut, NoElement, View, ViewId, ViewMarker, ViewPathTracker};
use crate::{DynMessage, OptionalAction, ViewCtx};
/// Await a future returned by `init_future` invoked with the argument `data`, `callback` is called with the output of the future. `init_future` will be invoked again, when `data` changes. Use [`memoized_await`] for construction of this [`View`]
pub struct MemoizedAwait<State, Action, OA, InitFuture, Data, Callback, F, FOut> {
@ -184,13 +184,13 @@ where
(NoElement, state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
(): Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
(): Mut<Self::Element>,
) {
let debounce_has_changed_and_update_is_scheduled = view_state.schedule_update
&& (prev.reset_debounce_on_update != self.reset_debounce_on_update
|| prev.debounce_ms != self.debounce_ms);
@ -225,7 +225,7 @@ where
}
}
fn teardown(&self, state: &mut Self::ViewState, _: &mut ViewCtx, (): Mut<'_, Self::Element>) {
fn teardown(&self, state: &mut Self::ViewState, _: &mut ViewCtx, (): Mut<Self::Element>) {
state.clear_update_timeout();
}

View File

@ -3,12 +3,14 @@
use std::{future::Future, marker::PhantomData, rc::Rc};
use crate::{
context::MessageThunk,
core::{MessageResult, Mut, NoElement, View, ViewId, ViewMarker},
DynMessage, Message, ViewCtx,
};
use futures::{channel::oneshot, FutureExt};
use wasm_bindgen::UnwrapThrowExt;
use wasm_bindgen_futures::spawn_local;
use xilem_core::{MessageResult, Mut, NoElement, View, ViewId, ViewMarker};
use crate::{context::MessageThunk, DynMessage, Message, ViewCtx};
/// Spawn an async task to update state asynchronously
///
@ -148,22 +150,11 @@ where
(NoElement, view_state)
}
fn rebuild<'el>(
&self,
_: &Self,
_: &mut Self::ViewState,
_: &mut ViewCtx,
(): Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
fn rebuild(&self, _: &Self, _: &mut Self::ViewState, _: &mut ViewCtx, (): Mut<Self::Element>) {
// Nothing to do
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
_: &mut ViewCtx,
_: Mut<'_, Self::Element>,
) {
fn teardown(&self, view_state: &mut Self::ViewState, _: &mut ViewCtx, _: Mut<Self::Element>) {
let handle = view_state.abort_handle.take().unwrap_throw();
handle.abort();
}

View File

@ -193,7 +193,7 @@ impl<'a, 'b, 'c, 'd> ElementSplice<AnyPod> for DomChildrenSplice<'a, 'b, 'c, 'd>
self.children.insert(element);
}
fn mutate<R>(&mut self, f: impl FnOnce(Mut<'_, AnyPod>) -> R) -> R {
fn mutate<R>(&mut self, f: impl FnOnce(Mut<AnyPod>) -> R) -> R {
let child = self.children.mutate();
let ret = f(child.as_mut(self.parent, self.parent_was_removed));
self.ix += 1;
@ -205,7 +205,7 @@ impl<'a, 'b, 'c, 'd> ElementSplice<AnyPod> for DomChildrenSplice<'a, 'b, 'c, 'd>
self.ix += n;
}
fn delete<R>(&mut self, f: impl FnOnce(Mut<'_, AnyPod>) -> R) -> R {
fn delete<R>(&mut self, f: impl FnOnce(Mut<AnyPod>) -> R) -> R {
let mut child = self.children.delete_next();
let child = child.as_mut(self.parent, true);
// This is an optimization to avoid too much DOM traffic, otherwise first the children would be deleted from that node in an up-traversal
@ -286,14 +286,13 @@ where
)
}
pub(crate) fn rebuild_element<'el, State, Action, Element>(
pub(crate) fn rebuild_element<State, Action, Element>(
children: &dyn DomViewSequence<State, Action>,
prev_children: &dyn DomViewSequence<State, Action>,
element: Mut<'el, Pod<Element>>,
element: Mut<Pod<Element>>,
state: &mut ElementState,
ctx: &mut ViewCtx,
) -> Mut<'el, Pod<Element>>
where
) where
State: 'static,
Action: 'static,
Element: 'static,
@ -315,12 +314,11 @@ where
ctx,
&mut dom_children_splice,
);
element
}
pub(crate) fn teardown_element<State, Action, Element>(
children: &dyn DomViewSequence<State, Action>,
element: Mut<'_, Pod<Element>>,
element: Mut<Pod<Element>>,
state: &mut ElementState,
ctx: &mut ViewCtx,
) where
@ -381,13 +379,13 @@ where
build_element(&*self.children, &self.name, HTML_NS, ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
element_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
if prev.name != self.name {
let new_element = document()
.create_element_ns(Some(HTML_NS), &self.name)
@ -410,14 +408,14 @@ where
element,
element_state,
ctx,
)
);
}
fn teardown(
&self,
element_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
teardown_element(&*self.children, element, element_state, ctx);
}
@ -472,27 +470,27 @@ macro_rules! define_element {
build_element(&*self.children, $tag_name, $ns, ctx)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
element_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
rebuild_element(
&*self.children,
&*prev.children,
element,
element_state,
ctx,
)
);
}
fn teardown(
&self,
element_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
teardown_element(&*self.children, element, element_state, ctx);
}

View File

@ -1,12 +1,13 @@
// Copyright 2023 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker},
DynMessage, ElementAsRef, OptionalAction, ViewCtx,
};
use std::{borrow::Cow, marker::PhantomData};
use wasm_bindgen::{prelude::Closure, throw_str, JsCast, UnwrapThrowExt};
use web_sys::{js_sys, AddEventListenerOptions};
use xilem_core::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker};
use crate::{DynMessage, ElementAsRef, OptionalAction, ViewCtx};
/// Use a distinctive number here, to be able to catch bugs.
/// In case the generational-id view path in `View::Message` lead to a wrong view
@ -143,10 +144,10 @@ where
}
#[allow(clippy::too_many_arguments)]
fn rebuild_event_listener<'el, State, Action, V, Event>(
fn rebuild_event_listener<State, Action, V, Event>(
element_view: &V,
prev_element_view: &V,
element: Mut<'el, V::Element>,
element: Mut<V::Element>,
event: &str,
capture: bool,
passive: bool,
@ -154,8 +155,7 @@ fn rebuild_event_listener<'el, State, Action, V, Event>(
prev_passive: bool,
state: &mut OnEventState<V::ViewState>,
ctx: &mut ViewCtx,
) -> Mut<'el, V::Element>
where
) where
State: 'static,
Action: 'static,
V: View<State, Action, ViewCtx, DynMessage>,
@ -169,13 +169,13 @@ where
state.callback =
create_event_listener::<Event>(element.as_ref(), event, capture, passive, ctx);
}
element_view.rebuild(prev_element_view, &mut state.child_state, ctx, element)
})
element_view.rebuild(prev_element_view, &mut state.child_state, ctx, element);
});
}
fn teardown_event_listener<State, Action, V>(
element_view: &V,
element: Mut<'_, V::Element>,
element: Mut<V::Element>,
_event: &str,
state: &mut OnEventState<V::ViewState>,
_capture: bool,
@ -253,13 +253,13 @@ where
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
// special case, where event name can change, so we can't reuse the rebuild_event_listener function above
ctx.with_id(ON_EVENT_VIEW_ID, |ctx| {
if prev.capture != self.capture
@ -282,15 +282,15 @@ where
);
}
self.element
.rebuild(&prev.element, &mut view_state.child_state, ctx, element)
})
.rebuild(&prev.element, &mut view_state.child_state, ctx, element);
});
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
teardown_event_listener(
&self.element,
@ -391,13 +391,13 @@ macro_rules! event_definitions {
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
rebuild_event_listener::<_, _, _, web_sys::$web_sys_ty>(
&self.element,
&prev.element,
@ -409,14 +409,14 @@ macro_rules! event_definitions {
prev.passive,
view_state,
ctx,
)
);
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
teardown_event_listener(&self.element, element, $event_name, view_state, self.capture, ctx);
}
@ -563,24 +563,24 @@ where
})
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
ctx.with_id(ON_EVENT_VIEW_ID, |ctx| {
self.element
.rebuild(&prev.element, &mut view_state.child_state, ctx, element)
})
.rebuild(&prev.element, &mut view_state.child_state, ctx, element);
});
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
ctx.with_id(ON_EVENT_VIEW_ID, |ctx| {
view_state.observer.unobserve(element.as_ref());

View File

@ -292,7 +292,7 @@ impl<N: DomNode> SuperElement<Pod<N>, ViewCtx> for AnyPod {
fn with_downcast_val<R>(
mut this: Self::Mut<'_>,
f: impl FnOnce(PodMut<'_, N>) -> R,
f: impl FnOnce(PodMut<N>) -> R,
) -> (Self::Mut<'_>, R) {
let downcast = this.downcast();
let ret = f(downcast);
@ -333,6 +333,7 @@ pub struct PodMut<'a, N: DomNode> {
props: &'a mut N::Props,
parent: Option<&'a web_sys::Node>,
was_removed: bool,
is_reborrow: bool,
}
impl<'a, N: DomNode> PodMut<'a, N> {
@ -347,12 +348,23 @@ impl<'a, N: DomNode> PodMut<'a, N> {
props,
parent,
was_removed,
is_reborrow: false,
}
}
fn reborrow_mut(&mut self) -> PodMut<N> {
PodMut {
node: self.node,
props: self.props,
parent: self.parent,
was_removed: self.was_removed,
is_reborrow: true,
}
}
}
impl PodMut<'_, Box<dyn AnyNode>> {
fn downcast<N: DomNode>(&mut self) -> PodMut<'_, N> {
fn downcast<N: DomNode>(&mut self) -> PodMut<N> {
PodMut::new(
self.node.deref_mut().as_any_mut().downcast_mut().unwrap(),
self.props.downcast_mut().unwrap(),
@ -364,7 +376,7 @@ impl PodMut<'_, Box<dyn AnyNode>> {
impl<N: DomNode> Drop for PodMut<'_, N> {
fn drop(&mut self) {
if !self.was_removed {
if !self.is_reborrow && !self.was_removed {
self.node.apply_props(self.props);
}
}

View File

@ -1,16 +1,17 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use wasm_bindgen::UnwrapThrowExt;
use xilem_core::{
one_of::{OneOf, OneOfCtx, PhantomElementCtx},
Mut,
};
use crate::{
attribute::WithAttributes, class::WithClasses, style::WithStyle, AttributeValue, DomNode, Pod,
PodMut, ViewCtx,
attribute::WithAttributes,
class::WithClasses,
core::{
one_of::{OneOf, OneOfCtx, PhantomElementCtx},
Mut,
},
style::WithStyle,
AttributeValue, DomNode, Pod, PodMut, ViewCtx,
};
use wasm_bindgen::UnwrapThrowExt;
type CowStr = std::borrow::Cow<'static, str>;
@ -85,7 +86,7 @@ where
}
fn update_one_of_element_mut(
elem_mut: &mut Mut<'_, Self::OneOfElement>,
elem_mut: &mut Mut<Self::OneOfElement>,
new_elem: OneOf<
Pod<N1>,
Pod<N2>,
@ -118,63 +119,63 @@ where
};
}
fn with_downcast_a(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N1>>)) {
fn with_downcast_a(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N1>>)) {
let (OneOf::A(node), OneOf::A(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_b(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N2>>)) {
fn with_downcast_b(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N2>>)) {
let (OneOf::B(node), OneOf::B(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_c(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N3>>)) {
fn with_downcast_c(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N3>>)) {
let (OneOf::C(node), OneOf::C(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_d(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N4>>)) {
fn with_downcast_d(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N4>>)) {
let (OneOf::D(node), OneOf::D(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_e(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N5>>)) {
fn with_downcast_e(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N5>>)) {
let (OneOf::E(node), OneOf::E(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_f(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N6>>)) {
fn with_downcast_f(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N6>>)) {
let (OneOf::F(node), OneOf::F(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_g(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N7>>)) {
fn with_downcast_g(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N7>>)) {
let (OneOf::G(node), OneOf::G(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_h(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N8>>)) {
fn with_downcast_h(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N8>>)) {
let (OneOf::H(node), OneOf::H(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};
f(PodMut::new(node, props, elem.parent, elem.was_removed));
}
fn with_downcast_i(elem: &mut Mut<'_, Self::OneOfElement>, f: impl FnOnce(Mut<'_, Pod<N9>>)) {
fn with_downcast_i(elem: &mut Mut<Self::OneOfElement>, f: impl FnOnce(Mut<Pod<N9>>)) {
let (OneOf::I(node), OneOf::I(props)) = (&mut elem.node, &mut elem.props) else {
unreachable!()
};

View File

@ -3,15 +3,15 @@
//! Interactivity with pointer events.
use crate::{
core::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker},
interfaces::Element,
DynMessage, ElementAsRef, ViewCtx,
};
use std::marker::PhantomData;
use wasm_bindgen::{prelude::Closure, throw_str, JsCast, UnwrapThrowExt};
use web_sys::PointerEvent;
use xilem_core::{MessageResult, Mut, View, ViewId, ViewMarker, ViewPathTracker};
use crate::{interfaces::Element, DynMessage, ElementAsRef, ViewCtx};
/// A view that allows stateful handling of [`PointerEvent`]s with [`PointerMsg`]
pub struct Pointer<V, T, A, F> {
child: V,
@ -128,24 +128,24 @@ where
})
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
ctx.with_id(ViewId::new(0), |ctx| {
self.child
.rebuild(&prev.child, &mut view_state.child_state, ctx, element)
})
.rebuild(&prev.child, &mut view_state.child_state, ctx, element);
});
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
// TODO remove event listeners from child or is this not necessary?
self.child

View File

@ -1,6 +1,11 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker},
vecmap::VecMap,
DomNode, DomView, DynMessage, ElementProps, Pod, PodMut, ViewCtx,
};
use peniko::kurbo::Vec2;
use std::{
collections::{BTreeMap, HashMap},
@ -8,9 +13,6 @@ use std::{
marker::PhantomData,
};
use wasm_bindgen::{JsCast, UnwrapThrowExt};
use xilem_core::{MessageResult, Mut, View, ViewElement, ViewId, ViewMarker};
use crate::{vecmap::VecMap, DomNode, DynMessage, ElementProps, Pod, PodMut, ViewCtx};
type CowStr = std::borrow::Cow<'static, str>;
@ -444,7 +446,7 @@ impl<T, A, E> View<T, A, ViewCtx, DynMessage> for Style<E, T, A>
where
T: 'static,
A: 'static,
E: View<T, A, ViewCtx, DynMessage, Element: ElementWithStyle>,
E: DomView<T, A, DomNode: DomNode<Props: WithStyle>>,
{
type Element = E::Element;
@ -460,27 +462,27 @@ where
(element, state)
}
fn rebuild<'e>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'e, Self::Element>,
) -> Mut<'e, Self::Element> {
mut element: Mut<Self::Element>,
) {
element.rebuild_style_modifier();
let mut element = self.el.rebuild(&prev.el, view_state, ctx, element);
self.el
.rebuild(&prev.el, view_state, ctx, element.reborrow_mut());
for (key, value) in &self.styles {
element.set_style(key, value);
}
element.mark_end_of_style_modifier();
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.el.teardown(view_state, ctx, element);
}
@ -526,7 +528,7 @@ impl<T, A, E> View<T, A, ViewCtx, DynMessage> for Rotate<E, T, A>
where
T: 'static,
A: 'static,
E: View<T, A, ViewCtx, DynMessage, Element: ElementWithStyle>,
E: DomView<T, A, DomNode: DomNode<Props: WithStyle>>,
{
type Element = E::Element;
@ -541,28 +543,28 @@ where
(element, (state, css_repr))
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(view_state, css_repr): &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
element.rebuild_style_modifier();
let mut element = self.el.rebuild(&prev.el, view_state, ctx, element);
self.el
.rebuild(&prev.el, view_state, ctx, element.reborrow_mut());
if prev.radians != self.radians || element.was_updated("transform") {
*css_repr = modify_rotate_transform(element.get_style("transform"), self.radians);
}
element.set_style(&"transform".into(), css_repr);
element.mark_end_of_style_modifier();
element
}
fn teardown(
&self,
(view_state, _): &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.el.teardown(view_state, ctx, element);
}
@ -641,7 +643,7 @@ impl<T, A, E> View<T, A, ViewCtx, DynMessage> for Scale<E, T, A>
where
T: 'static,
A: 'static,
E: View<T, A, ViewCtx, DynMessage, Element: ElementWithStyle>,
E: DomView<T, A, DomNode: DomNode<Props: WithStyle>>,
{
type Element = E::Element;
@ -656,28 +658,28 @@ where
(element, (state, css_repr))
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(view_state, css_repr): &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
element.rebuild_style_modifier();
let mut element = self.el.rebuild(&prev.el, view_state, ctx, element);
self.el
.rebuild(&prev.el, view_state, ctx, element.reborrow_mut());
if prev.scale != self.scale || element.was_updated("transform") {
*css_repr = modify_scale_transform(element.get_style("transform"), self.scale);
}
element.set_style(&"transform".into(), css_repr);
element.mark_end_of_style_modifier();
element
}
fn teardown(
&self,
(view_state, _): &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.el.teardown(view_state, ctx, element);
}

View File

@ -1,18 +1,15 @@
// Copyright 2023 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
attribute::WithAttributes,
core::{MessageResult, Mut, View, ViewId, ViewMarker},
AttributeValue, DomNode, DomView, DynMessage, IntoAttributeValue, ViewCtx,
};
use peniko::Brush;
use std::fmt::Write as _;
use std::marker::PhantomData;
use peniko::Brush;
use xilem_core::{MessageResult, Mut, View, ViewId, ViewMarker};
use crate::AttributeValue;
use crate::{
attribute::{ElementWithAttributes, WithAttributes},
DynMessage, IntoAttributeValue, ViewCtx,
};
pub struct Fill<V, State, Action> {
child: V,
// This could reasonably be static Cow also, but keep things simple
@ -93,7 +90,7 @@ impl<State, Action, V> View<State, Action, ViewCtx, DynMessage> for Fill<V, Stat
where
State: 'static,
Action: 'static,
V: View<State, Action, ViewCtx, DynMessage, Element: ElementWithAttributes>,
V: DomView<State, Action, DomNode: DomNode<Props: WithAttributes>>,
{
type ViewState = (Option<AttributeValue>, V::ViewState);
type Element = V::Element;
@ -107,29 +104,29 @@ where
(element, (brush_svg_repr, child_state))
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
(brush_svg_repr, child_state): &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
element.rebuild_attribute_modifier();
let mut element = self.child.rebuild(&prev.child, child_state, ctx, element);
self.child
.rebuild(&prev.child, child_state, ctx, element.reborrow_mut());
if self.brush != prev.brush {
*brush_svg_repr = brush_to_string(&self.brush).into_attr_value();
}
element.set_attribute(&"fill".into(), brush_svg_repr);
add_opacity_to_element(&self.brush, &mut element, "fill-opacity");
element.mark_end_of_attribute_modifier();
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.child.teardown(&mut view_state.1, ctx, element);
}
@ -156,7 +153,7 @@ impl<State, Action, V> View<State, Action, ViewCtx, DynMessage> for Stroke<V, St
where
State: 'static,
Action: 'static,
V: View<State, Action, ViewCtx, DynMessage, Element: ElementWithAttributes>,
V: DomView<State, Action, DomNode: DomNode<Props: WithAttributes>>,
{
type ViewState = StrokeState<V::ViewState>;
type Element = V::Element;
@ -185,7 +182,7 @@ where
)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
StrokeState {
@ -194,11 +191,12 @@ where
child_state,
}: &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'el, Self::Element>,
) -> Mut<'el, Self::Element> {
mut element: Mut<Self::Element>,
) {
element.rebuild_attribute_modifier();
let mut element = self.child.rebuild(&prev.child, child_state, ctx, element);
self.child
.rebuild(&prev.child, child_state, ctx, element.reborrow_mut());
if self.brush != prev.brush {
*brush_svg_repr = brush_to_string(&self.brush).into_attr_value();
@ -216,14 +214,13 @@ where
add_opacity_to_element(&self.brush, &mut element, "stroke-opacity");
element.mark_end_of_attribute_modifier();
element
}
fn teardown(
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.child
.teardown(&mut view_state.child_state, ctx, element);

View File

@ -3,13 +3,12 @@
//! Implementation of the View trait for various kurbo shapes.
use peniko::kurbo::{BezPath, Circle, Line, Rect};
use xilem_core::{MessageResult, Mut, OrphanView};
use crate::{
attribute::WithAttributes, AttributeValue, Attributes, DynMessage, IntoAttributeValue, Pod,
ViewCtx, SVG_NS,
attribute::WithAttributes,
core::{MessageResult, Mut, OrphanView, ViewId},
AttributeValue, Attributes, DynMessage, IntoAttributeValue, Pod, ViewCtx, SVG_NS,
};
use peniko::kurbo::{BezPath, Circle, Line, Rect};
fn create_element(name: &str, ctx: &mut ViewCtx, attr_size_hint: usize) -> Pod<web_sys::Element> {
ctx.add_modifier_size_hint::<Attributes>(attr_size_hint);
@ -40,34 +39,33 @@ impl<State: 'static, Action: 'static> OrphanView<Line, State, Action, DynMessage
(element, ())
}
fn orphan_rebuild<'el>(
fn orphan_rebuild(
new: &Line,
_prev: &Line,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::OrphanElement>,
) -> Mut<'el, Self::OrphanElement> {
mut element: Mut<Self::OrphanElement>,
) {
element.rebuild_attribute_modifier();
element.set_attribute(&"x1".into(), &new.p0.x.into_attr_value());
element.set_attribute(&"y1".into(), &new.p0.y.into_attr_value());
element.set_attribute(&"x2".into(), &new.p1.x.into_attr_value());
element.set_attribute(&"y2".into(), &new.p1.y.into_attr_value());
element.mark_end_of_attribute_modifier();
element
}
fn orphan_teardown(
_view: &Line,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Self::OrphanElement>,
_element: Mut<Self::OrphanElement>,
) {
}
fn orphan_message(
_view: &Line,
(): &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> MessageResult<Action, DynMessage> {
@ -92,34 +90,33 @@ impl<State: 'static, Action: 'static> OrphanView<Rect, State, Action, DynMessage
(element, ())
}
fn orphan_rebuild<'el>(
fn orphan_rebuild(
new: &Rect,
_prev: &Rect,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::OrphanElement>,
) -> Mut<'el, Self::OrphanElement> {
mut element: Mut<Self::OrphanElement>,
) {
element.rebuild_attribute_modifier();
element.set_attribute(&"x".into(), &new.x0.into_attr_value());
element.set_attribute(&"y".into(), &new.y0.into_attr_value());
element.set_attribute(&"width".into(), &new.width().into_attr_value());
element.set_attribute(&"height".into(), &new.height().into_attr_value());
element.mark_end_of_attribute_modifier();
element
}
fn orphan_teardown(
_view: &Rect,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Self::OrphanElement>,
_element: Mut<Self::OrphanElement>,
) {
}
fn orphan_message(
_view: &Rect,
(): &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> MessageResult<Action, DynMessage> {
@ -143,33 +140,32 @@ impl<State: 'static, Action: 'static> OrphanView<Circle, State, Action, DynMessa
(element, ())
}
fn orphan_rebuild<'el>(
fn orphan_rebuild(
new: &Circle,
_prev: &Circle,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::OrphanElement>,
) -> Mut<'el, Self::OrphanElement> {
mut element: Mut<Self::OrphanElement>,
) {
element.rebuild_attribute_modifier();
element.set_attribute(&"cx".into(), &new.center.x.into_attr_value());
element.set_attribute(&"cy".into(), &new.center.y.into_attr_value());
element.set_attribute(&"r".into(), &new.radius.into_attr_value());
element.mark_end_of_attribute_modifier();
element
}
fn orphan_teardown(
_view: &Circle,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Self::OrphanElement>,
_element: Mut<Self::OrphanElement>,
) {
}
fn orphan_message(
_view: &Circle,
(): &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> MessageResult<Action, DynMessage> {
@ -192,13 +188,13 @@ impl<State: 'static, Action: 'static> OrphanView<BezPath, State, Action, DynMess
(element, svg_repr)
}
fn orphan_rebuild<'el>(
fn orphan_rebuild(
new: &BezPath,
prev: &BezPath,
svg_repr: &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
mut element: Mut<'el, Self::OrphanElement>,
) -> Mut<'el, Self::OrphanElement> {
mut element: Mut<Self::OrphanElement>,
) {
// slight optimization to avoid serialization/allocation
if new != prev {
*svg_repr = new.to_svg().into_attr_value();
@ -206,21 +202,20 @@ impl<State: 'static, Action: 'static> OrphanView<BezPath, State, Action, DynMess
element.rebuild_attribute_modifier();
element.set_attribute(&"d".into(), svg_repr);
element.mark_end_of_attribute_modifier();
element
}
fn orphan_teardown(
_view: &BezPath,
_view_state: &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Self::OrphanElement>,
_element: Mut<Self::OrphanElement>,
) {
}
fn orphan_message(
_view: &BezPath,
_view_state: &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> MessageResult<Action, DynMessage> {

View File

@ -1,12 +1,12 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, View, ViewId, ViewMarker},
DomNode, DomView, DynMessage, PodMut, ViewCtx,
};
use std::{any::TypeId, ops::Deref as _, rc::Rc};
use wasm_bindgen::UnwrapThrowExt;
use xilem_core::{MessageResult, View, ViewMarker};
use crate::{DomNode, DomView, DynMessage, PodMut, ViewCtx};
/// This view creates an internally cached deep-clone of the underlying DOM node. When the inner view is created again, this will be done more efficiently.
pub struct Templated<E>(Rc<E>);
@ -65,20 +65,18 @@ where
(element, state)
}
fn rebuild<'el>(
fn rebuild(
&self,
prev: &Self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: xilem_core::Mut<'el, Self::Element>,
) -> xilem_core::Mut<'el, Self::Element> {
element: Mut<Self::Element>,
) {
// If this is the same value, or no rebuild was forced, there's no need to rebuild
if core::mem::take(&mut view_state.dirty) || !Rc::ptr_eq(&self.0, &prev.0) {
self.0
.deref()
.rebuild(&prev.0, &mut view_state.view_state, ctx, element)
} else {
// If this is the same value, or no rebuild was forced, there's no need to rebuild
element
.rebuild(&prev.0, &mut view_state.view_state, ctx, element);
}
}
@ -86,7 +84,7 @@ where
&self,
view_state: &mut Self::ViewState,
ctx: &mut ViewCtx,
element: xilem_core::Mut<'_, Self::Element>,
element: Mut<Self::Element>,
) {
self.0.teardown(&mut view_state.view_state, ctx, element);
}
@ -94,10 +92,10 @@ where
fn message(
&self,
view_state: &mut Self::ViewState,
id_path: &[xilem_core::ViewId],
id_path: &[ViewId],
message: DynMessage,
app_state: &mut State,
) -> xilem_core::MessageResult<Action, DynMessage> {
) -> MessageResult<Action, DynMessage> {
let message_result =
self.0
.deref()

View File

@ -1,11 +1,12 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0
use crate::{
core::{MessageResult, Mut, OrphanView, ViewId},
DynMessage, Pod, ViewCtx,
};
#[cfg(feature = "hydration")]
use wasm_bindgen::JsCast;
use xilem_core::{Mut, OrphanView};
use crate::{DynMessage, Pod, ViewCtx};
// strings -> text nodes
macro_rules! impl_string_view {
@ -30,35 +31,34 @@ macro_rules! impl_string_view {
(Pod { node, props: () }, ())
}
fn orphan_rebuild<'a>(
fn orphan_rebuild(
new: &$ty,
prev: &$ty,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
element: Mut<'a, Self::OrphanElement>,
) -> Mut<'a, Self::OrphanElement> {
element: Mut<Self::OrphanElement>,
) {
if prev != new {
element.node.set_data(new);
}
element
}
fn orphan_teardown(
_view: &$ty,
_view_state: &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Pod<web_sys::Text>>,
_element: Mut<Self::OrphanElement>,
) {
}
fn orphan_message(
_view: &$ty,
_view_state: &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> xilem_core::MessageResult<Action, DynMessage> {
xilem_core::MessageResult::Stale(message)
) -> MessageResult<Action, DynMessage> {
MessageResult::Stale(message)
}
}
};
@ -90,35 +90,34 @@ macro_rules! impl_to_string_view {
(Pod { node, props: () }, ())
}
fn orphan_rebuild<'a>(
fn orphan_rebuild(
new: &$ty,
prev: &$ty,
(): &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
element: Mut<'a, Self::OrphanElement>,
) -> Mut<'a, Self::OrphanElement> {
element: Mut<Self::OrphanElement>,
) {
if prev != new {
element.node.set_data(&new.to_string());
}
element
}
fn orphan_teardown(
_view: &$ty,
_view_state: &mut Self::OrphanViewState,
_ctx: &mut ViewCtx,
_element: Mut<'_, Pod<web_sys::Text>>,
_element: Mut<Pod<web_sys::Text>>,
) {
}
fn orphan_message(
_view: &$ty,
_view_state: &mut Self::OrphanViewState,
_id_path: &[xilem_core::ViewId],
_id_path: &[ViewId],
message: DynMessage,
_app_state: &mut State,
) -> xilem_core::MessageResult<Action, DynMessage> {
xilem_core::MessageResult::Stale(message)
) -> MessageResult<Action, DynMessage> {
MessageResult::Stale(message)
}
}
};