use frust_core::{
AnyView, BoxConstraints, BuildCtx, ChangeFlags, ChildPod, EventCtx, EventResult, HeroDirective,
InputEvent, LayoutCtx, PaintCtx, PaintScene, SemanticsCtx, View, Widget, any,
};
use kurbo::{Point, Rect, Size};
use super::transition::rect_to_rect;
pub struct HeroView<State: 'static> {
tag: String,
child: AnyView<State>,
}
pub fn hero<State: 'static, V: View<State>>(tag: impl Into<String>, child: V) -> HeroView<State> {
HeroView {
tag: tag.into(),
child: any(child),
}
}
pub struct HeroWidget {
tag: String,
child: ChildPod,
}
impl<State: 'static> View<State> for HeroView<State> {
type Element = HeroWidget;
fn build(&self, ctx: &mut BuildCtx<'_>) -> HeroWidget {
HeroWidget {
tag: self.tag.clone(),
child: crate::authoring::build_child(&self.child, ctx),
}
}
fn rebuild(
&self,
prev: &Self,
element: &mut HeroWidget,
ctx: &mut BuildCtx<'_>,
) -> ChangeFlags {
let mut flags = ChangeFlags::NONE;
if prev.tag != self.tag {
element.tag = self.tag.clone();
flags |= ChangeFlags::PAINT;
}
flags |= crate::authoring::rebuild_child(&prev.child, &self.child, &mut element.child, ctx);
flags
}
fn teardown(&self, element: &mut HeroWidget, ctx: &mut BuildCtx<'_>) {
crate::authoring::teardown_child(&self.child, &mut element.child, ctx);
}
}
impl Widget for HeroWidget {
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints) -> Size {
let size = self.child.layout_child(ctx, bc);
self.child.set_origin(Point::ZERO);
size
}
fn paint(&mut self, ctx: &mut PaintCtx, scene: &mut dyn PaintScene) {
let bounds = Rect::from_origin_size(ctx.origin(), ctx.size());
match ctx.report_hero(&self.tag, bounds) {
HeroDirective::Normal => self.child.paint_child(ctx, scene),
HeroDirective::Suppress => {}
HeroDirective::Morph { dest } => {
scene.push_transform(rect_to_rect(bounds, dest));
self.child.paint_child(ctx, scene);
scene.pop_transform();
}
}
}
fn event(&mut self, ctx: &mut EventCtx, event: &InputEvent) -> EventResult {
crate::authoring::route_event_single(&mut self.child, ctx, event)
}
fn semantics(&self, ctx: &mut SemanticsCtx) {
self.child.semantics_child(ctx);
}
crate::authoring::visit_children!(child);
}