Skip to main content

oino_ui/widgets/
gauge.rs

1//! ratatui `Gauge` and `LineGauge` (§4.5.1).
2
3use serde::{Deserialize, Serialize};
4
5use crate::node::{Common, IntoNode, Node};
6use crate::style::Style;
7use crate::text::{Line, Span};
8
9/// ratatui `Gauge` (§4.5.1).
10#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct Gauge {
13    /// Common node props (`key`, `style`, `block`, `fallback`).
14    #[serde(flatten)]
15    pub common: Common,
16    /// Fill ratio `0.0..=1.0`.
17    #[serde(default, skip_serializing_if = "Option::is_none")]
18    pub ratio: Option<f64>,
19    /// Percentage shorthand `0..=100`.
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    pub percent: Option<u16>,
22    /// Label (default: the percentage).
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    pub label: Option<Span>,
25    /// Fill style.
26    #[serde(default, skip_serializing_if = "Option::is_none")]
27    pub gauge_style: Option<Style>,
28    /// Use unicode half blocks.
29    #[serde(default, skip_serializing_if = "Option::is_none")]
30    pub use_unicode: Option<bool>,
31}
32
33impl Gauge {
34    /// Empty gauge (`ratio(0.0)`).
35    #[must_use]
36    pub fn new() -> Self {
37        Self {
38            common: Common::new(),
39            ratio: None,
40            percent: None,
41            label: None,
42            gauge_style: None,
43            use_unicode: None,
44        }
45    }
46
47    /// Sets the fill ratio.
48    #[must_use]
49    pub fn ratio(mut self, ratio: f64) -> Self {
50        self.ratio = Some(ratio);
51        self
52    }
53
54    /// Sets the fill percentage.
55    #[must_use]
56    pub fn percent(mut self, percent: u16) -> Self {
57        self.percent = Some(percent);
58        self
59    }
60
61    /// Sets the label.
62    #[must_use]
63    pub fn label(mut self, label: impl Into<Span>) -> Self {
64        self.label = Some(label.into());
65        self
66    }
67
68    /// Sets the fill style.
69    #[must_use]
70    pub fn gauge_style(mut self, style: Style) -> Self {
71        self.gauge_style = Some(style);
72        self
73    }
74
75    /// Uses unicode half blocks.
76    #[must_use]
77    pub fn use_unicode(mut self, use_unicode: bool) -> Self {
78        self.use_unicode = Some(use_unicode);
79        self
80    }
81}
82
83impl Default for Gauge {
84    fn default() -> Self {
85        Self::new()
86    }
87}
88
89impl IntoNode for Gauge {}
90impl From<Gauge> for Node {
91    fn from(g: Gauge) -> Self {
92        Node::Gauge(g)
93    }
94}
95
96/// Line glyph set of a [`LineGauge`].
97#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
98pub enum LineSet {
99    /// `━`.
100    #[default]
101    Normal,
102    /// `█`.
103    Thick,
104    /// `═`.
105    Double,
106}
107
108/// ratatui `LineGauge` (§4.5.1).
109#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct LineGauge {
112    /// Common node props (`key`, `style`, `block`, `fallback`).
113    #[serde(flatten)]
114    pub common: Common,
115    /// Fill ratio `0.0..=1.0`.
116    pub ratio: f64,
117    /// Label line (default: the percentage).
118    #[serde(default, skip_serializing_if = "Option::is_none")]
119    pub label: Option<Line>,
120    /// Filled-part style.
121    #[serde(default, skip_serializing_if = "Option::is_none")]
122    pub filled_style: Option<Style>,
123    /// Unfilled-part style.
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub unfilled_style: Option<Style>,
126    /// Line glyph set.
127    #[serde(default, skip_serializing_if = "Option::is_none")]
128    pub line_set: Option<LineSet>,
129}
130
131impl LineGauge {
132    /// A gauge with the given ratio.
133    #[must_use]
134    pub fn new(ratio: f64) -> Self {
135        Self {
136            common: Common::new(),
137            ratio,
138            label: None,
139            filled_style: None,
140            unfilled_style: None,
141            line_set: None,
142        }
143    }
144
145    /// Sets the label.
146    #[must_use]
147    pub fn label(mut self, label: impl Into<Line>) -> Self {
148        self.label = Some(label.into());
149        self
150    }
151
152    /// Sets the filled-part style.
153    #[must_use]
154    pub fn filled_style(mut self, style: Style) -> Self {
155        self.filled_style = Some(style);
156        self
157    }
158
159    /// Sets the unfilled-part style.
160    #[must_use]
161    pub fn unfilled_style(mut self, style: Style) -> Self {
162        self.unfilled_style = Some(style);
163        self
164    }
165
166    /// Sets the line glyph set.
167    #[must_use]
168    pub fn line_set(mut self, line_set: LineSet) -> Self {
169        self.line_set = Some(line_set);
170        self
171    }
172}
173
174impl Default for LineGauge {
175    fn default() -> Self {
176        Self::new(0.0)
177    }
178}
179
180impl IntoNode for LineGauge {}
181impl From<LineGauge> for Node {
182    fn from(g: LineGauge) -> Self {
183        Node::LineGauge(g)
184    }
185}