feat(barchart)!: allow axes to accept Lines (#1273)

Fixes: https://github.com/ratatui-org/ratatui/issues/1272
This commit is contained in:
Josh McKinney 2024-08-03 16:16:57 -07:00 committed by GitHub
parent edc2af9822
commit 8d4a1026ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 23 deletions

View file

@ -13,6 +13,7 @@ This is a quick summary of the sections below:
- [v0.28.0](#v0280) (unreleased)
- `Layout::init_cache` no longer returns bool and takes a `NonZeroUsize` instead of `usize`
- `ratatui::terminal` module is now private
- `Axis::labels` now accepts `Vec<T: Into<Line>>`
- [v0.27.0](#v0270)
- List no clamps the selected index to list
- Prelude items added / removed
@ -61,6 +62,17 @@ This is a quick summary of the sections below:
## v0.28.0 (unreleased)
### `Axis::labels()` now accepts `Vec<T: Into<Line>>` ([#1273])
[#1273]: https://github.com/ratatui-org/ratatui/pull/1173
Previously Axis::labels accepted `Vec<Span>`. Any code that uses conversion methods that infer the
type will need to be rewritten as the compiler cannot infer the correct type.
```diff
- Axis::default().labels("a".into(), "b".into())
+ Axis::default().labels("a", "b")
### `Layout::init_cache` no longer returns bool and takes a `NonZeroUsize` instead of `usize` ([#1145])
[#1145]: https://github.com/ratatui-org/ratatui/pull/1145

View file

@ -325,14 +325,14 @@ fn render_scatter(f: &mut Frame, area: Rect) {
.title("Year")
.bounds([1960., 2020.])
.style(Style::default().fg(Color::Gray))
.labels(vec!["1960".into(), "1990".into(), "2020".into()]),
.labels(vec!["1960", "1990", "2020"]),
)
.y_axis(
Axis::default()
.title("Cost")
.bounds([0., 75000.])
.style(Style::default().fg(Color::Gray))
.labels(vec!["0".into(), "37 500".into(), "75 000".into()]),
.labels(vec!["0", "37 500", "75 000"]),
)
.hidden_legend_constraints((Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)));

View file

@ -39,7 +39,7 @@ pub struct Axis<'a> {
/// Bounds for the axis (all data points outside these limits will not be represented)
bounds: [f64; 2],
/// A list of labels to put to the left or below the axis
labels: Option<Vec<Span<'a>>>,
labels: Option<Vec<Line<'a>>>,
/// The style used to draw the axis itself
style: Style,
/// The alignment of the labels of the Axis
@ -84,6 +84,11 @@ impl<'a> Axis<'a> {
///
/// [issue 334]: https://github.com/ratatui-org/ratatui/issues/334
///
/// `labels` is a vector of any type that can be converted into a [`Line`] (e.g. `&str`,
/// `String`, `&Line`, `Span`, ...). This allows you to style the labels using the methods
/// provided by [`Line`]. Any alignment set on the labels will be ignored as the alignment is
/// determined by the axis.
///
/// This is a fluent setter method which must be chained or used as it consumes self
///
/// # Examples
@ -96,8 +101,8 @@ impl<'a> Axis<'a> {
/// .labels(vec!["0".bold(), "25".into(), "50".bold()]);
/// ```
#[must_use = "method moves the value of self and returns the modified value"]
pub fn labels(mut self, labels: Vec<Span<'a>>) -> Self {
self.labels = Some(labels);
pub fn labels<T: Into<Line<'a>>>(mut self, labels: Vec<T>) -> Self {
self.labels = Some(labels.into_iter().map(Into::into).collect());
self
}
@ -469,14 +474,14 @@ struct ChartLayout {
/// .title("X Axis".red())
/// .style(Style::default().white())
/// .bounds([0.0, 10.0])
/// .labels(vec!["0.0".into(), "5.0".into(), "10.0".into()]);
/// .labels(vec!["0.0", "5.0", "10.0"]);
///
/// // Create the Y axis and define its properties
/// let y_axis = Axis::default()
/// .title("Y Axis".red())
/// .style(Style::default().white())
/// .bounds([0.0, 10.0])
/// .labels(vec!["0.0".into(), "5.0".into(), "10.0".into()]);
/// .labels(vec!["0.0", "5.0", "10.0"]);
///
/// // Create the chart and link all the parts together
/// let chart = Chart::new(datasets)
@ -578,7 +583,7 @@ impl<'a> Chart<'a> {
/// Axis::default()
/// .title("X Axis")
/// .bounds([0.0, 20.0])
/// .labels(vec!["0".into(), "20".into()]),
/// .labels(vec!["0", "20"]),
/// );
/// ```
#[must_use = "method moves the value of self and returns the modified value"]
@ -601,7 +606,7 @@ impl<'a> Chart<'a> {
/// Axis::default()
/// .title("Y Axis")
/// .bounds([0.0, 20.0])
/// .labels(vec!["0".into(), "20".into()]),
/// .labels(vec!["0", "20"]),
/// );
/// ```
#[must_use = "method moves the value of self and returns the modified value"]
@ -807,7 +812,7 @@ impl<'a> Chart<'a> {
.y_axis
.labels
.as_ref()
.map(|l| l.iter().map(Span::width).max().unwrap_or_default() as u16)
.map(|l| l.iter().map(Line::width).max().unwrap_or_default() as u16)
.unwrap_or_default();
if let Some(first_x_label) = self
@ -903,17 +908,13 @@ impl<'a> Chart<'a> {
Rect::new(min_x, y, max_x - min_x, 1)
}
fn render_label(buf: &mut Buffer, label: &Span, label_area: Rect, alignment: Alignment) {
let label_width = label.width() as u16;
let bounded_label_width = label_area.width.min(label_width);
let x = match alignment {
Alignment::Left => label_area.left(),
Alignment::Center => label_area.left() + label_area.width / 2 - bounded_label_width / 2,
Alignment::Right => label_area.right() - bounded_label_width,
fn render_label(buf: &mut Buffer, label: &Line, label_area: Rect, alignment: Alignment) {
let label = match alignment {
Alignment::Left => label.clone().left_aligned(),
Alignment::Center => label.clone().centered(),
Alignment::Right => label.clone().right_aligned(),
};
buf.set_span(x, label_area.top(), label, bounded_label_width);
label.render(label_area, buf);
}
fn render_y_labels(

View file

@ -203,7 +203,7 @@ fn widgets_chart_handles_long_labels<'line, Lines>(
" ",
" ",
"──────────",
"AAA B C",
"AAA B C",
],
)]
fn widgets_chart_handles_x_axis_labels_alignments<'line, Lines>(
@ -229,9 +229,9 @@ fn widgets_chart_handles_x_axis_labels_alignments<'line, Lines>(
"AAAAA B",
])]
#[case::center(Alignment::Center, [
" D │ ",
" D ",
"",
" C │ ",
" C ",
" └───────────────",
"AAAAA B",
])]