use topcoat_core::context::Cx;
use topcoat_view::BoxView;
use crate::{Body, Layout, Methods, Page, Path, PathBuf, RouteId, Slot, route};
#[doc(hidden)]
pub trait ModulePage: Send + Sync + 'static {
fn id(&self) -> RouteId;
fn methods(&self) -> Methods<'_>;
fn module_path(&self) -> &'static str;
fn render<'a>(&'a self, cx: &'a Cx, body: Body) -> BoxView<'a>;
fn is_current(&self, cx: &Cx) -> bool {
route(cx).id() == self.id()
}
}
impl<P: ModulePage + ?Sized> ModulePage for &'static P {
fn id(&self) -> RouteId {
(**self).id()
}
fn methods(&self) -> Methods<'_> {
(**self).methods()
}
fn module_path(&self) -> &'static str {
(**self).module_path()
}
fn render<'a>(&'a self, cx: &'a Cx, body: Body) -> BoxView<'a> {
(**self).render(cx, body)
}
}
#[cfg(feature = "discover")]
inventory::collect!(&'static dyn ModulePage);
pub(super) struct ResolvedPage<P> {
page: P,
path: PathBuf,
}
impl<P: ModulePage> ResolvedPage<P> {
pub(super) fn new(page: P, path: PathBuf) -> Self {
Self { page, path }
}
}
impl<P: ModulePage> Page for ResolvedPage<P> {
fn id(&self) -> RouteId {
self.page.id()
}
fn methods(&self) -> Methods<'_> {
self.page.methods()
}
fn path(&self) -> &Path {
&self.path
}
fn render<'a>(&'a self, cx: &'a Cx, body: Body) -> BoxView<'a> {
self.page.render(cx, body)
}
}
#[doc(hidden)]
pub trait ModuleLayout: Send + Sync + 'static {
fn module_path(&self) -> &'static str;
fn render<'a>(&'a self, cx: &'a Cx, slot: Slot<'a>) -> BoxView<'a>;
}
impl<L: ModuleLayout + ?Sized> ModuleLayout for &'static L {
fn module_path(&self) -> &'static str {
(**self).module_path()
}
fn render<'a>(&'a self, cx: &'a Cx, slot: Slot<'a>) -> BoxView<'a> {
(**self).render(cx, slot)
}
}
#[cfg(feature = "discover")]
inventory::collect!(&'static dyn ModuleLayout);
pub(super) struct ResolvedLayout<L> {
layout: L,
path: PathBuf,
}
impl<L: ModuleLayout> ResolvedLayout<L> {
pub(super) fn new(layout: L, path: PathBuf) -> Self {
Self { layout, path }
}
}
impl<L: ModuleLayout> Layout for ResolvedLayout<L> {
fn path(&self) -> &Path {
&self.path
}
fn render<'a>(&'a self, cx: &'a Cx, slot: Slot<'a>) -> BoxView<'a> {
self.layout.render(cx, slot)
}
}