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}