Skip to main content

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}