feat(chart): allow custom alignment of Y-Axis labels

pull/568/head
theogilbert 3 years ago
parent 807681ff47
commit 218858e983

@ -78,8 +78,8 @@ impl<'a> Axis<'a> {
/// Defines the alignment of the labels of the axis.
/// The alignment behaves differently based on the axis:
/// - Y-Axis: The labels are aligned in the area on the left of the axis
/// - X-Axis: The first label is aligned relative to the Y-axis
/// - Y-Axis: The labels are aligned within the area on the left of the axis
/// - X-Axis: The first X-axis label is aligned relative to the Y-axis
pub fn label_alignment(mut self, alignment: Alignment) -> Axis<'a> {
self.label_alignment = alignment;
self
@ -310,7 +310,7 @@ impl<'a> Chart<'a> {
}
layout.label_y = self.y_axis.labels.as_ref().and(Some(x));
x += self.max_width_of_labels_left_of_y_axis(area);
x += self.max_width_of_labels_left_of_y_axis(area, self.y_axis.labels.is_some());
if self.x_axis.labels.is_some() && y > area.top() {
layout.axis_x = Some(y);
@ -366,7 +366,7 @@ impl<'a> Chart<'a> {
layout
}
fn max_width_of_labels_left_of_y_axis(&self, area: Rect) -> u16 {
fn max_width_of_labels_left_of_y_axis(&self, area: Rect, has_y_axis: bool) -> u16 {
let mut max_width = self
.y_axis
.labels
@ -377,7 +377,10 @@ impl<'a> Chart<'a> {
if !x_labels.is_empty() {
let mut first_label_width = x_labels[0].content.width() as u16;
first_label_width = match self.x_axis.label_alignment {
Alignment::Left => first_label_width,
Alignment::Left => {
let y_axis_offset = if has_y_axis { 1 } else { 0 };
first_label_width.saturating_sub(y_axis_offset)
}
Alignment::Center => first_label_width / 2,
Alignment::Right => 0,
};
@ -482,11 +485,16 @@ impl<'a> Chart<'a> {
};
let labels = self.y_axis.labels.as_ref().unwrap();
let labels_len = labels.len() as u16;
let label_width = graph_area.left().saturating_sub(chart_area.left());
for (i, label) in labels.iter().enumerate() {
let dy = i as u16 * (graph_area.height - 1) / (labels_len - 1);
if dy < graph_area.bottom() {
buf.set_span(x, graph_area.bottom() - 1 - dy, label, label_width as u16);
let label_area = Rect::new(
x,
graph_area.bottom() - 1 - dy,
graph_area.left() - chart_area.left() - 1,
1,
);
Self::render_label(buf, label, label_area, self.y_axis.label_alignment);
}
}
}

@ -169,16 +169,13 @@ fn widgets_chart_handles_x_axis_labels_alignments() {
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
let datasets = vec![Dataset::default()
.marker(symbols::Marker::Braille)
.style(Style::default().fg(Color::Magenta))
.data(&[(2.0, 2.0)])];
let x_axis = Axis::default()
.bounds([0.0, 1.0])
.labels(vec![Span::from("AAAA"), Span::from("B"), Span::from("C")])
.label_alignment(alignment);
let y_axis = Axis::default().bounds([0.0, 1.0]);
let chart = Chart::new(datasets).x_axis(x_axis).y_axis(y_axis);
let y_axis = Axis::default();
let chart = Chart::new(vec![]).x_axis(x_axis).y_axis(y_axis);
f.render_widget(chart, f.size());
})
.unwrap();
@ -217,6 +214,58 @@ fn widgets_chart_handles_x_axis_labels_alignments() {
);
}
#[test]
fn widgets_chart_handles_y_axis_labels_alignments() {
let test_case = |y_alignment, lines| {
let backend = TestBackend::new(20, 5);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
let x_axis = Axis::default().labels(create_labels(&["AAAAA", "B"]));
let y_axis = Axis::default()
.labels(create_labels(&["C", "D"]))
.label_alignment(y_alignment);
let chart = Chart::new(vec![]).x_axis(x_axis).y_axis(y_axis);
f.render_widget(chart, f.size());
})
.unwrap();
let expected = Buffer::with_lines(lines);
terminal.backend().assert_buffer(&expected);
};
test_case(
Alignment::Left,
vec![
"D │ ",
" │ ",
"C │ ",
" └───────────────",
"AAAAA B",
],
);
test_case(
Alignment::Center,
vec![
" D │ ",
" │ ",
" C │ ",
" └───────────────",
"AAAAA B",
],
);
test_case(
Alignment::Right,
vec![
" D│ ",
" │ ",
" C│ ",
" └───────────────",
"AAAAA B",
],
);
}
#[test]
fn widgets_chart_can_have_axis_with_zero_length_bounds() {
let backend = TestBackend::new(100, 100);

Loading…
Cancel
Save