Skip to content

Commit

Permalink
feat(barchart): set custom text value in the bar (ratatui#309)
Browse files Browse the repository at this point in the history
for now the value is converted to a string and then printed. in many
cases the values are too wide or double values. so it make sense
to set a custom value text instead of the default behavior.

this patch suggests to add a method
"fn text_value(mut self, text_value: String)"
to the Bar, which allows to override the value printed in the bar

Signed-off-by: Ben Fekih, Hichem <[email protected]>
  • Loading branch information
karthago1 authored and a-kenji committed Jul 16, 2023
1 parent e52104e commit 93161c5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 30 deletions.
9 changes: 5 additions & 4 deletions examples/barchart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,17 @@ impl<'a> App<'a> {
companies: [
Company {
label: "Comp.A",
revenue: [9, 12, 5, 8],
revenue: [9500, 12500, 5300, 8500],
bar_style: Style::default().fg(Color::Green),
},
Company {
label: "Comp.B",
revenue: [1, 2, 3, 4],
revenue: [1500, 2500, 3000, 4100],
bar_style: Style::default().fg(Color::Yellow),
},
Company {
label: "Comp.C",
revenue: [10, 10, 9, 4],
revenue: [10500, 10600, 9000, 4200],
bar_style: Style::default().fg(Color::White),
},
],
Expand Down Expand Up @@ -182,7 +182,8 @@ where
Style::default()
.bg(c.bar_style.fg.unwrap())
.fg(Color::Black),
);
)
.text_value(format!("{:.1}", (c.revenue[i] as f64) / 1000.));
if bar_labels {
bar = bar.label(c.label.into());
}
Expand Down
44 changes: 25 additions & 19 deletions src/widgets/barchart/bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use crate::{buffer::Buffer, style::Style, text::Line};
/// .label("Bar 1".into())
/// .value(10)
/// .style(Style::default().fg(Color::Red))
/// .value_style(Style::default().bg(Color::Red).fg(Color::White));
/// .value_style(Style::default().bg(Color::Red).fg(Color::White))
/// .text_value("10°C".to_string());
/// ```
#[derive(Debug, Clone, Default)]
pub struct Bar<'a> {
Expand All @@ -24,6 +25,8 @@ pub struct Bar<'a> {
pub(super) style: Style,
/// style of the value printed at the bottom of the bar.
pub(super) value_style: Style,
/// optional text_value to be shown on the bar instead of the actual value
pub(super) text_value: Option<String>,
}

impl<'a> Bar<'a> {
Expand All @@ -47,43 +50,46 @@ impl<'a> Bar<'a> {
self
}

/// render the bar's value
pub(super) fn render_value(
&self,
/// set the text value printed in the bar. (By default self.value is printed)
pub fn text_value(mut self, text_value: String) -> Bar<'a> {
self.text_value = Some(text_value);
self
}

pub(super) fn render_label_and_value(
self,
buf: &mut Buffer,
max_width: u16,
x: u16,
y: u16,
default_style: Style,
default_value_style: Style,
default_label_style: Style,
) {
// render the value
if self.value != 0 {
let value_label = format!("{}", self.value);
let value_label = if let Some(text) = self.text_value {
text
} else {
self.value.to_string()
};

let width = value_label.len() as u16;
if width < max_width {
buf.set_string(
x + (max_width.saturating_sub(value_label.len() as u16) >> 1),
y,
value_label,
self.value_style.patch(default_style),
self.value_style.patch(default_value_style),
);
}
}
}

/// render the bar's label
pub(super) fn render_label(
self,
buf: &mut Buffer,
max_width: u16,
x: u16,
y: u16,
default_style: Style,
) {
// render the label
if let Some(mut label) = self.label {
label.patch_style(default_style);
label.patch_style(default_label_style);
buf.set_line(
x + (max_width.saturating_sub(label.width() as u16) >> 1),
y,
y + 1,
&label,
max_width,
);
Expand Down
9 changes: 4 additions & 5 deletions src/widgets/barchart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ impl<'a> BarChart<'a> {
fn render_labels_and_values(self, area: Rect, buf: &mut Buffer, label_height: u16) {
// print labels and values in one go
let mut bar_x = area.left();
let y_value_offset = area.bottom() - label_height - 1;
let bar_y = area.bottom() - label_height - 1;
for group in self.data.into_iter() {
// print group labels under the bars or the previous labels
if let Some(mut label) = group.label {
Expand All @@ -282,13 +282,12 @@ impl<'a> BarChart<'a> {

// print the bar values and numbers
for bar in group.bars.into_iter() {
bar.render_value(buf, self.bar_width, bar_x, y_value_offset, self.value_style);

bar.render_label(
bar.render_label_and_value(
buf,
self.bar_width,
bar_x,
y_value_offset + 1,
bar_y,
self.value_style,
self.label_style,
);

Expand Down
5 changes: 3 additions & 2 deletions tests/widgets_barchart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ fn widgets_barchart_group() {
.value_style(Style::default().fg(Color::Blue)),
Bar::default()
.value(20)
.style(Style::default().fg(Color::Green)),
.style(Style::default().fg(Color::Green))
.text_value("20M".to_string()),
]),
)
.data(&vec![("C1", 50u64), ("C2", 40u64)])
Expand All @@ -86,7 +87,7 @@ fn widgets_barchart_group() {
"│ ▇▇▇▇ ████ ████│",
"│ ████ ████ ████ ████│",
"│ ▄▄▄▄ ████ ████ ████ ████│",
"│▆10▆ █20█ █50█ █40█ █60█ █90█│",
"│▆10▆ 20M█ █50█ █40█ █60█ █90█│",
"│ C1 C1 C2 C1 C2 │",
"│ Mar │",
"└─────────────────────────────────┘",
Expand Down

0 comments on commit 93161c5

Please sign in to comment.