feat(barchart): set custom text value in the bar (#309)

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 <hichem.f@live.de>
This commit is contained in:
Hichem 2023-07-14 06:38:54 +02:00 committed by GitHub
parent 2889c7d084
commit 60150f6236
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 30 deletions

View File

@ -57,17 +57,17 @@ impl<'a> App<'a> {
companies: [ companies: [
Company { Company {
label: "Comp.A", label: "Comp.A",
revenue: [9, 12, 5, 8], revenue: [9500, 12500, 5300, 8500],
bar_style: Style::default().fg(Color::Green), bar_style: Style::default().fg(Color::Green),
}, },
Company { Company {
label: "Comp.B", label: "Comp.B",
revenue: [1, 2, 3, 4], revenue: [1500, 2500, 3000, 4100],
bar_style: Style::default().fg(Color::Yellow), bar_style: Style::default().fg(Color::Yellow),
}, },
Company { Company {
label: "Comp.C", label: "Comp.C",
revenue: [10, 10, 9, 4], revenue: [10500, 10600, 9000, 4200],
bar_style: Style::default().fg(Color::White), bar_style: Style::default().fg(Color::White),
}, },
], ],
@ -182,7 +182,8 @@ where
Style::default() Style::default()
.bg(c.bar_style.fg.unwrap()) .bg(c.bar_style.fg.unwrap())
.fg(Color::Black), .fg(Color::Black),
); )
.text_value(format!("{:.1}", (c.revenue[i] as f64) / 1000.));
if bar_labels { if bar_labels {
bar = bar.label(c.label.into()); bar = bar.label(c.label.into());
} }

View File

@ -12,7 +12,8 @@ use crate::{buffer::Buffer, style::Style, text::Line};
/// .label("Bar 1".into()) /// .label("Bar 1".into())
/// .value(10) /// .value(10)
/// .style(Style::default().fg(Color::Red)) /// .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)] #[derive(Debug, Clone, Default)]
pub struct Bar<'a> { pub struct Bar<'a> {
@ -24,6 +25,8 @@ pub struct Bar<'a> {
pub(super) style: Style, pub(super) style: Style,
/// style of the value printed at the bottom of the bar. /// style of the value printed at the bottom of the bar.
pub(super) value_style: Style, 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> { impl<'a> Bar<'a> {
@ -47,43 +50,46 @@ impl<'a> Bar<'a> {
self self
} }
/// render the bar's value /// set the text value printed in the bar. (By default self.value is printed)
pub(super) fn render_value( pub fn text_value(mut self, text_value: String) -> Bar<'a> {
&self, self.text_value = Some(text_value);
self
}
pub(super) fn render_label_and_value(
self,
buf: &mut Buffer, buf: &mut Buffer,
max_width: u16, max_width: u16,
x: u16, x: u16,
y: u16, y: u16,
default_style: Style, default_value_style: Style,
default_label_style: Style,
) { ) {
// render the value
if self.value != 0 { 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; let width = value_label.len() as u16;
if width < max_width { if width < max_width {
buf.set_string( buf.set_string(
x + (max_width.saturating_sub(value_label.len() as u16) >> 1), x + (max_width.saturating_sub(value_label.len() as u16) >> 1),
y, y,
value_label, value_label,
self.value_style.patch(default_style), self.value_style.patch(default_value_style),
); );
} }
} }
}
/// render the bar's label // render the label
pub(super) fn render_label(
self,
buf: &mut Buffer,
max_width: u16,
x: u16,
y: u16,
default_style: Style,
) {
if let Some(mut label) = self.label { if let Some(mut label) = self.label {
label.patch_style(default_style); label.patch_style(default_label_style);
buf.set_line( buf.set_line(
x + (max_width.saturating_sub(label.width() as u16) >> 1), x + (max_width.saturating_sub(label.width() as u16) >> 1),
y, y + 1,
&label, &label,
max_width, max_width,
); );

View File

@ -264,7 +264,7 @@ impl<'a> BarChart<'a> {
fn render_labels_and_values(self, area: Rect, buf: &mut Buffer, label_height: u16) { fn render_labels_and_values(self, area: Rect, buf: &mut Buffer, label_height: u16) {
// print labels and values in one go // print labels and values in one go
let mut bar_x = area.left(); 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() { for group in self.data.into_iter() {
// print group labels under the bars or the previous labels // print group labels under the bars or the previous labels
if let Some(mut label) = group.label { if let Some(mut label) = group.label {
@ -282,13 +282,12 @@ impl<'a> BarChart<'a> {
// print the bar values and numbers // print the bar values and numbers
for bar in group.bars.into_iter() { 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_and_value(
bar.render_label(
buf, buf,
self.bar_width, self.bar_width,
bar_x, bar_x,
y_value_offset + 1, bar_y,
self.value_style,
self.label_style, self.label_style,
); );

View File

@ -63,7 +63,8 @@ fn widgets_barchart_group() {
.value_style(Style::default().fg(Color::Blue)), .value_style(Style::default().fg(Color::Blue)),
Bar::default() Bar::default()
.value(20) .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)]) .data(&vec![("C1", 50u64), ("C2", 40u64)])
@ -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 │", "│ C1 C1 C2 C1 C2 │",
"│ Mar │", "│ Mar │",
"└─────────────────────────────────┘", "└─────────────────────────────────┘",