tui_piechart/legend.rs
1//! Legend positioning and layout configuration for pie charts.
2//!
3//! This module provides types and functionality for controlling where and how
4//! the legend is displayed relative to the pie chart.
5//!
6//! # Examples
7//!
8//! ```
9//! use tui_piechart::{PieChart, PieSlice, LegendPosition, LegendLayout, LegendAlignment};
10//! use ratatui::style::Color;
11//!
12//! let slices = vec![
13//! PieSlice::new("Rust", 45.0, Color::Red),
14//! PieSlice::new("Go", 30.0, Color::Blue),
15//! PieSlice::new("Python", 25.0, Color::Green),
16//! ];
17//!
18//! // Position legend on the left with horizontal layout and center alignment
19//! let chart = PieChart::new(slices)
20//! .legend_position(LegendPosition::Left)
21//! .legend_layout(LegendLayout::Horizontal)
22//! .legend_alignment(LegendAlignment::Center);
23//! ```
24
25/// Position of the legend relative to the pie chart.
26///
27/// Controls where the legend appears in relation to the pie chart visualization.
28/// The legend can be positioned on any of the four sides: right (default), left,
29/// top, or bottom.
30///
31/// # Examples
32///
33/// ```
34/// use tui_piechart::{PieChart, PieSlice, LegendPosition};
35/// use ratatui::style::Color;
36///
37/// let slices = vec![PieSlice::new("Rust", 45.0, Color::Red)];
38///
39/// // Position legend on the left side
40/// let chart = PieChart::new(slices)
41/// .legend_position(LegendPosition::Left);
42/// ```
43///
44/// # Layout Impact
45///
46/// The legend position affects how space is allocated:
47/// - **Right/Left**: Legend takes a portion of horizontal space
48/// - **Top/Bottom**: Legend takes a portion of vertical space
49///
50/// The chart automatically adjusts its size to accommodate the legend.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
52pub enum LegendPosition {
53 /// Legend on the right side (default)
54 ///
55 /// The legend appears to the right of the pie chart. This is the default
56 /// position and works well for most use cases.
57 #[default]
58 Right,
59
60 /// Legend on the left side
61 ///
62 /// The legend appears to the left of the pie chart. Useful when you want
63 /// the chart to be more prominent on the right side of the display.
64 Left,
65
66 /// Legend at the top
67 ///
68 /// The legend appears above the pie chart. Best used with horizontal layout
69 /// for a more compact display.
70 Top,
71
72 /// Legend at the bottom
73 ///
74 /// The legend appears below the pie chart. Works well with horizontal layout
75 /// when vertical space is limited.
76 Bottom,
77}
78
79/// Layout mode for the legend.
80///
81/// Controls how legend items are arranged: either stacked vertically in a column
82/// (default) or arranged horizontally in a single row.
83///
84/// # Examples
85///
86/// ```
87/// use tui_piechart::{PieChart, PieSlice, LegendLayout, LegendPosition};
88/// use ratatui::style::Color;
89///
90/// let slices = vec![
91/// PieSlice::new("Rust", 45.0, Color::Red),
92/// PieSlice::new("Go", 30.0, Color::Blue),
93/// ];
94///
95/// // Use horizontal layout with legend at top
96/// let chart = PieChart::new(slices)
97/// .legend_position(LegendPosition::Top)
98/// .legend_layout(LegendLayout::Horizontal);
99/// ```
100///
101/// # Layout Considerations
102///
103/// - **Vertical**: Each legend item takes one line. Best for detailed legends
104/// with longer labels or when vertical space is available.
105/// - **Horizontal**: All legend items on one line. Best for compact displays
106/// or when used with Top/Bottom positions.
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
108pub enum LegendLayout {
109 /// Vertical layout - items stacked vertically (default)
110 ///
111 /// Each legend item appears on its own line, stacked vertically:
112 /// ```text
113 /// ● Item 1 45%
114 /// ● Item 2 30%
115 /// ● Item 3 25%
116 /// ```
117 ///
118 /// This is the default layout and provides clear separation between items.
119 #[default]
120 Vertical,
121
122 /// Horizontal layout - items in a single row
123 ///
124 /// All legend items appear in a single horizontal row:
125 /// ```text
126 /// ● Item 1 45% ● Item 2 30% ● Item 3 25%
127 /// ```
128 ///
129 /// This layout is more compact and works well with Top/Bottom positions.
130 /// The chart automatically calculates required width to prevent item cutoff.
131 Horizontal,
132}
133
134/// Alignment of legend items within the legend area.
135///
136/// Controls how legend items are aligned horizontally within their allocated space.
137/// This is particularly useful in grid layouts or when the legend area is wider
138/// than the legend content.
139///
140/// # Examples
141///
142/// ```
143/// use tui_piechart::{PieChart, PieSlice, LegendAlignment};
144/// use ratatui::style::Color;
145///
146/// let slices = vec![
147/// PieSlice::new("Rust", 45.0, Color::Red),
148/// PieSlice::new("Go", 30.0, Color::Blue),
149/// ];
150///
151/// // Center-align legend items
152/// let chart = PieChart::new(slices)
153/// .legend_alignment(LegendAlignment::Center);
154/// ```
155///
156/// # Layout Considerations
157///
158/// - **Left**: Legend items start from the left edge (default)
159/// - **Center**: Legend items are centered within the legend area
160/// - **Right**: Legend items align to the right edge
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
162pub enum LegendAlignment {
163 /// Left alignment (default)
164 ///
165 /// Legend items start from the left edge of the legend area.
166 /// This is the default alignment.
167 #[default]
168 Left,
169
170 /// Center alignment
171 ///
172 /// Legend items are centered within the legend area.
173 /// Useful for creating balanced, symmetric layouts.
174 Center,
175
176 /// Right alignment
177 ///
178 /// Legend items align to the right edge of the legend area.
179 Right,
180}
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 #[test]
187 fn legend_position_default() {
188 assert_eq!(LegendPosition::default(), LegendPosition::Right);
189 }
190
191 #[test]
192 fn legend_layout_default() {
193 assert_eq!(LegendLayout::default(), LegendLayout::Vertical);
194 }
195
196 #[test]
197 fn legend_position_clone() {
198 let pos = LegendPosition::Left;
199 let cloned = pos;
200 assert_eq!(pos, cloned);
201 }
202
203 #[test]
204 fn legend_layout_clone() {
205 let layout = LegendLayout::Horizontal;
206 let cloned = layout;
207 assert_eq!(layout, cloned);
208 }
209
210 #[test]
211 fn legend_position_debug() {
212 let pos = LegendPosition::Top;
213 let debug = format!("{pos:?}");
214 assert_eq!(debug, "Top");
215 }
216
217 #[test]
218 fn legend_layout_debug() {
219 let layout = LegendLayout::Vertical;
220 let debug = format!("{layout:?}");
221 assert_eq!(debug, "Vertical");
222 }
223
224 #[test]
225 fn legend_alignment_default() {
226 assert_eq!(LegendAlignment::default(), LegendAlignment::Left);
227 }
228
229 #[test]
230 fn legend_alignment_clone() {
231 let alignment = LegendAlignment::Center;
232 let cloned = alignment;
233 assert_eq!(alignment, cloned);
234 }
235
236 #[test]
237 fn legend_alignment_debug() {
238 let alignment = LegendAlignment::Right;
239 let debug = format!("{:?}", alignment);
240 assert_eq!(debug, "Right");
241 }
242}