use std::cmp::min; use strum::{Display, EnumString}; use crate::{ buffer::Buffer, layout::Rect, style::{Style, Styled}, symbols::{self}, widgets::{block::BlockExt, Block, Widget, WidgetRef}, }; /// Widget to render a sparkline over one or more lines. /// /// Each bar in a `Sparkline` represents a value from the provided dataset. The height of the bar /// is determined by the value in the dataset. /// /// You can create a `Sparkline` using [`Sparkline::default`]. /// /// The data is set using [`Sparkline::data`]. The data can be a slice of `u64`, `Option`, or a /// [`SparklineBar`]. For the `Option` and [`SparklineBar`] cases, a data point with a value /// of `None` is interpreted an as the _absence_ of a value. /// /// `Sparkline` can be styled either using [`Sparkline::style`] or preferably using the methods /// provided by the [`Stylize`](crate::style::Stylize) trait. The style may be set for the entire /// widget or for individual bars by setting individual [`SparklineBar::style`]. /// /// The bars are rendered using a set of symbols. The default set is [`symbols::bar::NINE_LEVELS`]. /// You can change the set using [`Sparkline::bar_set`]. /// /// If the data provided is a slice of `u64` or `Option`, the bars will be styled with the /// style of the sparkline. If the data is a slice of [`SparklineBar`], the bars will be /// styled with the style of the sparkline combined with the style provided in the [`SparklineBar`] /// if it is set, otherwise the sparkline style will be used. /// /// Absent values and will be rendered with the style set by [`Sparkline::absent_value_style`] and /// the symbol set by [`Sparkline::absent_value_symbol`]. /// /// # Setter methods /// /// - [`Sparkline::block`] wraps the sparkline in a [`Block`] /// - [`Sparkline::data`] defines the dataset, you'll almost always want to use it /// - [`Sparkline::max`] sets the maximum value of bars /// - [`Sparkline::direction`] sets the render direction /// /// # Examples /// /// ``` /// use ratatui::{ /// style::{Style, Stylize}, /// widgets::{Block, RenderDirection, Sparkline}, /// }; /// /// Sparkline::default() /// .block(Block::bordered().title("Sparkline")) /// .data(&[0, 2, 3, 4, 1, 4, 10]) /// .max(5) /// .direction(RenderDirection::RightToLeft) /// .style(Style::default().red().on_white()) /// .absent_value_style(Style::default().fg(Color::Red)) /// .absent_value_symbol(symbols::shade::FULL); /// ``` #[derive(Debug, Default, Clone, Eq, PartialEq)] pub struct Sparkline<'a> { /// A block to wrap the widget in block: Option>, /// Widget style style: Style, /// Style of absent values absent_value_style: Style, /// The symbol to use for absent values absent_value_symbol: AbsentValueSymbol, /// A slice of the data to display data: Vec, /// The maximum value to take to compute the maximum bar height (if nothing is specified, the /// widget uses the max of the dataset) max: Option, /// A set of bar symbols used to represent the give data bar_set: symbols::bar::Set, /// The direction to render the sparkline, either from left to right, or from right to left direction: RenderDirection, } /// Defines the direction in which sparkline will be rendered. /// /// See [`Sparkline::direction`]. #[derive(Debug, Default, Display, EnumString, Clone, Copy, Eq, PartialEq, Hash)] pub enum RenderDirection { /// The first value is on the left, going to the right #[default] LeftToRight, /// The first value is on the right, going to the left RightToLeft, } impl<'a> Sparkline<'a> { /// Wraps the sparkline with the given `block`. #[must_use = "method moves the value of self and returns the modified value"] pub fn block(mut self, block: Block<'a>) -> Self { self.block = Some(block); self } /// Sets the style of the entire widget. /// /// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or /// your own type that implements [`Into