mirror of https://github.com/linebender/xilem
Add the `Portal` view to Xilem (#561)
This is also added to `variable_clocks` as needed. This could also be added to `mason`, but I see a worrying amount of lag if I do... I could do with some help tracking this down.
This commit is contained in:
parent
251f42ae87
commit
ac95f2524a
|
@ -41,13 +41,17 @@ pub struct Portal<W: Widget> {
|
|||
// --- MARK: BUILDERS ---
|
||||
impl<W: Widget> Portal<W> {
|
||||
pub fn new(child: W) -> Self {
|
||||
Self::new_pod(WidgetPod::new(child))
|
||||
}
|
||||
|
||||
pub fn new_pod(child: WidgetPod<W>) -> Self {
|
||||
Portal {
|
||||
child: WidgetPod::new(child),
|
||||
child,
|
||||
viewport_pos: Point::ORIGIN,
|
||||
constrain_horizontal: false,
|
||||
constrain_vertical: false,
|
||||
must_fill: false,
|
||||
// TODO - remove
|
||||
// TODO - remove (TODO: why?)
|
||||
scrollbar_horizontal: WidgetPod::new(ScrollBar::new(Axis::Horizontal, 1.0, 1.0)),
|
||||
scrollbar_horizontal_visible: false,
|
||||
scrollbar_vertical: WidgetPod::new(ScrollBar::new(Axis::Vertical, 1.0, 1.0)),
|
||||
|
|
|
@ -13,7 +13,8 @@ use time::{error::IndeterminateOffset, macros::format_description, OffsetDateTim
|
|||
use winit::error::EventLoopError;
|
||||
use xilem::{
|
||||
view::{
|
||||
button, flex, label, prose, sized_box, task, variable_label, Axis, FlexExt, FlexSpacer,
|
||||
button, flex, label, portal, prose, sized_box, task, variable_label, Axis, FlexExt,
|
||||
FlexSpacer,
|
||||
},
|
||||
Color, EventLoop, EventLoopBuilder, WidgetView, Xilem,
|
||||
};
|
||||
|
@ -43,8 +44,11 @@ fn app_logic(data: &mut Clocks) -> impl WidgetView<Clocks> {
|
|||
FlexSpacer::Fixed(40.),
|
||||
local_time(data),
|
||||
controls(),
|
||||
// TODO: When we get responsive layouts, move this into a two-column view.
|
||||
TIMEZONES.iter().map(|it| it.view(data)).collect::<Vec<_>>(),
|
||||
portal(flex(
|
||||
// TODO: When we get responsive layouts, move this into a two-column view on desktop.
|
||||
TIMEZONES.iter().map(|it| it.view(data)).collect::<Vec<_>>(),
|
||||
))
|
||||
.flex(1.),
|
||||
));
|
||||
fork(
|
||||
view,
|
||||
|
|
|
@ -30,3 +30,6 @@ pub use prose::*;
|
|||
|
||||
mod textbox;
|
||||
pub use textbox::*;
|
||||
|
||||
mod portal;
|
||||
pub use portal::*;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2024 the Xilem Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use masonry::widget;
|
||||
use xilem_core::{Mut, ViewMarker};
|
||||
|
||||
use crate::{Pod, View, ViewCtx, ViewId, WidgetView};
|
||||
|
||||
/// A view which puts `child` into a scrollable region.
|
||||
///
|
||||
/// This corresponds to the Masonry [`Portal`](masonry::widget::Portal) widget.
|
||||
pub fn portal<Child, State, Action>(child: Child) -> Portal<Child, State, Action>
|
||||
where
|
||||
Child: WidgetView<State, Action>,
|
||||
{
|
||||
Portal {
|
||||
child,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Portal<V, State, Action> {
|
||||
child: V,
|
||||
phantom: PhantomData<(State, Action)>,
|
||||
}
|
||||
|
||||
impl<V, State, Action> ViewMarker for Portal<V, State, Action> {}
|
||||
impl<Child, State, Action> View<State, Action, ViewCtx> for Portal<Child, State, Action>
|
||||
where
|
||||
Child: WidgetView<State, Action>,
|
||||
State: 'static,
|
||||
Action: 'static,
|
||||
{
|
||||
type Element = Pod<widget::Portal<Child::Widget>>;
|
||||
type ViewState = Child::ViewState;
|
||||
|
||||
fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
|
||||
// The Portal `View` doesn't get any messages directly (yet - scroll events?), so doesn't need to
|
||||
// use ctx.with_id.
|
||||
let (child, child_state) = self.child.build(ctx);
|
||||
let widget_pod = Pod::new(widget::Portal::new_pod(child.inner));
|
||||
(widget_pod, child_state)
|
||||
}
|
||||
|
||||
fn rebuild<'el>(
|
||||
&self,
|
||||
prev: &Self,
|
||||
view_state: &mut Self::ViewState,
|
||||
ctx: &mut ViewCtx,
|
||||
mut element: Mut<'el, Self::Element>,
|
||||
) -> Mut<'el, 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>,
|
||||
) {
|
||||
let child_element = element.child_mut();
|
||||
self.child.teardown(view_state, ctx, child_element);
|
||||
}
|
||||
|
||||
fn message(
|
||||
&self,
|
||||
view_state: &mut Self::ViewState,
|
||||
id_path: &[ViewId],
|
||||
message: xilem_core::DynMessage,
|
||||
app_state: &mut State,
|
||||
) -> crate::MessageResult<Action> {
|
||||
self.child.message(view_state, id_path, message, app_state)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue