mod compose;
pub mod legend;
pub mod rotated_label;
pub mod tick_labels;
pub use compose::Layout;
use crate::{
bounds::Bounds,
edge::Edge,
state::{PreState, State},
Tick,
};
use leptos::prelude::*;
#[derive(Clone)]
#[non_exhaustive]
pub enum EdgeLayout<XY: Tick> {
Legend(legend::Legend),
RotatedLabel(rotated_label::RotatedLabel),
TickLabels(tick_labels::TickLabels<XY>),
}
struct UseVerticalLayout {
width: Signal<f64>,
layout: UseLayout,
}
#[derive(Clone)]
enum UseLayout {
Legend(legend::Legend),
RotatedLabel(rotated_label::RotatedLabel),
TickLabels(tick_labels::UseTickLabels),
}
impl UseLayout {
fn render<X: Tick, Y: Tick>(
self,
edge: Edge,
bounds: Memo<Bounds>,
state: State<X, Y>,
) -> impl IntoView {
match self {
Self::Legend(inner) => view! {<legend::Legend legend=inner edge=edge bounds=bounds state=state />}.into_any(),
Self::RotatedLabel(inner) => view! {<rotated_label::RotatedLabel label=inner edge=edge bounds=bounds state=state />}.into_any(),
Self::TickLabels(inner) => view! {<tick_labels::TickLabels ticks=inner edge=edge bounds=bounds state=state />}.into_any(),
}
}
}
impl<X: Tick> EdgeLayout<X> {
fn fixed_height<Y: Tick>(&self, state: &PreState<X, Y>) -> Signal<f64> {
match self {
Self::Legend(inner) => inner.fixed_height(state),
Self::RotatedLabel(inner) => inner.fixed_height(state),
Self::TickLabels(inner) => inner.fixed_height(state),
}
}
fn to_horizontal_use<Y: Tick>(
&self,
state: &PreState<X, Y>,
avail_width: Memo<f64>,
) -> UseLayout {
match self {
Self::Legend(inner) => inner.to_horizontal_use(),
Self::RotatedLabel(inner) => inner.to_horizontal_use(),
Self::TickLabels(inner) => inner.to_horizontal_use(state, avail_width),
}
}
}
impl<Y: Tick> EdgeLayout<Y> {
fn to_vertical_use<X: Tick>(
&self,
state: &PreState<X, Y>,
avail_height: Memo<f64>,
) -> UseVerticalLayout {
match self {
Self::Legend(inner) => inner.to_vertical_use(state),
Self::RotatedLabel(inner) => inner.to_vertical_use(state),
Self::TickLabels(inner) => inner.to_vertical_use(state, avail_height),
}
}
}
pub trait IntoEdge<XY: Tick> {
fn into_edge(self) -> EdgeLayout<XY>;
}
macro_rules! impl_into_edge {
($ty:ty, $enum:ident) => {
impl<XY: Tick> IntoEdge<XY> for $ty {
fn into_edge(self) -> EdgeLayout<XY> {
EdgeLayout::$enum(self)
}
}
impl<XY: Tick> From<$ty> for EdgeLayout<XY> {
fn from(inner: $ty) -> Self {
inner.into_edge()
}
}
impl<XY: Tick> From<$ty> for Vec<EdgeLayout<XY>> {
fn from(inner: $ty) -> Self {
vec![inner.into_edge()]
}
}
};
}
impl_into_edge!(legend::Legend, Legend);
impl_into_edge!(rotated_label::RotatedLabel, RotatedLabel);
impl_into_edge!(tick_labels::TickLabels<XY>, TickLabels);