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)]
183#[allow(unnameable_test_items)]
184mod tests {
185 use super::*;
186 use crate::{debug_format_tests, enum_tests};
187
188 enum_tests! {
189 enum_type: LegendPosition,
190 default_test: (legend_position_default, LegendPosition::Right),
191 clone_test: (legend_position_clone, LegendPosition::Left),
192 debug_test: (legend_position_debug, LegendPosition::Top, "Top"),
193 }
194
195 enum_tests! {
196 enum_type: LegendLayout,
197 default_test: (legend_layout_default, LegendLayout::Vertical),
198 clone_test: (legend_layout_clone, LegendLayout::Horizontal),
199 debug_test: (legend_layout_debug, LegendLayout::Vertical, "Vertical"),
200 }
201
202 enum_tests! {
203 enum_type: LegendAlignment,
204 default_test: (legend_alignment_default, LegendAlignment::Left),
205 clone_test: (legend_alignment_clone, LegendAlignment::Center),
206 debug_test: (legend_alignment_debug, LegendAlignment::Right, "Right"),
207 }
208
209 // Exhaustive debug-format coverage for every variant.
210 debug_format_tests! {
211 enum_type: LegendPosition,
212 tests: [
213 (legend_position_debug_left, LegendPosition::Left, "Left"),
214 (legend_position_debug_right, LegendPosition::Right, "Right"),
215 (legend_position_debug_bottom, LegendPosition::Bottom, "Bottom"),
216 ]
217 }
218
219 debug_format_tests! {
220 enum_type: LegendAlignment,
221 tests: [
222 (legend_alignment_debug_left, LegendAlignment::Left, "Left"),
223 (legend_alignment_debug_center, LegendAlignment::Center, "Center"),
224 ]
225 }
226}