Skip to content

Commit

Permalink
feat(widgets/chart): add option to set the position of legend
Browse files Browse the repository at this point in the history
  • Loading branch information
lyuha committed Aug 6, 2023
1 parent c8ddc16 commit 7f7fbc0
Show file tree
Hide file tree
Showing 3 changed files with 807 additions and 11 deletions.
3 changes: 2 additions & 1 deletion examples/chart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, app: &App) {
.style(Style::default().fg(Color::Gray))
.bounds([0.0, 5.0])
.labels(vec!["0".bold(), "2.5".into(), "5".bold()]),
);
)
.legend_position(Corner::BottomLeft);
f.render_widget(chart, chunks[2]);
}
51 changes: 42 additions & 9 deletions src/widgets/chart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use unicode_width::UnicodeWidthStr;

use crate::{
buffer::Buffer,
layout::{Alignment, Constraint, Rect},
layout::{Alignment, Constraint, Corner, Rect},
style::{Color, Style, Styled},
symbols,
text::{Line as TextLine, Span},
Expand Down Expand Up @@ -202,6 +202,8 @@ pub struct Chart<'a> {
style: Style,
/// Constraints used to determine whether the legend should be shown or not
hidden_legend_constraints: (Constraint, Constraint),
/// The position of a legend
legend_position: Corner,
}

impl<'a> Chart<'a> {
Expand All @@ -213,6 +215,7 @@ impl<'a> Chart<'a> {
style: Style::default(),
datasets,
hidden_legend_constraints: (Constraint::Ratio(1, 4), Constraint::Ratio(1, 4)),
legend_position: Corner::TopRight,
}
}

Expand Down Expand Up @@ -257,6 +260,21 @@ impl<'a> Chart<'a> {
self
}

/// Set the position of a legend.
///
/// # Examples
///
/// ```
/// # use ratatui::widgets::Chart;
/// # use ratatui::layout::Corner;
/// let _chart: Chart = Chart::new(vec![])
/// .legend_position(Corner::TopLeft);
/// ```
pub fn legend_position(mut self, position: Corner) -> Chart<'a> {
self.legend_position = position;
self
}

/// Compute the internal layout of the chart given the area. If the area is too small some
/// elements may be automatically hidden
fn layout(&self, area: Rect) -> ChartLayout {
Expand Down Expand Up @@ -318,12 +336,27 @@ impl<'a> Chart<'a> {
&& legend_width < max_legend_width
&& legend_height < max_legend_height
{
layout.legend_area = Some(Rect::new(
layout.graph_area.right() - legend_width,
layout.graph_area.top(),
legend_width,
legend_height,
));
let (x, y) = match self.legend_position {
Corner::TopRight => (
layout.graph_area.right() - legend_width,
layout.graph_area.top(),
),
Corner::TopLeft => (
layout.graph_area.left(),
layout.graph_area.top() + if self.y_axis.title.is_some() { 1 } else { 0 },
),
Corner::BottomRight => (
layout.graph_area.right() - legend_width,
layout.graph_area.bottom()
- legend_height
- if self.x_axis.title.is_some() { 1 } else { 0 },
),
Corner::BottomLeft => (
layout.graph_area.left(),
layout.graph_area.bottom() - legend_height,
),
};
layout.legend_area = Some(Rect::new(x, y, legend_width, legend_height));
}
}
layout
Expand Down Expand Up @@ -559,7 +592,7 @@ impl<'a> Widget for Chart<'a> {

if let Some((x, y)) = layout.title_x {
let title = self.x_axis.title.unwrap();
let width = graph_area.right().saturating_sub(x);
let width = title.width() as u16;
buf.set_style(
Rect {
x,
Expand All @@ -574,7 +607,7 @@ impl<'a> Widget for Chart<'a> {

if let Some((x, y)) = layout.title_y {
let title = self.y_axis.title.unwrap();
let width = graph_area.right().saturating_sub(x);
let width = title.width() as u16;
buf.set_style(
Rect {
x,
Expand Down

0 comments on commit 7f7fbc0

Please sign in to comment.