Skip to main content

leptos_chartistry/inner/
legend.rs

1use crate::{edge::Edge, state::State, Anchor, Legend, Tick};
2use leptos::prelude::*;
3
4/// Builds an inset legend for the chart [series](crate::Series). Differs from [Legend](struct@Legend) by being placed inside the chart area.
5#[derive(Clone, Debug, PartialEq)]
6#[non_exhaustive]
7pub struct InsetLegend {
8    /// Edge of the chart area to place the legend.
9    pub edge: RwSignal<Edge>,
10    /// Legend to display. Relies on the internal `anchor` signal. See [Legend](struct@Legend) for details.
11    pub legend: Legend,
12}
13
14impl InsetLegend {
15    fn new(edge: Edge, anchor: Anchor) -> Self {
16        Self {
17            edge: RwSignal::new(edge),
18            legend: Legend::new(anchor),
19        }
20    }
21
22    /// Creates a new inset legend placed at the top-left corner of the chart area.
23    pub fn top_left() -> Self {
24        Self::new(Edge::Top, Anchor::Start)
25    }
26    /// Creates a new inset legend placed at the top-middle of the chart area.
27    pub fn top() -> Self {
28        Self::new(Edge::Top, Anchor::Middle)
29    }
30    /// Creates a new inset legend placed at the top-right corner of the chart area.
31    pub fn top_right() -> Self {
32        Self::new(Edge::Top, Anchor::End)
33    }
34    /// Creates a new inset legend placed at the bottom-left corner of the chart area.
35    pub fn bottom_left() -> Self {
36        Self::new(Edge::Bottom, Anchor::Start)
37    }
38    /// Creates a new inset legend placed at the bottom-middle of the chart area.
39    pub fn bottom() -> Self {
40        Self::new(Edge::Bottom, Anchor::Middle)
41    }
42    /// Creates a new inset legend placed at the bottom-right corner of the chart area.
43    pub fn bottom_right() -> Self {
44        Self::new(Edge::Bottom, Anchor::End)
45    }
46    /// Creates a new inset legend placed at the left-middle of the chart area.
47    pub fn left() -> Self {
48        Self::new(Edge::Left, Anchor::Middle)
49    }
50    /// Creates a new inset legend placed at the right-middle of the chart area.
51    pub fn right() -> Self {
52        Self::new(Edge::Right, Anchor::Middle)
53    }
54}
55
56#[component]
57pub(super) fn InsetLegend<X: Tick, Y: Tick>(
58    legend: InsetLegend,
59    state: State<X, Y>,
60) -> impl IntoView {
61    let InsetLegend { edge, legend } = legend;
62    let inner = state.layout.inner;
63    let width = Legend::width(&state.pre);
64    let height = legend.fixed_height(&state.pre);
65    let bounds = Memo::new(move |_| {
66        let inner = inner.get();
67        let height = height.get();
68        let width = width.get();
69        // Build legend bounds as an inset of the chart bounds
70        let (top, right, bottom, left) = match edge.get() {
71            Edge::Top => (0.0, 0.0, inner.height() - height, 0.0),
72            Edge::Bottom => (inner.height() - height, 0.0, 0.0, 0.0),
73            Edge::Left => (0.0, inner.width() - width, 0.0, 0.0),
74            Edge::Right => (0.0, 0.0, 0.0, inner.width() - width),
75        };
76        inner.shrink(top, right, bottom, left)
77    });
78
79    view! {
80        <g class="_chartistry_legend_inset">
81            <Legend legend=legend edge=edge bounds=bounds state=state />
82        </g>
83    }
84    .into_any()
85}