#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#[cfg(feature = "async")]
mod async_route;
mod handler;
pub mod history;
mod route_kind;
mod router;
mod router_builder;
pub mod transition;
use crate::history::HistoryError;
use crate::transition::{ActiveTransition, SlideFadeTransition, SlideTransition, Transition};
use egui::emath::ease_in_ease_out;
use egui::{Ui, Vec2};
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::sync::atomic::AtomicUsize;
pub use handler::{HandlerError, HandlerResult};
pub use router::EguiRouter;
pub use router_builder::RouterBuilder;
pub trait Route<State = ()> {
fn ui(&mut self, ui: &mut egui::Ui, state: &mut State);
fn on_showing(&mut self) {}
fn on_shown(&mut self) {}
fn on_hiding(&mut self) {}
fn on_hide(&mut self) {}
fn enable_swipe(&self) -> Option<bool> {
None
}
}
impl<F: FnMut(&mut Ui, &mut State), State> Route<State> for F {
fn ui(&mut self, ui: &mut egui::Ui, state: &mut State) {
self(ui, state);
}
}
static ID: AtomicUsize = AtomicUsize::new(0);
struct RouteState<State> {
path_with_query: String,
route: HandlerResult<Box<dyn Route<State>>>,
id: usize,
state: u32,
}
pub type RouterResult<T = ()> = Result<T, RouterError>;
#[derive(Debug, thiserror::Error)]
pub enum RouterError {
#[error("History error: {0}")]
HistoryError(HistoryError),
#[error("Route not found")]
NotFound,
}
impl From<HistoryError> for RouterError {
fn from(err: HistoryError) -> Self {
Self::HistoryError(err)
}
}
#[derive(Debug, Clone)]
pub struct TransitionConfig {
duration: Option<f32>,
easing: fn(f32) -> f32,
in_: Transition,
out: Transition,
}
impl Default for TransitionConfig {
fn default() -> Self {
Self {
duration: None,
easing: ease_in_ease_out,
in_: transition::SlideTransition::new(Vec2::X).into(),
out: transition::SlideTransition::new(Vec2::X * -0.1).into(),
}
}
}
impl TransitionConfig {
pub fn new(in_: impl Into<Transition>, out: impl Into<Transition>) -> Self {
Self {
in_: in_.into(),
out: out.into(),
..Self::default()
}
}
pub fn slide() -> Self {
Self::default()
}
pub fn fade_up() -> Self {
Self::new(
SlideFadeTransition(
SlideTransition::new(Vec2::Y * 0.3),
transition::FadeTransition,
),
transition::NoTransition,
)
}
pub fn fade() -> Self {
Self::new(transition::FadeTransition, transition::FadeTransition)
}
pub fn none() -> Self {
Self::new(transition::NoTransition, transition::NoTransition)
}
pub fn with_easing(mut self, easing: fn(f32) -> f32) -> Self {
self.easing = easing;
self
}
pub fn with_duration(mut self, duration: f32) -> Self {
self.duration = Some(duration);
self
}
}
struct CurrentTransition<State> {
active_transition: ActiveTransition,
leaving_route: Option<RouteState<State>>,
}
pub struct Request<'a, State = ()> {
pub params: matchit::Params<'a, 'a>,
pub query: BTreeMap<Cow<'a, str>, Cow<'a, str>>,
pub state: &'a mut State,
}
#[cfg(feature = "async")]
pub struct OwnedRequest<State = ()> {
pub params: BTreeMap<String, String>,
pub query: BTreeMap<String, String>,
pub state: State,
}