1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use crateLegendEntry;
/// A plot cell that renders only a legend — no axes, no data.
///
/// `LegendPlot` is designed for two situations:
///
/// 1. **Shared legend in a figure.** Place it in any adjacent cell so multiple
/// data panels can share one legend without duplicating it.
/// 2. **Standalone use.** Render a freestanding legend key outside of any figure,
/// e.g. to composite with an externally produced image.
///
/// Entries can be supplied directly or collected from a set of plots via
/// [`collect_legend_entries`](crate::render::render::collect_legend_entries).
///
/// # Column layout
///
/// By default the number of columns is chosen automatically: the renderer
/// estimates each entry's pixel width from the longest label (using a 0.68
/// character-width factor at the current font size) and packs as many columns
/// as fit across the available cell width. Call [`with_cols`](Self::with_cols)
/// to pin the column count instead.
///
/// # Examples
///
/// ## Shared legend below a scatter plot
///
/// ```rust
/// use kuva::prelude::*;
/// use kuva::render::render::collect_legend_entries;
///
/// let scatter = ScatterPlot::new()
/// .with_data(vec![(1.0_f64, 2.0), (3.0, 4.0)])
/// .with_color("steelblue");
///
/// // Collect entries from the data plots, then hand them to a LegendPlot cell.
/// let data_plots: Vec<Plot> = vec![scatter.into()];
/// let entries = collect_legend_entries(&data_plots);
///
/// let legend_cell = LegendPlot::from_entries(entries);
///
/// let fig = Figure::new(2, 1) // two rows, one column
/// .with_cell_size(600.0, 400.0)
/// .with_plots(vec![
/// data_plots, // row 0 — the chart
/// vec![legend_cell.into()], // row 1 — the legend
/// ]);
/// let svg = fig.render();
/// # let _ = svg;
/// ```
///
/// ## Legend to the right of the chart
///
/// ```rust
/// use kuva::prelude::*;
/// use kuva::render::render::collect_legend_entries;
///
/// let scatter = ScatterPlot::new()
/// .with_data(vec![(1.0_f64, 2.0), (3.0, 4.0)])
/// .with_color("steelblue");
///
/// let data_plots: Vec<Plot> = vec![scatter.into()];
/// let entries = collect_legend_entries(&data_plots);
///
/// let legend_cell = LegendPlot::from_entries(entries).with_cols(1);
///
/// let fig = Figure::new(1, 2) // one row, two columns
/// .with_cell_size(500.0, 400.0)
/// .with_plots(vec![
/// data_plots,
/// vec![legend_cell.into()],
/// ]);
/// # let _ = fig.render();
/// ```
///
/// ## Manual entries with a title
///
/// ```rust
/// use kuva::prelude::*;
///
/// let entries = vec![
/// LegendEntry { label: "Treatment".into(), color: "#4477AA".into(),
/// shape: LegendShape::Rect, dasharray: None },
/// LegendEntry { label: "Control".into(), color: "#EE6677".into(),
/// shape: LegendShape::Rect, dasharray: None },
/// ];
///
/// let lp = LegendPlot::from_entries(entries)
/// .with_title("Groups")
/// .with_cols(2);
/// # let _ = lp;
/// ```