use std::any::Any;
use std::cell::Cell;
use std::rc::Rc;
use frust_core::AnyView;
use super::path::Location;
use super::route_state::RouteStack;
use super::transition::TransitionSpec;
#[allow(unused_imports)]
use super::controller::NavigatorController;
#[allow(unused_imports)]
use super::navigator::NavigatorWidget;
#[allow(unused_imports)]
use super::view::NavigatorView;
pub type PageBuilder<State> = Rc<dyn Fn() -> AnyView<State>>;
pub type ResultCallback<State> = Rc<dyn Fn(&mut State, PopResult)>;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum PageVisibility {
#[default]
Current,
Visible,
Covered,
}
pub type VisibilityCallback = Rc<dyn Fn(PageVisibility)>;
pub type RouteChangeCallback = Rc<dyn Fn(&RouteStack)>;
pub struct PopResult(Option<Box<dyn Any>>);
impl PopResult {
pub fn empty() -> Self {
PopResult(None)
}
pub fn of<T: Any>(value: T) -> Self {
PopResult(Some(Box::new(value)))
}
pub fn is_empty(&self) -> bool {
self.0.is_none()
}
pub fn take<T: Any>(self) -> Option<T> {
self.0
.and_then(|boxed| boxed.downcast::<T>().ok())
.map(|boxed| *boxed)
}
}
impl std::fmt::Debug for PopResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PopResult")
.field("has_payload", &self.0.is_some())
.finish()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BackPolicy {
Pop,
DismissAnimated,
Veto,
}
pub struct PushOptions<State: 'static> {
pub(super) opaque: bool,
pub(super) back: BackPolicy,
pub(super) transition: Option<TransitionSpec>,
pub(super) on_result: Option<ResultCallback<State>>,
pub(super) dismiss_signal: Option<Rc<Cell<u64>>>,
pub(super) on_visibility: Option<VisibilityCallback>,
pub(super) route: Option<Location>,
pub(super) pop_swipe: Option<bool>,
}
impl<State: 'static> PushOptions<State> {
pub fn opaque() -> Self {
Self {
opaque: true,
back: BackPolicy::Pop,
transition: None,
on_result: None,
dismiss_signal: None,
on_visibility: None,
route: None,
pop_swipe: None,
}
}
pub fn transparent() -> Self {
Self {
opaque: false,
..Self::opaque()
}
}
pub fn back(mut self, policy: BackPolicy) -> Self {
self.back = policy;
self
}
pub fn transition(mut self, spec: TransitionSpec) -> Self {
self.transition = Some(spec);
self
}
pub fn on_result(mut self, callback: impl Fn(&mut State, PopResult) + 'static) -> Self {
self.on_result = Some(Rc::new(callback));
self
}
pub fn dismiss_signal(mut self, signal: Rc<Cell<u64>>) -> Self {
self.dismiss_signal = Some(signal);
self
}
pub fn on_visibility(mut self, f: impl Fn(PageVisibility) + 'static) -> Self {
self.on_visibility = Some(Rc::new(f));
self
}
pub fn route(mut self, location: Location) -> Self {
self.route = Some(location);
self
}
pub fn pop_swipe(mut self, enabled: bool) -> Self {
self.pop_swipe = Some(enabled);
self
}
}
pub struct ReplaceOptions {
pub(super) opaque: bool,
pub(super) transition: Option<TransitionSpec>,
pub(super) route: Option<Location>,
}
impl ReplaceOptions {
pub fn opaque() -> Self {
Self {
opaque: true,
transition: None,
route: None,
}
}
pub fn transparent() -> Self {
Self {
opaque: false,
..Self::opaque()
}
}
pub fn transition(mut self, spec: TransitionSpec) -> Self {
self.transition = Some(spec);
self
}
pub fn route(mut self, location: Location) -> Self {
self.route = Some(location);
self
}
}
pub(super) enum NavOp<State: 'static> {
Push {
builder: PageBuilder<State>,
opaque: bool,
on_result: Option<ResultCallback<State>>,
transition: Option<TransitionSpec>,
back: BackPolicy,
dismiss_signal: Option<Rc<Cell<u64>>>,
on_visibility: Option<VisibilityCallback>,
route: Option<Location>,
pop_swipe: Option<bool>,
},
Pop { result: PopResult },
RequestBack,
Replace {
builder: PageBuilder<State>,
opaque: bool,
transition: Option<TransitionSpec>,
route: Option<Location>,
},
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct NavigatorId(pub(super) usize);